From 0bb4494ba46d459cbc3becc530017da520d9c66a Mon Sep 17 00:00:00 2001 From: ubbo Date: Sun, 16 Sep 2012 20:47:02 +0000 Subject: merge mac-build-branch with trunk git-svn-id: http://cpunk.de/svn/src/gpg4usb/trunk@957 34ebc366-c3a9-4b3c-9f84-69acf7962910 --- TODO | 4 + TODO.kgpgport | 6 + fileencryptiondialog.cpp | 5 +- gpg4usb.pro | 75 +- gpgcontext.cpp | 214 +- gpgcontext.h | 13 +- keydetailsdialog.cpp | 68 +- keydetailsdialog.h | 11 +- keygendialog.cpp | 46 +- keygendialog.h | 1 + keymgmt.cpp | 89 +- keymgmt.h | 8 +- keyserverimportdialog.cpp | 43 +- keyserverimportdialog.h | 2 +- kgpg/core/KGpgExpandableNode.cpp | 88 + kgpg/core/KGpgExpandableNode.h | 85 + kgpg/core/KGpgGroupMemberNode.cpp | 100 + kgpg/core/KGpgGroupMemberNode.h | 61 + kgpg/core/KGpgGroupNode.cpp | 279 + kgpg/core/KGpgGroupNode.h | 84 + kgpg/core/KGpgKeyNode.cpp | 358 + kgpg/core/KGpgKeyNode.h | 191 + kgpg/core/KGpgNode.cpp | 337 + kgpg/core/KGpgNode.h | 156 + kgpg/core/KGpgOrphanNode.cpp | 84 + kgpg/core/KGpgOrphanNode.h | 53 + kgpg/core/KGpgRefNode.cpp | 151 + kgpg/core/KGpgRefNode.h | 98 + kgpg/core/KGpgRootNode.cpp | 189 + kgpg/core/KGpgRootNode.h | 129 + kgpg/core/KGpgSignNode.cpp | 95 + kgpg/core/KGpgSignNode.h | 54 + kgpg/core/KGpgSignableNode.cpp | 99 + kgpg/core/KGpgSignableNode.h | 62 + kgpg/core/KGpgSubkeyNode.cpp | 100 + kgpg/core/KGpgSubkeyNode.h | 55 + kgpg/core/KGpgUatNode.cpp | 174 + kgpg/core/KGpgUatNode.h | 61 + kgpg/core/KGpgUidNode.cpp | 146 + kgpg/core/KGpgUidNode.h | 57 + kgpg/core/convert.cpp | 183 + kgpg/core/convert.h | 53 + kgpg/core/images.cpp | 100 + kgpg/core/images.h | 47 + kgpg/core/kgpgkey.cpp | 354 + kgpg/core/kgpgkey.h | 327 + kgpg/gpgproc.cpp | 370 ++ kgpg/gpgproc.h | 157 + kgpg/kgpginterface.cpp | 439 ++ kgpg/kgpginterface.h | 52 + kgpg/klinebufferedprocess.cpp | 112 + kgpg/klinebufferedprocess.h | 155 + kgpg/kprocess.cpp | 411 ++ kgpg/kprocess.h | 341 + kgpg/kprocess_p.h | 50 + kgpg/transactions/kgpgdecrypt.cpp | 141 + kgpg/transactions/kgpgdecrypt.h | 86 + kgpg/transactions/kgpgdelkey.cpp | 94 + kgpg/transactions/kgpgdelkey.h | 55 + kgpg/transactions/kgpgencrypt.cpp | 154 + kgpg/transactions/kgpgencrypt.h | 94 + kgpg/transactions/kgpgexport.cpp | 197 + kgpg/transactions/kgpgexport.h | 147 + kgpg/transactions/kgpggeneratekey.cpp | 276 + kgpg/transactions/kgpggeneratekey.h | 99 + kgpg/transactions/kgpgimport.cpp | 295 + kgpg/transactions/kgpgimport.h | 129 + kgpg/transactions/kgpgsigntext.cpp | 118 + kgpg/transactions/kgpgsigntext.h | 98 + kgpg/transactions/kgpgtextorfiletransaction.cpp | 165 + kgpg/transactions/kgpgtextorfiletransaction.h | 109 + kgpg/transactions/kgpgtransaction.cpp | 558 ++ kgpg/transactions/kgpgtransaction.h | 465 ++ kgpg/transactions/kgpgverify.cpp | 204 + kgpg/transactions/kgpgverify.h | 90 + main.cpp | 4 +- mainwindow.cpp | 224 +- mainwindow.h | 20 + release/bin/gpg-mac | Bin 0 -> 2714192 bytes release/ts/gpg4usb_ar.qm | Bin 42163 -> 42269 bytes release/ts/gpg4usb_ar.ts | 21 +- release/ts/gpg4usb_de.ts | 772 +-- release/ts/gpg4usb_en.ts | 29 +- release/ts/gpg4usb_es.ts | 1876 +----- release/ts/gpg4usb_he.qm | Bin 0 -> 39848 bytes release/ts/gpg4usb_he.ts | 1973 ++++++ release/ts/gpg4usb_my.ts | 543 +- release/ts/gpg4usb_pt_BR.ts | 784 +-- release/ts/gpg4usb_ru.qm | Bin 45023 -> 45187 bytes release/ts/gpg4usb_ru.ts | 689 +- release/ts/gpg4usb_sv.qm | Bin 0 -> 43986 bytes release/ts/gpg4usb_sv.ts | 1975 ++++++ release/ts/gpg4usb_vi.ts | 509 +- release/ts/gpg4usb_zh.ts | 157 +- release/ts/gpg4usb_zh_tw.qm | Bin 0 -> 32860 bytes release/ts/gpg4usb_zh_tw.ts | 1975 ++++++ release/ts/qt_linux_he.qm | Bin 0 -> 25666 bytes release/ts/qt_linux_sv.qm | Bin 0 -> 65848 bytes release/ts/qt_linux_zh_TW.qm | Bin 0 -> 117253 bytes release/ts/qt_linux_zh_TW.ts | 8129 +++++++++++++++++++++++ release/ts/qt_windows_he.qm | Bin 0 -> 25666 bytes release/ts/qt_windows_sv.qm | Bin 0 -> 65848 bytes release/ts/qt_windows_zh.qm | Bin 0 -> 117337 bytes release/ts/qt_windows_zh.ts | 7964 ++++++++++++++++++++++ release/ts/qt_windows_zh_TW.qm | Bin 0 -> 117253 bytes release/ts/qt_windows_zh_TW.ts | 8129 +++++++++++++++++++++++ verifydetailsdialog.cpp | 6 +- verifynotification.cpp | 160 +- verifynotification.h | 5 + 109 files changed, 41234 insertions(+), 5366 deletions(-) create mode 100644 TODO.kgpgport create mode 100644 kgpg/core/KGpgExpandableNode.cpp create mode 100644 kgpg/core/KGpgExpandableNode.h create mode 100644 kgpg/core/KGpgGroupMemberNode.cpp create mode 100644 kgpg/core/KGpgGroupMemberNode.h create mode 100644 kgpg/core/KGpgGroupNode.cpp create mode 100644 kgpg/core/KGpgGroupNode.h create mode 100644 kgpg/core/KGpgKeyNode.cpp create mode 100644 kgpg/core/KGpgKeyNode.h create mode 100644 kgpg/core/KGpgNode.cpp create mode 100644 kgpg/core/KGpgNode.h create mode 100644 kgpg/core/KGpgOrphanNode.cpp create mode 100644 kgpg/core/KGpgOrphanNode.h create mode 100644 kgpg/core/KGpgRefNode.cpp create mode 100644 kgpg/core/KGpgRefNode.h create mode 100644 kgpg/core/KGpgRootNode.cpp create mode 100644 kgpg/core/KGpgRootNode.h create mode 100644 kgpg/core/KGpgSignNode.cpp create mode 100644 kgpg/core/KGpgSignNode.h create mode 100644 kgpg/core/KGpgSignableNode.cpp create mode 100644 kgpg/core/KGpgSignableNode.h create mode 100644 kgpg/core/KGpgSubkeyNode.cpp create mode 100644 kgpg/core/KGpgSubkeyNode.h create mode 100644 kgpg/core/KGpgUatNode.cpp create mode 100644 kgpg/core/KGpgUatNode.h create mode 100644 kgpg/core/KGpgUidNode.cpp create mode 100644 kgpg/core/KGpgUidNode.h create mode 100644 kgpg/core/convert.cpp create mode 100644 kgpg/core/convert.h create mode 100644 kgpg/core/images.cpp create mode 100644 kgpg/core/images.h create mode 100644 kgpg/core/kgpgkey.cpp create mode 100644 kgpg/core/kgpgkey.h create mode 100644 kgpg/gpgproc.cpp create mode 100644 kgpg/gpgproc.h create mode 100644 kgpg/kgpginterface.cpp create mode 100644 kgpg/kgpginterface.h create mode 100644 kgpg/klinebufferedprocess.cpp create mode 100644 kgpg/klinebufferedprocess.h create mode 100644 kgpg/kprocess.cpp create mode 100644 kgpg/kprocess.h create mode 100644 kgpg/kprocess_p.h create mode 100644 kgpg/transactions/kgpgdecrypt.cpp create mode 100644 kgpg/transactions/kgpgdecrypt.h create mode 100644 kgpg/transactions/kgpgdelkey.cpp create mode 100644 kgpg/transactions/kgpgdelkey.h create mode 100644 kgpg/transactions/kgpgencrypt.cpp create mode 100644 kgpg/transactions/kgpgencrypt.h create mode 100644 kgpg/transactions/kgpgexport.cpp create mode 100644 kgpg/transactions/kgpgexport.h create mode 100644 kgpg/transactions/kgpggeneratekey.cpp create mode 100644 kgpg/transactions/kgpggeneratekey.h create mode 100644 kgpg/transactions/kgpgimport.cpp create mode 100644 kgpg/transactions/kgpgimport.h create mode 100644 kgpg/transactions/kgpgsigntext.cpp create mode 100644 kgpg/transactions/kgpgsigntext.h create mode 100644 kgpg/transactions/kgpgtextorfiletransaction.cpp create mode 100644 kgpg/transactions/kgpgtextorfiletransaction.h create mode 100644 kgpg/transactions/kgpgtransaction.cpp create mode 100644 kgpg/transactions/kgpgtransaction.h create mode 100644 kgpg/transactions/kgpgverify.cpp create mode 100644 kgpg/transactions/kgpgverify.h create mode 100755 release/bin/gpg-mac create mode 100644 release/ts/gpg4usb_he.qm create mode 100644 release/ts/gpg4usb_he.ts create mode 100644 release/ts/gpg4usb_sv.qm create mode 100644 release/ts/gpg4usb_sv.ts create mode 100644 release/ts/gpg4usb_zh_tw.qm create mode 100644 release/ts/gpg4usb_zh_tw.ts create mode 100644 release/ts/qt_linux_he.qm create mode 100644 release/ts/qt_linux_sv.qm create mode 100644 release/ts/qt_linux_zh_TW.qm create mode 100644 release/ts/qt_linux_zh_TW.ts create mode 100644 release/ts/qt_windows_he.qm create mode 100644 release/ts/qt_windows_sv.qm create mode 100644 release/ts/qt_windows_zh.qm create mode 100644 release/ts/qt_windows_zh.ts create mode 100644 release/ts/qt_windows_zh_TW.qm create mode 100644 release/ts/qt_windows_zh_TW.ts diff --git a/TODO b/TODO index 5f2c5e3..f62045c 100644 --- a/TODO +++ b/TODO @@ -25,6 +25,10 @@ BUGS: Release 0.3.4 - Catch bad passphrase message - add keyless encryption +- create revocation file + - on key generation + - later +- add posibility to add keyserver in settings - set gpgme error language to chosen language (context.cpp:49) - Add default key functionality - encrypt and sign, decrypt and verify (?) diff --git a/TODO.kgpgport b/TODO.kgpgport new file mode 100644 index 0000000..1267f3f --- /dev/null +++ b/TODO.kgpgport @@ -0,0 +1,6 @@ +TODO: +- central import, move code duplication from keymgmt, mainwindow and keyserverimport to central place, e.g. keyimportdetaildialog +-reactivate keyimportdetaildialog +- sign should work for more than one secret keyid +- why is listkeys called so often (twice?) +- signverify on one button like kgpg? diff --git a/fileencryptiondialog.cpp b/fileencryptiondialog.cpp index 88f73a8..af05a24 100755 --- a/fileencryptiondialog.cpp +++ b/fileencryptiondialog.cpp @@ -193,9 +193,10 @@ void FileEncryptionDialog::executeAction() if (! mCtx->decrypt(inBuffer, outBuffer)) return; } - if( mAction == Sign ) { + // TODO: with kgpg + /*if( mAction == Sign ) { if(! mCtx->sign(mKeyList->getChecked(), inBuffer, outBuffer, true)) return; - } + }*/ if( mAction == Verify ) { QFile signfile; diff --git a/gpg4usb.pro b/gpg4usb.pro index 3b7a682..646be19 100644 --- a/gpg4usb.pro +++ b/gpg4usb.pro @@ -14,7 +14,9 @@ INCLUDEPATH += . \ #DEFINES += GPG4USB_NON_PORTABLE #CONFIG += release static +#CONFIG += release CONFIG += debug + QT += network # Input HEADERS += attachments.h \ @@ -40,7 +42,41 @@ HEADERS += attachments.h \ verifykeydetailbox.h \ wizard.h \ helppage.h \ - gpgconstants.h + gpgconstants.h \ + kgpg/gpgproc.h \ + kgpg/klinebufferedprocess.h \ + kgpg/kprocess.h \ + kgpg/kprocess_p.h \ + kgpg/kgpginterface.h \ + kgpg/core/kgpgkey.h \ + kgpg/core/KGpgSignableNode.h \ + kgpg/core/KGpgExpandableNode.h \ + kgpg/core/KGpgSignNode.h \ + kgpg/core/KGpgUidNode.h \ + kgpg/core/KGpgUatNode.h \ + kgpg/core/KGpgKeyNode.h \ + kgpg/core/KGpgSubKeyNode.h \ + kgpg/core/KGpgNode.h \ + kgpg/core/KGpgRefNode.h \ + kgpg/core/KGpgRootNode.h \ + kgpg/core/KGpgGroupNode.h \ + kgpg/core/KGpgGroupMemberNode.h \ + kgpg/core/KGpgOrphanNode.h \ + kgpg/core/convert.h \ + kgpg/core/images.h \ + kgpg/transactions/kgpgtransaction.h \ + kgpg/transactions/kgpgtextorfiletransaction.h \ + kgpg/transactions/kgpgencrypt.h \ + kgpg/transactions/kgpgdecrypt.h \ + kgpg/transactions/kgpgexport.h \ + kgpg/transactions/kgpgimport.h \ + kgpg/transactions/kgpgdelkey.h \ + kgpg/transactions/kgpggeneratekey.h \ + kgpg/transactions/kgpgsigntext.h \ + kgpg/transactions/kgpgverify.h \ + #kgpg/model/kgpgitemmodel.h \ + #kgpg/model/kgpgitemnode.h + SOURCES += attachments.cpp \ gpgcontext.cpp \ @@ -66,7 +102,38 @@ SOURCES += attachments.cpp \ verifykeydetailbox.cpp \ wizard.cpp \ helppage.cpp \ - gpgconstants.cpp + gpgconstants.cpp \ + kgpg/gpgproc.cpp \ + kgpg/klinebufferedprocess.cpp \ + kgpg/kprocess.cpp \ + kgpg/kgpginterface.cpp \ + kgpg/core/kgpgkey.cpp \ + kgpg/core/KGpgSignableNode.cpp \ + kgpg/core/KGpgExpandableNode.cpp \ + kgpg/core/KGpgSignNode.cpp \ + kgpg/core/KGpgUidNode.cpp \ + kgpg/core/KGpgUatNode.cpp \ + kgpg/core/KGpgKeyNode.cpp \ + kgpg/core/KGpgSubKeyNode.cpp \ + kgpg/core/KGpgNode.cpp \ + kgpg/core/KGpgRefNode.cpp \ + kgpg/core/KGpgRootNode.cpp \ + kgpg/core/KGpgGroupNode.cpp \ + kgpg/core/KGpgGroupMemberNode.cpp \ + kgpg/core/KGpgOrphanNode.cpp \ + kgpg/core/convert.cpp \ + kgpg/core/images.cpp \ + kgpg/transactions/kgpgtransaction.cpp \ + kgpg/transactions/kgpgtextorfiletransaction.cpp \ + kgpg/transactions/kgpgencrypt.cpp \ + kgpg/transactions/kgpgdecrypt.cpp \ + kgpg/transactions/kgpgexport.cpp \ + kgpg/transactions/kgpgimport.cpp \ + kgpg/transactions/kgpgdelkey.cpp \ + kgpg/transactions/kgpggeneratekey.cpp \ + kgpg/transactions/kgpgsigntext.cpp \ + kgpg/transactions/kgpgverify.cpp \ + #kgpg/model/kgpgitemmodel.cpp RC_FILE = gpg4usb.rc @@ -80,6 +147,9 @@ LIBS += -lgpgme \ #INCLUDEPATH += ./winbuild/include #LIBS +=./winbuild/lib/libgpgme.a ./winbuild/lib/libgpg-error.a +#INCLUDEPATH += ./macbuild/include +#LIBS +=./macbuild/lib/libgpgme.a ./macbuild/lib/libgpg-error.a + DEFINES += _FILE_OFFSET_BITS=64 TRANSLATIONS = release/ts/gpg4usb_en.ts \ @@ -91,6 +161,7 @@ TRANSLATIONS = release/ts/gpg4usb_en.ts \ release/ts/gpg4usb_vi.ts \ release/ts/gpg4usb_my.ts \ release/ts/gpg4usb_zh.ts \ + release/ts/gpg4usb_zh_tw.ts \ release/ts/gpg4usb_ar.ts diff --git a/gpgcontext.cpp b/gpgcontext.cpp index 7d0fbf2..2d98372 100644 --- a/gpgcontext.cpp +++ b/gpgcontext.cpp @@ -20,7 +20,11 @@ */ #include "gpgcontext.h" - +#include "kgpg/gpgproc.h" +#include "kgpg/kgpginterface.h" +#include "kgpg/klinebufferedprocess.h" +#include "kgpg/core/kgpgkey.h" +#include "kgpg/transactions/kgpgencrypt.h" #ifdef _WIN32 #include #include /* contains read/write */ @@ -41,80 +45,35 @@ GpgContext::GpgContext() /** The function `gpgme_check_version' must be called before any other * function in the library, because it initializes the thread support * subsystem in GPGME. (from the info page) */ - gpgme_check_version(NULL); - - // TODO: Set gpgme_language to config - /*QSettings settings; - qDebug() << " - " << settings.value("int/lang").toLocale().name(); - qDebug() << " - " << QLocale(settings.value("int/lang").toString()).name();*/ - // the locale set here is used for the other setlocale calls which have NULL - // -> NULL means use default, which is configured here - setlocale(LC_ALL, ""); - - /** set locale, because tests do also */ - gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL)); - //qDebug() << "Locale set to" << LC_CTYPE << " - " << setlocale(LC_CTYPE, NULL); -#ifndef _WIN32 - gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL)); +#ifdef Q_WS_WIN + gpgBin = appPath + "/bin/gpg.exe"; + gpgKeys = appPath + "/keydb"; #endif +#ifdef Q_WS_MAC + gpgBin = appPath + "/bin/gpg-mac.app"; - err = gpgme_new(&mCtx); + gpgKeys = appPath + "/keydb"; - checkErr(err); - /** here come the settings, instead of /usr/bin/gpg - * a executable in the same path as app is used. - * also lin/win must be checked, for calling gpg.exe if needed - */ -#ifdef _WIN32 - QString gpgBin = appPath + "/bin/gpg.exe"; -#else - QString gpgBin = appPath + "/bin/gpg"; + qDebug() << "gpg bin:" << gpgBin; + qDebug() << "gpg keydb: " << gpgKeys; #endif - - QSettings settings; - QString accKeydbPath = settings.value("gpgpaths/keydbpath").toString(); - QString gpgKeys = appPath + "/keydb/"+accKeydbPath; - - if (accKeydbPath != "") { - if (!QDir(gpgKeys).exists()) { - QMessageBox::critical(0,tr("keydb path"),tr("Didn't find keydb directory. Switching to gpg4usb's default keydb directory for this session.")); - gpgKeys = appPath + "/keydb"; - } - } - - /* err = gpgme_ctx_set_engine_info(mCtx, GPGME_PROTOCOL_OpenPGP, - gpgBin.toUtf8().constData(), - gpgKeys.toUtf8().constData());*/ -#ifndef GPG4USB_NON_PORTABLE - err = gpgme_ctx_set_engine_info(mCtx, GPGME_PROTOCOL_OpenPGP, - gpgBin.toLocal8Bit().constData(), - gpgKeys.toLocal8Bit().constData()); - checkErr(err); +#ifdef Q_WS_X11 + gpgBin = appPath + "/bin/gpg"; + gpgKeys = appPath + "/keydb"; #endif - gpgme_engine_info_t engineInfo; - engineInfo = gpgme_ctx_get_engine_info(mCtx); + QStringList args; + args << "--homedir" << gpgKeys << "--list-keys"; - while (engineInfo !=NULL ) { - qDebug() << gpgme_get_protocol_name(engineInfo->protocol); - engineInfo=engineInfo->next; - } +/* QProcess gpg; + gpg.setProcessChannelMode(QProcess::MergedChannels); + gpg.start(gpgBin, args); - /** Setting the output type must be done at the beginning */ - /** think this means ascii-armor --> ? */ - gpgme_set_armor(mCtx, 1); - /** passphrase-callback */ - gpgme_set_passphrase_cb(mCtx, passphraseCb, this); - - /** check if app is called with -d from command line */ - if (qApp->arguments().contains("-d")) { - qDebug() << "gpgme_data_t debug on"; - debug = true; - } else { - debug = false; - } + gpg.waitForFinished(-1); + qDebug() << "huhu" << gpg.readAll(); +*/ connect(this,SIGNAL(keyDBChanged()),this,SLOT(refreshKeyList())); refreshKeyList(); } @@ -124,8 +83,8 @@ GpgContext::GpgContext() */ GpgContext::~GpgContext() { - if (mCtx) gpgme_release(mCtx); - mCtx = 0; + //if (mCtx) gpgme_release(mCtx); + //mCtx = 0; } /** Import Key from QByteArray @@ -236,67 +195,62 @@ bool GpgContext::exportKeys(QStringList *uidList, QByteArray *outBuffer) return true; } -gpgme_key_t GpgContext::getKeyDetails(QString uid) -{ - gpgme_key_t key; +KgpgCore::KgpgKey GpgContext::getKeyDetails(QString uid) { + // try secret - gpgme_get_key(mCtx, uid.toAscii().constData(), &key, 1); - // ok, its a public key - if (!key) { - gpgme_get_key(mCtx, uid.toAscii().constData(), &key, 0); + KgpgCore::KgpgKeyList keys = KgpgInterface::readSecretKeys(QStringList() << uid); + if(keys.empty()) { + // ok try public + keys = KgpgInterface::readPublicKeys(QStringList() << uid); + // that should not happen + /*if(keys.empty()) { + qDebug() << "error, no key with uid" << uid; + return ; + }*/ + } + + KgpgCore::KgpgKey key = keys.first(); return key; + } + + /** List all availabe Keys (VERY much like kgpgme) */ GpgKeyList GpgContext::listKeys() { - gpgme_error_t err; - gpgme_key_t key; - GpgKeyList keys; - //TODO dont run the loop more often than necessary - // list all keys ( the 0 is for all ) - err = gpgme_op_keylist_start(mCtx, NULL, 0); - checkErr(err); - while (!(err = gpgme_op_keylist_next(mCtx, &key))) { - GpgKey gpgkey; + KgpgInterface::readPublicKeys(); - if (!key->subkeys) - continue; - gpgkey.id = key->subkeys->keyid; - gpgkey.fpr = key->subkeys->fpr; - gpgkey.expired = (key->expired != 0); - gpgkey.revoked = (key->revoked != 0); + GpgKeyList keys; + KgpgCore::KgpgKeyList kl = KgpgInterface::readPublicKeys(); - if (key->uids) { - gpgkey.name = QString::fromUtf8(key->uids->name); - gpgkey.email = QString::fromUtf8(key->uids->email); - } - keys.append(gpgkey); - gpgme_key_unref(key); + foreach(KgpgCore::KgpgKey kkey, kl) { + GpgKey key; + key.email = kkey.email(); + //key.expired = kkey.expirationDate().toString(); + key.expired = false; + key.fpr = kkey.fingerprint(); + key.id = kkey.id(); + key.name = kkey.name(); + key.revoked = false; + keys.append(key); } - gpgme_op_keylist_end(mCtx); - // list only private keys ( the 1 does ) - gpgme_op_keylist_start(mCtx, NULL, 1); - while (!(err = gpgme_op_keylist_next(mCtx, &key))) { - if (!key->subkeys) - continue; + foreach(KgpgCore::KgpgKey skey, KgpgInterface::readSecretKeys()) { // iterate keys, mark privates GpgKeyList::iterator it = keys.begin(); while (it != keys.end()) { - if (key->subkeys->keyid == it->id.toStdString()) + if (skey.id() == it->id) { it->privkey = true; + } it++; } - - gpgme_key_unref(key); } - gpgme_op_keylist_end(mCtx); return keys; } @@ -324,7 +278,7 @@ void GpgContext::deleteKeys(QStringList *uidList) bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer) { - gpgme_data_t in = 0, out = 0; + /*gpgme_data_t in = 0, out = 0; outBuffer->resize(0); if (uidList->count() == 0) { @@ -335,7 +289,7 @@ bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByte //gpgme_encrypt_result_t e_result; gpgme_key_t recipients[uidList->count()+1]; - /* get key for user */ + // get key for user for (int i = 0; i < uidList->count(); i++) { // the last 0 is for public keys, 1 would return private keys gpgme_op_keylist_start(mCtx, uidList->at(i).toAscii().constData(), 0); @@ -362,7 +316,7 @@ bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByte } } } - /* unref all keys */ + // unref all keys for (int i = 0; i <= uidList->count(); i++) { gpgme_key_unref(recipients[i]); } @@ -372,9 +326,17 @@ bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByte if (out) { gpgme_data_release(out); } - return (err == GPG_ERR_NO_ERROR); + return (err == GPG_ERR_NO_ERROR);*/ + QStringList options; + KGpgEncrypt::EncryptOptions opts = KGpgEncrypt::DefaultEncryption; + + //KGpgEncrypt *encr = new KGpgEncrypt(this, uidList, toPlainText(), opts, options); + //encr->start(); + //connect(encr, SIGNAL(done(int)), SLOT(slotEncodeUpdate(int))); } + + /** Decrypt QByteAarray, return QByteArray * mainly from http://basket.kde.org/ (kgpgme.cpp) */ @@ -609,14 +571,12 @@ void GpgContext::executeGpgCommand(QStringList arguments, QByteArray *stdOut, QB } /*** - * if sigbuffer not set, the inbuffer should contain signed text - * * TODO: return type should contain: * -> list of sigs * -> valid * -> errors */ -gpgme_signature_t GpgContext::verify(QByteArray *inBuffer, QByteArray *sigBuffer) { +gpgme_signature_t GpgContext::verify(QByteArray inBuffer) { int error=0; gpgme_data_t in; @@ -624,16 +584,10 @@ gpgme_signature_t GpgContext::verify(QByteArray *inBuffer, QByteArray *sigBuffer gpgme_signature_t sign; gpgme_verify_result_t result; - err = gpgme_data_new_from_mem(&in, inBuffer->data(), inBuffer->size(), 1); + err = gpgme_data_new_from_mem(&in, inBuffer.data(), inBuffer.size(), 1); checkErr(err); - if (sigBuffer != NULL ) { - gpgme_data_t sigdata; - err = gpgme_data_new_from_mem(&sigdata, sigBuffer->data(), sigBuffer->size(), 1); - err = gpgme_op_verify (mCtx, sigdata, in, NULL); - } else { - err = gpgme_op_verify (mCtx, in, NULL, in); - } + err = gpgme_op_verify (mCtx, in, NULL, in); error = checkErr(err); if (error != 0) { @@ -666,12 +620,11 @@ gpgme_signature_t GpgContext::verify(QByteArray *inBuffer, QByteArray *sigBuffer */ //} -bool GpgContext::sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached ) { +bool GpgContext::sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer ) { gpgme_error_t err; gpgme_data_t in, out; gpgme_sign_result_t result; - gpgme_sig_mode_t mode; if (uidList->count() == 0) { QMessageBox::critical(0, tr("Key Selection"), tr("No Private Key Selected")); @@ -714,13 +667,7 @@ bool GpgContext::sign(QStringList *uidList, const QByteArray &inBuffer, QByteArr mode settings of the context are ignored. */ - if(detached) { - mode = GPGME_SIG_MODE_DETACH; - } else { - mode = GPGME_SIG_MODE_CLEAR; - } - - err = gpgme_op_sign (mCtx, in, out, mode); + err = gpgme_op_sign (mCtx, in, out, GPGME_SIG_MODE_CLEAR); checkErr (err); if (err == GPG_ERR_CANCELED) { @@ -739,6 +686,10 @@ bool GpgContext::sign(QStringList *uidList, const QByteArray &inBuffer, QByteArr gpgme_data_release(in); gpgme_data_release(out); + if (! settings.value("general/rememberPassword").toBool()) { + clearPasswordCache(); + } + return (err == GPG_ERR_NO_ERROR); } @@ -822,9 +773,14 @@ QString GpgContext::getGpgmeVersion() { return QString(gpgme_check_version(NULL)); } +void GpgContext::emitKeyDBChanged() { + emit keyDBChanged(); +} + } + diff --git a/gpgcontext.h b/gpgcontext.h index cdb522d..388c957 100644 --- a/gpgcontext.h +++ b/gpgcontext.h @@ -28,6 +28,7 @@ #include #include #include +#include "kgpg/core/kgpgkey.h" QT_BEGIN_NAMESPACE class QMessageBox; @@ -118,10 +119,11 @@ public: bool decrypt(const QByteArray &inBuffer, QByteArray *outBuffer); void clearPasswordCache(); void exportSecretKey(QString uid, QByteArray *outBuffer); - gpgme_key_t getKeyDetails(QString uid); - gpgme_signature_t verify(QByteArray *inBuffer, QByteArray *sigBuffer = NULL); + //gpgme_key_t getKeyDetails(QString uid); + KgpgCore::KgpgKey getKeyDetails(QString uid); + gpgme_signature_t verify(QByteArray in); // void decryptVerify(QByteArray in); - bool sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached = false ); + bool sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer ); /** * @details If text contains PGP-message, put a linebreak before the message, * so that gpgme can decrypt correctly @@ -133,6 +135,8 @@ public: GpgKey getKeyByFpr(QString fpr); GpgKey getKeyById(QString id); + void emitKeyDBChanged(); + static QString gpgErrString(gpgme_error_t err); static QString getGpgmeVersion(); @@ -176,6 +180,9 @@ private: QByteArray *stdOut, QByteArray *stdErr); + QString gpgBin; + QString gpgKeys; + }; } // namespace GpgME diff --git a/keydetailsdialog.cpp b/keydetailsdialog.cpp index 5a66122..fb6edf6 100644 --- a/keydetailsdialog.cpp +++ b/keydetailsdialog.cpp @@ -20,12 +20,13 @@ */ #include "keydetailsdialog.h" +#include "kgpg/transactions/kgpgexport.h" -KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWidget *parent) +KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, KgpgCore::KgpgKey key, QWidget *parent) : QDialog(parent) { mCtx = ctx; - keyid = new QString(key->subkeys->keyid); + keyid = new QString(key.id()); ownerBox = new QGroupBox(tr("Owner details")); keyBox = new QGroupBox(tr("Key details")); @@ -34,29 +35,29 @@ KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWid buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); - nameVarLabel = new QLabel(QString::fromUtf8(key->uids->name)); + nameVarLabel = new QLabel(key.name()); nameVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - emailVarLabel = new QLabel(QString::fromUtf8(key->uids->email)); + emailVarLabel = new QLabel(key.email()); emailVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - commentVarLabel = new QLabel(QString::fromUtf8(key->uids->comment)); + commentVarLabel = new QLabel(key.comment()); commentVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - keyidVarLabel = new QLabel(key->subkeys->keyid); + keyidVarLabel = new QLabel(key.id()); keyidVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); QString keySizeVal, keyExpireVal, keyCreatedVal, keyAlgoVal; - if (key->subkeys->expires == 0) { + if (key.expirationDate().isNull()) { keyExpireVal = tr("Never"); } else { - keyExpireVal = QDateTime::fromTime_t(key->subkeys->expires).toString("dd. MMM. yyyy"); + keyExpireVal = key.expirationDate().toString("dd. MMM. yyyy"); } - keyAlgoVal = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo); - keyCreatedVal = QDateTime::fromTime_t(key->subkeys->timestamp).toString("dd. MMM. yyyy"); + keyAlgoVal = key.algorithm(); + keyCreatedVal = key.creationDate().toString("dd. MMM. yyyy"); // have el-gamal key? - if (key->subkeys->next) { + /*if (key->subkeys->next) { keySizeVal.sprintf("%d / %d", int(key->subkeys->length), int(key->subkeys->next->length)); if (key->subkeys->next->expires == 0) { keyExpireVal += tr(" / Never"); @@ -67,7 +68,7 @@ KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWid keyCreatedVal += " / " + QDateTime::fromTime_t(key->subkeys->next->timestamp).toString("dd. MMM. yyyy"); } else { keySizeVal.setNum(int(key->subkeys->length)); - } + }*/ keySizeVarLabel = new QLabel(keySizeVal); expireVarLabel = new QLabel(keyExpireVal); @@ -102,7 +103,7 @@ KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWid keyBox->setLayout(vboxKD); mvbox->addWidget(keyBox); - fingerPrintVarLabel = new QLabel(beautifyFingerprint(key->subkeys->fpr)); + fingerPrintVarLabel = new QLabel(key.fingerprintBeautified()); fingerPrintVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); fingerPrintVarLabel->setStyleSheet("margin-left: 20; margin-right: 20;"); QHBoxLayout *hboxFP = new QHBoxLayout(); @@ -122,7 +123,7 @@ KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWid mvbox->addWidget(fingerprintBox); // If key has more than primary uid, also show the other uids - gpgme_user_id_t addUserIds = key->uids->next; + /*gpgme_user_id_t addUserIds = key->uids->next; if (addUserIds !=NULL) { QVBoxLayout *vboxUID = new QVBoxLayout(); while (addUserIds != NULL){ @@ -133,9 +134,9 @@ KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWid } additionalUidBox->setLayout(vboxUID); mvbox->addWidget(additionalUidBox); - } + }*/ - if (key->secret) { + if (key.secret()) { QGroupBox *privKeyBox = new QGroupBox(tr("Private Key")); QVBoxLayout *vboxPK = new QVBoxLayout(); @@ -147,7 +148,7 @@ KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWid mvbox->addWidget(privKeyBox); } - if((key->expired) || (key->revoked)) { + /*if((key->expired) || (key->revoked)) { QHBoxLayout *expBox = new QHBoxLayout(); QIcon icon = QIcon::fromTheme("dialog-warning"); QPixmap pixmap = icon.pixmap(QSize(32,32),QIcon::Normal,QIcon::On); @@ -168,7 +169,7 @@ KeyDetailsDialog::KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWid expBox->addWidget(iconLabel); expBox->addWidget(expLabel); mvbox->addLayout(expBox); - } + }*/ mvbox->addWidget(buttonBox); @@ -192,10 +193,10 @@ void KeyDetailsDialog::exportPrivateKey() // export key, if ok was clicked if (ret == QMessageBox::Ok) { - QByteArray *keyArray = new QByteArray(); + /* QByteArray *keyArray = new QByteArray(); mCtx->exportSecretKey(*keyid, keyArray); - gpgme_key_t key = mCtx->getKeyDetails(*keyid); - QString fileString = QString::fromUtf8(key->uids->name) + " " + QString::fromUtf8(key->uids->email) + "(" + QString(key->subkeys->keyid)+ ")_pub_sec.asc"; + KgpgCore::KgpgKey key = mCtx->getKeyDetails(*keyid); + QString fileString = key.name() + " " + key.email() + "(" + key.id()+ ")_pub_sec.asc"; QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, tr("Key Files") + " (*.asc *.txt);;All Files (*)"); QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -205,10 +206,33 @@ void KeyDetailsDialog::exportPrivateKey() QTextStream stream(&file); stream << *keyArray; file.close(); - delete keyArray; + delete keyArray;*/ + KgpgCore::KgpgKey key = mCtx->getKeyDetails(*keyid); + QString fileString = key.name() + " " + key.email() + "(" + key.id()+ ")_pub_sec.asc"; + + QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, tr("Key Files") + " (*.asc *.txt);;All Files (*)"); + + QStringList expopts; + expopts.append(QLatin1String( "--armor" )); + KGpgExport *exp = new KGpgExport(this, QStringList() << *keyid, fileName, expopts, true); + connect(exp, SIGNAL(done(int)), SLOT(slotExportPrivateKeyDone(int))); + exp->start(); } } +void KeyDetailsDialog::slotExportPrivateKeyDone(int result) { + KGpgExport *exp = qobject_cast(sender()); + Q_ASSERT(exp != NULL); + + if (result == KGpgTransaction::TS_OK) { + qDebug() << "export seems ok"; + } else { + qDebug() << "Your key could not be exported\nCheck the key."; + } + + exp->deleteLater(); +} + QString KeyDetailsDialog::beautifyFingerprint(QString fingerprint) { uint len = fingerprint.length(); diff --git a/keydetailsdialog.h b/keydetailsdialog.h index 1079801..8863553 100644 --- a/keydetailsdialog.h +++ b/keydetailsdialog.h @@ -23,6 +23,7 @@ #define __KEYDETAILSDIALOG_H__ #include "gpgcontext.h" +#include "kgpg/core/kgpgkey.h" #include QT_BEGIN_NAMESPACE @@ -42,14 +43,7 @@ class KeyDetailsDialog : public QDialog Q_OBJECT public: - /** - * @details Constructor of this class - * - * @param ctx The current GpgME context - * @param key The key to show details of - * @param parent The parent of this widget - */ - KeyDetailsDialog(GpgME::GpgContext* ctx, gpgme_key_t key, QWidget *parent = 0); + KeyDetailsDialog(GpgME::GpgContext* ctx, KgpgCore::KgpgKey key, QWidget *parent = 0); /** * @details Return QString with a space inserted at every fourth character @@ -63,6 +57,7 @@ private slots: * @details Export the key to a file, which is choosen in a file dialog */ void exportPrivateKey(); + void slotExportPrivateKeyDone(int result); /** * @details Copy the fingerprint to clipboard diff --git a/keygendialog.cpp b/keygendialog.cpp index 998fa27..0778b0c 100644 --- a/keygendialog.cpp +++ b/keygendialog.cpp @@ -27,6 +27,7 @@ KeyGenDialog::KeyGenDialog(GpgME::GpgContext *ctx, QWidget *parent) { mCtx = ctx; buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + this->setWindowTitle(tr("Generate Key")); this->setModal(true); generateKeyDialog(); @@ -42,7 +43,6 @@ void KeyGenDialog::generateKeyDialog() keySizeSpinBox = new QSpinBox(this); keySizeSpinBox->setRange(768, 16384); keySizeSpinBox->setValue(2048); - this->lastKeySize=2048; keySizeSpinBox->setSingleStep(256); @@ -132,24 +132,13 @@ void KeyGenDialog::keyGenAccept() /** * create the string for key generation */ - - if (keyTypeComboBox->currentText() == "RSA") { - keyGenParams = "\n" - "Key-Type: RSA\n" - "Key-Usage: sign\n" - "Key-Length: " + keySizeSpinBox->cleanText() + "\n" - "Subkey-Type: RSA\n" - "Subkey-Length: " + keySizeSpinBox->cleanText() + "\n" - "Subkey-Usage: encrypt\n"; - } else { - keyGenParams = "\n" - "Key-Type: DSA\n" - "Key-Length: " + keySizeSpinBox->cleanText() + "\n" - "Subkey-Type: ELG-E\n" - "Subkey-Length: " - + keySizeSpinBox->cleanText() + "\n"; - } - keyGenParams += "Name-Real: " + nameEdit->text().toUtf8() + "\n"; + /*keyGenParams = "\n" + "Key-Type: DSA\n" + "Key-Length: 1024\n" + "Subkey-Type: ELG-E\n" + "Subkey-Length: " + + keySizeSpinBox->cleanText() + "\n" + "Name-Real: " + nameEdit->text().toUtf8() + "\n"; if (!(commentEdit->text().isEmpty())) { keyGenParams += "Name-Comment: " + commentEdit->text().toUtf8() + "\n"; } @@ -167,7 +156,20 @@ void KeyGenDialog::keyGenAccept() keyGenParams += ""; KeyGenThread *kg = new KeyGenThread(keyGenParams, mCtx); - kg->start(); + kg->start();*/ + + + // TODO: expdate + KGpgGenerateKey *genkey = new KGpgGenerateKey(this, + nameEdit->text(), + emailEdit->text(), + commentEdit->text(), + KgpgCore::ALGO_RSA_RSA, + keySizeSpinBox->cleanText().toInt(), + 0, + 'd'); + + genkey->start(); this->accept(); @@ -186,7 +188,9 @@ void KeyGenDialog::keyGenAccept() dialog->show(); - while (kg->isRunning()) { + //genkey->thread()->isRunning() + + while (genkey->thread()->isRunning()) { QCoreApplication::processEvents(); } diff --git a/keygendialog.h b/keygendialog.h index 6d264c1..fb661c3 100644 --- a/keygendialog.h +++ b/keygendialog.h @@ -24,6 +24,7 @@ #include "keygenthread.h" #include "gpgcontext.h" +#include "kgpg/transactions/kgpggeneratekey.h" #include QT_BEGIN_NAMESPACE diff --git a/keymgmt.cpp b/keymgmt.cpp index 8bfc8c5..be17e48 100755 --- a/keymgmt.cpp +++ b/keymgmt.cpp @@ -155,26 +155,61 @@ void KeyMgmt::createToolBars() } -void KeyMgmt::importKeys(QByteArray inBuffer) + +// import for text based keys +void KeyMgmt::importKeys(QString text) +{ + KGpgImport *imp = new KGpgImport(this, text); + connect(imp, SIGNAL(done(int)), SLOT(slotImportDone(int))); + imp->start(); +} + +void KeyMgmt::slotImportDone(int result) { - GpgImportInformation result = mCtx->importKey(inBuffer); - new KeyImportDetailDialog(mCtx, result, this); + KGpgImport *import = qobject_cast(sender()); + Q_ASSERT(import != NULL); + const QStringList rawmsgs(import->getMessages()); + + if (result != 0) { + /*KMessageBox::detailedSorry(this, i18n("Key importing failed. Please see the detailed log for more information."), + rawmsgs.join( QLatin1String( "\n")) , i18n("Key Import" ));*/ + qDebug() << "Key importing failed. Please see the detailed log for more information." << rawmsgs.join( QLatin1String( "\n")); + } + + QStringList keys(import->getImportedIds(0x1f)); + const bool needsRefresh = !keys.isEmpty(); + keys << import->getImportedIds(0); +/* + if (!keys.isEmpty()) { + const QString msg(import->getImportMessage()); + const QStringList keynames(import->getImportedKeys()); + + new KgpgDetailedInfo(this, msg, rawmsgs.join( QLatin1String( "\n") ), keynames, i18n("Key Import" )); + if (needsRefresh) + imodel->refreshKeys(keys); + else + changeMessage(i18nc("Application ready for user input", "Ready")); + } else{ + changeMessage(i18nc("Application ready for user input", "Ready")); + } +*/ + //changeMessage(tr("Application ready for user input", "Ready")); + mCtx->emitKeyDBChanged(); + import->deleteLater(); } void KeyMgmt::importKeyFromFile() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open Key"), "", tr("Key Files") + " (*.asc *.txt);;"+tr("Keyring files")+" (*.gpg);;All Files (*)"); if (! fileName.isNull()) { - QFile file; - file.setFileName(fileName); - if (!file.open(QIODevice::ReadOnly)) { - qDebug() << tr("Couldn't Open File: ") + fileName; - return; - } - QByteArray inBuffer = file.readAll(); - importKeys(inBuffer); - file.close(); + + QList urlList; + urlList << QUrl::fromLocalFile(fileName); + + KGpgImport *imp = new KGpgImport(this, urlList); + connect(imp, SIGNAL(done(int)), SLOT(slotImportDone(int))); + imp->start(); } } @@ -212,9 +247,9 @@ void KeyMgmt::deleteKeysWithWarning(QStringList *uidList) } QString keynames; foreach (QString uid, *uidList) { - keynames.append(QString::fromUtf8(mCtx->getKeyDetails(uid)->uids->name)); + keynames.append(mCtx->getKeyDetails(uid).name()); keynames.append(" <"); - keynames.append(QString::fromUtf8(mCtx->getKeyDetails(uid)->uids->email)); + keynames.append(mCtx->getKeyDetails(uid).email()); keynames.append(">
"); } @@ -224,10 +259,28 @@ void KeyMgmt::deleteKeysWithWarning(QStringList *uidList) QMessageBox::No | QMessageBox::Yes); if (ret == QMessageBox::Yes) { - mCtx->deleteKeys(uidList); + //mCtx->deleteKeys(uidList); + KGpgDelKey *delkey = new KGpgDelKey(this, *uidList); + connect(delkey, SIGNAL(done(int)), SLOT(slotKeyDeleted(int))); + delkey->start(); } } +void KeyMgmt::slotKeyDeleted(int retcode) +{ + KGpgDelKey *delkey = qobject_cast(sender()); + + /*KGpgKeyNode *delkey = m_delkey->keys().first(); + if (retcode == 0) { + KMessageBox::information(this, i18n("Key %1 deleted.", delkey->getBeautifiedFingerprint()), i18n("Delete key")); + imodel->delNode(delkey); + } else { + KMessageBox::error(this, i18n("Deleting key %1 failed.", delkey->getBeautifiedFingerprint()), i18n("Delete key")); + }*/ + mCtx->emitKeyDBChanged(); + delkey->deleteLater(); +} + void KeyMgmt::showKeyDetails() { if (mKeyList->getSelected()->isEmpty()) { @@ -235,7 +288,7 @@ void KeyMgmt::showKeyDetails() } // TODO: first...? - gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getSelected()->first()); + KgpgCore::KgpgKey key = mCtx->getKeyDetails(mKeyList->getSelected()->first()); new KeyDetailsDialog(mCtx, key); } @@ -246,8 +299,8 @@ void KeyMgmt::exportKeyToFile() if (!mCtx->exportKeys(mKeyList->getChecked(), keyArray)) { return; } - gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getChecked()->first()); - QString fileString = QString::fromUtf8(key->uids->name) + " " + QString::fromUtf8(key->uids->email) + "(" + QString(key->subkeys->keyid)+ ")_pub.asc"; + KgpgCore::KgpgKey key = mCtx->getKeyDetails(mKeyList->getChecked()->first()); + QString fileString = key.name() + " " + key.email() + "(" + key.id()+ ")_pub.asc"; QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, tr("Key Files") + " (*.asc *.txt);;All Files (*)"); QFile file(fileName); diff --git a/keymgmt.h b/keymgmt.h index 1c1b138..723fd9b 100755 --- a/keymgmt.h +++ b/keymgmt.h @@ -28,6 +28,8 @@ #include "keyimportdetaildialog.h" #include "keyserverimportdialog.h" #include "keygendialog.h" +#include "kgpg/transactions/kgpgdelkey.h" +#include "kgpg/transactions/kgpgimport.h" #include QT_BEGIN_NAMESPACE @@ -44,7 +46,7 @@ class KeyMgmt : public QMainWindow Q_OBJECT public: - KeyMgmt(GpgME::GpgContext* ctx, QWidget *parent = 0); + KeyMgmt(GpgME::GpgContext *ctx, QWidget *parent); QAction *importKeyFromClipboardAct; QAction *importKeyFromFileAct; QAction *importKeyFromKeyServerAct; @@ -53,13 +55,15 @@ public slots: void importKeyFromFile(); void importKeyFromClipboard(); void importKeyFromKeyServer(); - void importKeys(QByteArray inBuffer); + void importKeys(QString text); + void slotImportDone(int result); void exportKeyToFile(); void exportKeyToClipboard(); void deleteSelectedKeys(); void deleteCheckedKeys(); void generateKeyDialog(); void showKeyDetails(); + void slotKeyDeleted(int retcode); signals: void statusBarChanged(QString); diff --git a/keyserverimportdialog.cpp b/keyserverimportdialog.cpp index 7118676..877e5d5 100644 --- a/keyserverimportdialog.cpp +++ b/keyserverimportdialog.cpp @@ -21,6 +21,7 @@ */ #include "keyserverimportdialog.h" +#include "keymgmt.h" KeyServerImportDialog::KeyServerImportDialog(GpgME::GpgContext *ctx, KeyList *keyList, QWidget *parent) : QDialog(parent) @@ -308,6 +309,44 @@ void KeyServerImportDialog::importFinished() void KeyServerImportDialog::importKeys(QByteArray inBuffer) { - GpgImportInformation result = mCtx->importKey(inBuffer); - new KeyImportDetailDialog(mCtx, result, this); + //GpgImportInformation result = mCtx->importKey(inBuffer); + KGpgImport *imp = new KGpgImport(this, QString(inBuffer)); + connect(imp, SIGNAL(done(int)), SLOT(slotImportDone(int))); + imp->start(); + +} + +void KeyServerImportDialog::slotImportDone(int result) +{ + KGpgImport *import = qobject_cast(sender()); + + Q_ASSERT(import != NULL); + const QStringList rawmsgs(import->getMessages()); + + if (result != 0) { + /*KMessageBox::detailedSorry(this, i18n("Key importing failed. Please see the detailed log for more information."), + rawmsgs.join( QLatin1String( "\n")) , i18n("Key Import" ));*/ + qDebug() << "Key importing failed. Please see the detailed log for more information." << rawmsgs.join( QLatin1String( "\n")); + } + + QStringList keys(import->getImportedIds(0x1f)); + const bool needsRefresh = !keys.isEmpty(); + keys << import->getImportedIds(0); +/* + if (!keys.isEmpty()) { + const QString msg(import->getImportMessage()); + const QStringList keynames(import->getImportedKeys()); + + new KgpgDetailedInfo(this, msg, rawmsgs.join( QLatin1String( "\n") ), keynames, i18n("Key Import" )); + if (needsRefresh) + imodel->refreshKeys(keys); + else + changeMessage(i18nc("Application ready for user input", "Ready")); + } else{ + changeMessage(i18nc("Application ready for user input", "Ready")); + } +*/ + //changeMessage(tr("Application ready for user input", "Ready")); + mCtx->emitKeyDBChanged(); + import->deleteLater(); } diff --git a/keyserverimportdialog.h b/keyserverimportdialog.h index 5f98d8f..801a7df 100644 --- a/keyserverimportdialog.h +++ b/keyserverimportdialog.h @@ -58,7 +58,7 @@ public: private slots: void import(); - + void slotImportDone(int result); void searchFinished(); void importFinished(); void search(); diff --git a/kgpg/core/KGpgExpandableNode.cpp b/kgpg/core/KGpgExpandableNode.cpp new file mode 100644 index 0000000..4cf9607 --- /dev/null +++ b/kgpg/core/KGpgExpandableNode.cpp @@ -0,0 +1,88 @@ +/* Copyright 2008,2009,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgExpandableNode.h" + +//#include "kgpgsettings.h" +#include "convert.h" +//#include "model/kgpgitemmodel.h" + +//#include + +KGpgExpandableNode::KGpgExpandableNode(KGpgExpandableNode *parent) + : KGpgNode(parent) +{ + if (parent != NULL) + parent->children.append(this); +} + +KGpgExpandableNode::~KGpgExpandableNode() +{ + for (int i = children.count() - 1; i >= 0; i--) + delete children[i]; +} + +KGpgNode * +KGpgExpandableNode::getChild(const int index) const +{ + if ((index < 0) || (index > children.count())) + return NULL; + return children.at(index); +} + +int +KGpgExpandableNode::getChildCount() +{ + if (children.count() == 0) + readChildren(); + + return children.count(); +} + +bool +KGpgExpandableNode::hasChildren() const +{ + return (children.count() != 0); +} + +bool +KGpgExpandableNode::wasExpanded() const +{ + return (children.count() != 0); +} + +const +KGpgNode::List & +KGpgExpandableNode::getChildren() const +{ + return children; +} + +int +KGpgExpandableNode::getChildIndex(KGpgNode *node) const +{ + return children.indexOf(node); +} + +void +KGpgExpandableNode::deleteChild(KGpgNode *child) +{ + children.removeAll(child); +} + +//#include "KGpgExpandableNode.moc" diff --git a/kgpg/core/KGpgExpandableNode.h b/kgpg/core/KGpgExpandableNode.h new file mode 100644 index 0000000..39f351d --- /dev/null +++ b/kgpg/core/KGpgExpandableNode.h @@ -0,0 +1,85 @@ +/* Copyright 2008,2009,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGEXPANDABLENODE_H +#define KGPGEXPANDABLENODE_H + +#include "KGpgNode.h" + +class KGpgSubkeyNode; +class KGpgRefNode; + +/** + * @brief The abstract base class for all classes that may have child objects + * + * Every class that represents something in the keyring that may have + * child objects inherits from this class. That does not mean that every + * child object always has children, but every child \em may have children. + */ +class KGpgExpandableNode : public KGpgNode +{ + Q_OBJECT + + friend class KGpgRefNode; + friend class KGpgSubkeyNode; +protected: + KGpgNode::List children; + + /** + * reimplemented in every base class to read in the child data + * + * This allows the child objects to delay the loading of the + * child objects until they are really needed to avoid time + * consuming operations for data never used. + */ + virtual void readChildren() = 0; + + explicit KGpgExpandableNode(KGpgExpandableNode *parent = NULL); +public: + virtual ~KGpgExpandableNode(); + + /** + * check if there are any child nodes + * + * The default implementation returns true if any child nodes were loaded. + * This may be reimplemented by child classes so they can indicate that + * there are child nodes before actually loading them. + * + * This method indicates if there are children if this node is expanded. + * In contrast wasExpanded() will only return true if the child nodes + * are actually present in memory. + */ + virtual bool hasChildren() const; + /** + * check if there are any child nodes present in memory + * + * Returns true if any child nodes were loaded. + * + * This method indicates if the children of this node are already loaded + * into memory. In contrast hasChildren() may return true even if the child + * objects are not present in memory. + */ + virtual bool wasExpanded() const; + virtual int getChildCount(); + virtual const KGpgNode::List &getChildren() const; + virtual KGpgNode *getChild(const int index) const; + virtual int getChildIndex(KGpgNode *node) const; + virtual void deleteChild(KGpgNode *child); +}; + +#endif /* KGPGEXPANDABLENODE_H */ diff --git a/kgpg/core/KGpgGroupMemberNode.cpp b/kgpg/core/KGpgGroupMemberNode.cpp new file mode 100644 index 0000000..e7a9f97 --- /dev/null +++ b/kgpg/core/KGpgGroupMemberNode.cpp @@ -0,0 +1,100 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgGroupMemberNode.h" + +#include + +#include "KGpgGroupNode.h" +#include "KGpgKeyNode.h" + +KGpgGroupMemberNode::KGpgGroupMemberNode(KGpgGroupNode *parent, const QString &k) + : KGpgRefNode(parent, k) +{ +} + +KGpgGroupMemberNode::KGpgGroupMemberNode(KGpgGroupNode *parent, KGpgKeyNode *k) + : KGpgRefNode(parent, k) +{ +} + +KGpgGroupMemberNode::~KGpgGroupMemberNode() +{ +} + +KgpgKeyTrust +KGpgGroupMemberNode::getTrust() const +{ + if (m_keynode != NULL) + return m_keynode->getTrust(); + return KgpgCore::TRUST_NOKEY; +} + +KgpgItemType +KGpgGroupMemberNode::getType() const +{ + if (m_keynode != NULL) + return m_keynode->getType() | KgpgCore::ITYPE_GROUP; + return KgpgCore::ITYPE_PUBLIC | KgpgCore::ITYPE_GROUP; +} + +QString +KGpgGroupMemberNode::getSize() const +{ + if (m_keynode != NULL) + return m_keynode->getSize(); + return QString(); +} + +QDateTime +KGpgGroupMemberNode::getExpiration() const +{ + if (m_keynode != NULL) + return m_keynode->getExpiration(); + return QDateTime(); +} + +QDateTime +KGpgGroupMemberNode::getCreation() const +{ + if (m_keynode != NULL) + return m_keynode->getCreation(); + return QDateTime(); +} + +unsigned int +KGpgGroupMemberNode::getSignKeySize() const +{ + if (m_keynode != NULL) + return m_keynode->getSignKeySize(); + return 0; +} + +unsigned int +KGpgGroupMemberNode::getEncryptionKeySize() const +{ + if (m_keynode != NULL) + return m_keynode->getEncryptionKeySize(); + return 0; +} + +KGpgGroupNode * +KGpgGroupMemberNode::getParentKeyNode() const +{ + return m_parent->toGroupNode(); +} diff --git a/kgpg/core/KGpgGroupMemberNode.h b/kgpg/core/KGpgGroupMemberNode.h new file mode 100644 index 0000000..2a456ef --- /dev/null +++ b/kgpg/core/KGpgGroupMemberNode.h @@ -0,0 +1,61 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGGROUPMEMBERNODE_H +#define KGPGGROUPMEMBERNODE_H + +#include "KGpgRefNode.h" + +#include +#include "kgpgkey.h" + +using namespace KgpgCore; + +class KGpgKeyNode; +class KGpgGroupNode; + +/** + * @brief A member of a GnuPG group + */ +class KGpgGroupMemberNode : public KGpgRefNode +{ +public: + explicit KGpgGroupMemberNode(KGpgGroupNode *parent, const QString &k); + explicit KGpgGroupMemberNode(KGpgGroupNode *parent, KGpgKeyNode *k); + virtual ~KGpgGroupMemberNode(); + + virtual KgpgCore::KgpgKeyTrust getTrust() const; + virtual KgpgCore::KgpgItemType getType() const; + virtual QString getSize() const; + virtual QDateTime getExpiration() const; + virtual QDateTime getCreation() const; + virtual KGpgGroupNode *getParentKeyNode() const; + + /** + * Returns the size of the signing key. + * @return signing key size in bits + */ + virtual unsigned int getSignKeySize() const; + /** + * Returns the size of the first encryption subkey. + * @return encryption key size in bits + */ + virtual unsigned int getEncryptionKeySize() const; +}; + +#endif /* KGPGGROUPMEMBERNODE_H */ diff --git a/kgpg/core/KGpgGroupNode.cpp b/kgpg/core/KGpgGroupNode.cpp new file mode 100644 index 0000000..3475303 --- /dev/null +++ b/kgpg/core/KGpgGroupNode.cpp @@ -0,0 +1,279 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgGroupNode.h" + +#include "KGpgGroupMemberNode.h" +#include "KGpgRootNode.h" +//#include "kgpgsettings.h" + +#include +//#include +#include +#include +#include + +class KGpgGroupNodePrivate { +public: + KGpgGroupNodePrivate(const QString &name); + + QString m_name; + + /** + * @brief find the line that defines this group in the configuration + * @param conffile file object (will be initialized) + * @param stream text stream (will be initialized and connected to conffile) + * @param lines the lines found in conffile (will be filled) + * @return the index in lines of the entry defining this group + * @retval -1 no entry defining this group was found + * + * stream will be positioned at the beginning. + */ + int findGroupEntry(QFile &conffile, QTextStream &stream, QStringList &lines); + + static const QRegExp &groupPattern(); + static const QString &groupTag(); +}; + +KGpgGroupNodePrivate::KGpgGroupNodePrivate(const QString &name) + : m_name(name) +{ +} + +int +KGpgGroupNodePrivate::findGroupEntry(QFile &conffile, QTextStream &stream, QStringList &lines) +{ + //conffile.setFileName(KGpgSettings::gpgConfigPath()); + conffile.setFileName(""); + + if (!conffile.exists()) + return -1; + + if (!conffile.open(QIODevice::ReadWrite)) + return -1; + + stream.setDevice(&conffile); + int index = -1; + int i = -1; + + while (!stream.atEnd()) { + const QString rawLine = stream.readLine(); + i++; + QString parsedLine = rawLine.simplified().section(QLatin1Char('#'), 0, 0); + + if (groupPattern().exactMatch(parsedLine)) { + // remove "group " + parsedLine = parsedLine.remove(0, 6); + if (parsedLine.startsWith(m_name)) { + if (parsedLine.mid(m_name.length()).simplified().startsWith(QLatin1Char('='))) { + if (index >= 0) { + // multiple definitions of the same group, drop the second one + continue; + } else { + index = i; + } + } + } + } + + lines << rawLine; + } + + stream.seek(0); + + return index; +} + +const QRegExp & +KGpgGroupNodePrivate::groupPattern() +{ + static const QRegExp groupre(QLatin1String("^group [^ ]+ ?= ?([0-9a-fA-F]{8,} ?)*$")); + + return groupre; +} + +const QString & +KGpgGroupNodePrivate::groupTag() +{ + static const QString grouptag(QLatin1String("group ")); + + return grouptag; +} + +KGpgGroupNode::KGpgGroupNode(KGpgRootNode *parent, const QString &name, const QStringList &members) + : KGpgExpandableNode(parent), + d_ptr(new KGpgGroupNodePrivate(name)) +{ + foreach (const QString &id, members) + new KGpgGroupMemberNode(this, id); + + parent->m_groups++; +} + +KGpgGroupNode::KGpgGroupNode(KGpgRootNode *parent, const QString &name, const KGpgKeyNode::List &members) + : KGpgExpandableNode(parent), + d_ptr(new KGpgGroupNodePrivate(name)) +{ + Q_ASSERT(members.count() > 0); + + foreach (KGpgKeyNode *nd, members) + new KGpgGroupMemberNode(this, nd); + + parent->m_groups++; +} + +KGpgGroupNode::~KGpgGroupNode() +{ + KGpgRootNode *root = m_parent->toRootNode(); + + if (root != NULL) + root->m_groups--; +} + +KgpgCore::KgpgItemType +KGpgGroupNode::getType() const +{ + return ITYPE_GROUP; +} + +QString +KGpgGroupNode::getName() const +{ + const Q_D(KGpgGroupNode); + + return d->m_name; +} + +QString +KGpgGroupNode::getSize() const +{ + return tr("1 key", "%1 keys").arg(children.count()); +} + +void +KGpgGroupNode::readChildren() +{ +} + +void +KGpgGroupNode::rename(const QString &newName) +{ + Q_D(KGpgGroupNode); + + QFile conffile; + QTextStream t; + QStringList lines; + int index = d->findGroupEntry(conffile, t, lines); + + // check if file opening failed + if (!t.device()) + return; + + if (index < 0) { + qDebug() << "Group " << d->m_name << " not renamed, group does not exist"; + return; + } + + // 6 = groupTag().length() + const QString values = lines[index].simplified().mid(6 + d->m_name.length()); + lines[index] = d->groupTag() + newName + QLatin1Char(' ') + values; + + conffile.resize(0); + t << lines.join(QLatin1String("\n")) + QLatin1Char('\n'); + + d->m_name = newName; +} + +void +KGpgGroupNode::saveMembers() +{ + Q_D(KGpgGroupNode); + + QFile conffile; + QTextStream t; + QStringList lines; + int index = d->findGroupEntry(conffile, t, lines); + + // check if file opening failed + if (!t.device()) + return; + + QStringList memberIds; + + for (int j = getChildCount() - 1; j >= 0; j--) + memberIds << getChild(j)->toGroupMemberNode()->getId(); + + const QString groupEntry = d->groupTag() + d->m_name + QLatin1String(" = ") + + memberIds.join(QLatin1String(" ")); + + if (index >= 0) + lines[index] = groupEntry; + else + lines << groupEntry; + + conffile.resize(0); + t << lines.join(QLatin1String("\n")) + QLatin1Char('\n'); +} + +void +KGpgGroupNode::remove() +{ + Q_D(KGpgGroupNode); + + QFile conffile; + QTextStream t; + QStringList lines; + int index = d->findGroupEntry(conffile, t, lines); + + // check if file opening failed + if (!t.device()) + return; + + if (index < 0) + return; + + lines.removeAt(index); + conffile.resize(0); + t << lines.join(QLatin1String("\n")) + QLatin1Char('\n'); +} + +QStringList +KGpgGroupNode::readGroups() +{ + QStringList groups; + //QFile qfile(KGpgSettings::gpgConfigPath()); + QFile qfile(""); + + if (!qfile.exists() || !qfile.open(QIODevice::ReadOnly)) + return groups; + + QTextStream t(&qfile); + + while (!t.atEnd()) { + QString line = t.readLine().simplified().section(QLatin1Char('#'), 0, 0); + if (!KGpgGroupNodePrivate::groupPattern().exactMatch(line)) + continue; + + // remove the "group " at the start + line.remove(0, 6); + // transform it in a simple space separated list + groups.append(line.replace(QLatin1Char('='), QLatin1Char(' ')).simplified()); + } + + return groups; +} diff --git a/kgpg/core/KGpgGroupNode.h b/kgpg/core/KGpgGroupNode.h new file mode 100644 index 0000000..5aca837 --- /dev/null +++ b/kgpg/core/KGpgGroupNode.h @@ -0,0 +1,84 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGGROUPNODE_H +#define KGPGGROUPNODE_H + +#include "KGpgExpandableNode.h" +#include "KGpgKeyNode.h" + +class QString; +class QStringList; + +class KGpgGroupNodePrivate; + +/** + * @brief A GnuPG group of public keys + */ +class KGpgGroupNode : public KGpgExpandableNode +{ +private: + KGpgGroupNodePrivate * const d_ptr; + Q_DECLARE_PRIVATE(KGpgGroupNode) + Q_DISABLE_COPY(KGpgGroupNode) + +protected: + virtual void readChildren(); + +public: + KGpgGroupNode(KGpgRootNode *parent, const QString &name, const QStringList &members); + KGpgGroupNode(KGpgRootNode *parent, const QString &name, const KGpgKeyNode::List &members); + virtual ~KGpgGroupNode(); + + virtual KgpgCore::KgpgItemType getType() const; + /** + * Return size of group + * + * @return the number of keys in this group + */ + virtual QString getSize() const; + virtual QString getName() const; + + /** + * Rename this group node + * + * @param newName new name of the group + */ + void rename(const QString &newName); + + /** + * Write the current members to GnuPG config file + */ + void saveMembers(); + + /** + * Remove this group from the GnuPG config file + */ + void remove(); + + /** + * @brief get all groups from GnuPG config file + * @return list of groups names and their keys + * + * The strings are themself space separated list. The first entry is the + * group name, the others are the keys inside + */ + static QStringList readGroups(); +}; + +#endif /* KGPGGROUPNODE_H */ diff --git a/kgpg/core/KGpgKeyNode.cpp b/kgpg/core/KGpgKeyNode.cpp new file mode 100644 index 0000000..4e5fb55 --- /dev/null +++ b/kgpg/core/KGpgKeyNode.cpp @@ -0,0 +1,358 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgKeyNode.h" + +#include "KGpgGroupMemberNode.h" +#include "KGpgRootNode.h" +#include "KGpgSubkeyNode.h" +#include "KGpgUatNode.h" +#include "KGpgUidNode.h" +#include "convert.h" +#include "../kgpginterface.h" +//#include "kgpgsettings.h" +//#include "model/kgpgitemmodel.h" + +//#include + +KGpgKeyNode::KGpgKeyNode(KGpgRootNode *parent, const KgpgCore::KgpgKey &k) + : KGpgSignableNode(parent), + m_key(new KgpgCore::KgpgKey(k)), + m_signs(0) +{ +} + +KGpgKeyNode::~KGpgKeyNode() +{ + foreach (KGpgRefNode *nd, m_refs) { + nd->unRef(m_parent->toRootNode()); + } +} + +KgpgCore::KgpgItemType +KGpgKeyNode::getType() const +{ + return getType(m_key); +} + +bool +KGpgKeyNode::hasChildren() const +{ + return true; +} + +KgpgCore::KgpgItemType +KGpgKeyNode::getType(const KgpgCore::KgpgKey *k) +{ + if (k->secret()) + return KgpgCore::ITYPE_PAIR; + + return KgpgCore::ITYPE_PUBLIC; +} + +KgpgCore::KgpgKeyTrust +KGpgKeyNode::getTrust() const +{ + return m_key->trust(); +} + +const QString & +KGpgKeyNode::getFingerprint() const +{ + return m_key->fingerprint(); +} + +QString +KGpgKeyNode::getSize() const +{ + return "size of signing key / size of encryption key", + "%1 / %2", QString::number(getSignKeySize()), + QString::number(getEncryptionKeySize()); +} + +QString +KGpgKeyNode::getName() const +{ + return m_key->name(); +} + +QString +KGpgKeyNode::getEmail() const +{ + return m_key->email(); +} + +QDateTime +KGpgKeyNode::getExpiration() const +{ + return m_key->expirationDate(); +} + +QDateTime +KGpgKeyNode::getCreation() const +{ + return m_key->creationDate(); +} + +QString +KGpgKeyNode::getId() const +{ + return m_key->fullId(); +} + +KGpgKeyNode * +KGpgKeyNode::getKeyNode(void) +{ + return this; +} + +bool +KGpgKeyNode::isSecret() const +{ + return m_key->secret(); +} + +const KGpgKeyNode * +KGpgKeyNode::getKeyNode(void) const +{ + return this; +} + +QString +KGpgKeyNode::getBeautifiedFingerprint() const +{ + return m_key->fingerprintBeautified(); +} + +QString +KGpgKeyNode::getComment() const +{ + return m_key->comment(); +} + +void +KGpgKeyNode::readChildren() +{ + KgpgInterface::readSignatures(this); + + m_signs = 0; + foreach(KGpgNode *n, children) + if (n->getType() == ITYPE_SIGN) + m_signs++; +} + +QString +KGpgKeyNode::getSignCount() const +{ + if (!wasExpanded()) + return QString(); + //return i18np("1 signature", "%1 signatures", m_signs); + return "TODO"; +} + +KgpgKey * +KGpgKeyNode::copyKey() const +{ + return new KgpgKey(*m_key); +} + +void +KGpgKeyNode::setKey(const KgpgKey &key) +{ + Q_ASSERT(m_key->fingerprint() == key.fingerprint()); + delete m_key; + + for (int i = 0; i < children.count(); i++) + delete children.at(i); + children.clear(); + + m_key = new KgpgKey(key); +} + +const KgpgKey * +KGpgKeyNode::getKey() const +{ + return m_key; +} + +unsigned int +KGpgKeyNode::getSignKeySize() const +{ + return m_key->size(); +} + +unsigned int +KGpgKeyNode::getEncryptionKeySize() const +{ + return m_key->encryptionSize(); +} + +void +KGpgKeyNode::addRef(KGpgRefNode *node) +{ + Q_ASSERT(m_refs.indexOf(node) == -1); + m_refs.append(node); +} + +void +KGpgKeyNode::delRef(KGpgRefNode *node) +{ + Q_ASSERT(m_refs.indexOf(node) != -1); + m_refs.removeOne(node); + Q_ASSERT(m_refs.indexOf(node) == -1); +} + +QList +KGpgKeyNode::getGroups(void) const +{ + QList ret; + + foreach (KGpgGroupMemberNode *gnd, getGroupRefs()) + ret.append(gnd->getParentKeyNode()); + + return ret; +} + +QList +KGpgKeyNode::getRefsOfType(const KgpgItemType &type) const +{ + QList ret; + + foreach (KGpgRefNode *nd, m_refs) { + if (nd->getType() & type) + ret.append(nd); + } + + return ret; +} + +QList +KGpgKeyNode::getGroupRefs(void) const +{ + QList ret; + + foreach (KGpgRefNode *rn, getRefsOfType(KgpgCore::ITYPE_GROUP)) + ret.append(rn->toGroupMemberNode()); + + return ret; +} + +KGpgSignNode::List +KGpgKeyNode::getSignRefs(void) const +{ + KGpgSignNode::List ret; + + QList refs = getRefsOfType(KgpgCore::ITYPE_SIGN); + + foreach (KGpgRefNode *rn, refs) + ret.append(rn->toSignNode()); + + return ret; +} + +KGpgSignNode::List +KGpgKeyNode::getSignatures(const bool subkeys) const +{ + KGpgSignNode::List ret = KGpgSignableNode::getSignatures(); + + if (!subkeys) + return ret; + + foreach (KGpgNode *child, children) { + KGpgSignNode::List tmp; + + switch (child->getType()) { + case KgpgCore::ITYPE_UID: + case KgpgCore::ITYPE_UAT: + tmp = child->toSignableNode()->getSignatures(); + break; + default: + continue; + } + + foreach (KGpgSignNode *sn, tmp) { + bool found = false; + const QString snid(sn->getId()); + + foreach (const KGpgSignNode *retsn, ret) { + found = (retsn->getId() == snid); + if (found) + break; + } + + if (!found) + ret << sn; + } + } + + return ret; +} + +const KGpgSignableNode * +KGpgKeyNode::getUid(const unsigned int index) const +{ + Q_ASSERT(index > 0); + + if (index == 1) + return this; + + const QString idxstr(QString::number(index)); + + foreach (const KGpgNode *child, children) { + KGpgSignNode::List tmp; + + switch (child->getType()) { + case KgpgCore::ITYPE_UID: + case KgpgCore::ITYPE_UAT: + if (child->getId() == idxstr) + return child->toSignableNode(); + break; + default: + continue; + } + } + + return NULL; +} + +bool +KGpgKeyNode::compareId(const QString &other) const +{ + if (other.length() == m_key->fullId().length()) + return (other.compare(m_key->fullId(), Qt::CaseInsensitive) == 0); + + if (other.length() == m_key->fingerprint().length()) + return (other.compare(m_key->fingerprint(), Qt::CaseInsensitive) == 0); + + const QString comId = m_key->fullId().isEmpty() ? m_key->fingerprint() : m_key->fullId(); + + return (other.right(comId.length()).compare( + comId.right(other.length()), + Qt::CaseInsensitive) == 0); +} + +void +KGpgKeyNode::expand() +{ + if (!wasExpanded()) + readChildren(); + + emit expanded(); +} + +//#include "KGpgKeyNode.moc" diff --git a/kgpg/core/KGpgKeyNode.h b/kgpg/core/KGpgKeyNode.h new file mode 100644 index 0000000..caf0ba4 --- /dev/null +++ b/kgpg/core/KGpgKeyNode.h @@ -0,0 +1,191 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGKEYNODE_H +#define KGPGKEYNODE_H + +#include "KGpgSignableNode.h" +#include "KGpgSignNode.h" + +#include "kgpgkey.h" + +class KGpgExpandableNode; +class KGpgRefNode; + +/** + * @brief A public key with or without corresponding secret key + */ +class KGpgKeyNode : public KGpgSignableNode +{ + Q_OBJECT + + friend class KGpgGroupMemberNode; + +private: + KgpgCore::KgpgKey *m_key; + int m_signs; + +protected: + virtual void readChildren(); + + QList m_refs; + QList getRefsOfType(const KgpgCore::KgpgItemType &type) const; + +public: + typedef QList List; + typedef QList ConstList; + + explicit KGpgKeyNode(KGpgRootNode *parent, const KgpgCore::KgpgKey &k); + virtual ~KGpgKeyNode(); + + virtual bool hasChildren() const; + + static KgpgCore::KgpgItemType getType(const KgpgCore::KgpgKey *k); + + virtual KgpgCore::KgpgItemType getType() const; + virtual KgpgCore::KgpgKeyTrust getTrust() const; + const QString &getFingerprint() const; + virtual QString getSize() const; + virtual QString getName() const; + virtual QString getEmail() const; + virtual QDateTime getExpiration() const; + virtual QDateTime getCreation() const; + virtual QString getId() const; + virtual KGpgKeyNode *getKeyNode(void); + virtual const KGpgKeyNode *getKeyNode(void) const; + /** + * @brief Return if this key has a private key + */ + bool isSecret() const; + /** + * @brief Print the full key fingerprint with spaces inserted + * + * For display purposes you normally don't want to print the full + * fingerprint as is because it's too many hex characters at once. + * This function returns the fingerprint in the format usually used + * for printing this out, i.e. with a space after each fourth hex + * character. + * + * @return the full fingerprint with spaces inserted + */ + QString getBeautifiedFingerprint() const; + virtual QString getComment() const; + /** + * @brief Return the number of signatures of the primary user id + * + * This is different from the number of children of this node as there + * is usually at least one subkey and there may also be additional + * user ids or attributes. This does not count the signatures to those + * slave objects, only the ones that are direct children of this node. + * + * @return the number of signatures to the primary user id + */ + virtual QString getSignCount() const; + /** + * @brief Creates a copy of the KgpgKey that belongs to this class + */ + virtual KgpgCore::KgpgKey *copyKey() const; + /** + * @brief Replaces the current key information with the new one. + * All sub-items (i.e. signatures, user ids ...) will be deleted. This must + * only be used when the id of both new and old key is the same. + */ + void setKey(const KgpgCore::KgpgKey &key); + /** + * @brief Returns a reference to the key used in this object. + * This allows direct access to the values of the key e.g. for KgpgKeyInfo. + */ + const KgpgCore::KgpgKey *getKey() const; + + /** + * @brief Returns the size of the signing key. + * @return signing key size in bits + */ + virtual unsigned int getSignKeySize() const; + /** + * @brief Returns the size of the first encryption subkey. + * @return encryption key size in bits + */ + virtual unsigned int getEncryptionKeySize() const; + /** + * @brief Notify this key that a KGpgRefNode now references this key. + * @param node object that takes the reference + */ + void addRef(KGpgRefNode *node); + /** + * @brief Remove a reference to this object + * @param node node that no longer has the reference + * + * Note that this must not be called as reply when this object + * emits updated(NULL) + */ + void delRef(KGpgRefNode *node); + /** + * @brief returns a list of all groups this key is member of + */ + QList getGroups(void) const; + /** + * @brief returns a list of all group member nodes that reference this key + */ + QList getGroupRefs(void) const; + /** + * @brief returns a list of all sign nodes that reference this key + */ + KGpgSignNode::List getSignRefs(void) const; + /** + * @brief returns a list of signatures to this key + * @param subkeys if signatures on subkeys should be included + */ + KGpgSignNode::List getSignatures(const bool subkeys) const; + /** + * @brief get the user id or user attribute with the given number + * @param index the index of the user id to return + * @return the requested subitem or NULL if that is not present + * + * User ids indexes are 1-based, so 0 is not a valid index. Passing + * 1 as index will return the object itself, representing the primary + * user id. + */ + const KGpgSignableNode *getUid(const unsigned int index) const; + + /** + * @brief compare the id of this node to the given other node + * @param other key id to compare to + * @return if ids are identical + * + * This handles different length of the id string. + */ + bool compareId(const QString &other) const; +Q_SIGNALS: + void expanded(); + +public slots: + /** + * @brief read all subitems + * + * This will read in all subitems (e.g. subkeys, signatures). When + * this is done the expanded() signal is emitted. The signal is emitted + * immediately if the key has been expanded before. + * + * This will not update the child items in case they are already present. + * Use KGpgItemModel::refreshKey() instead. + */ + void expand(); +}; + +#endif /* KGPGKEYNODE_H */ diff --git a/kgpg/core/KGpgNode.cpp b/kgpg/core/KGpgNode.cpp new file mode 100644 index 0000000..18645f8 --- /dev/null +++ b/kgpg/core/KGpgNode.cpp @@ -0,0 +1,337 @@ +/* Copyright 2008,2009,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgNode.h" + +#include "KGpgGroupMemberNode.h" +#include "KGpgGroupNode.h" +#include "KGpgOrphanNode.h" +#include "KGpgRootNode.h" +#include "KGpgSubkeyNode.h" +#include "KGpgUatNode.h" +#include "KGpgUidNode.h" +//#include "model/kgpgitemmodel.h" + +//#include + +KGpgNode::KGpgNode(KGpgExpandableNode *parent) + : QObject(), m_parent(parent) +{ +/* if (parent == NULL) + m_model = NULL; + else + m_model = parent->m_model; +*/ +} + +KGpgNode::~KGpgNode() +{ +/* Q_ASSERT(m_model); + m_model->invalidateIndexes(this); +*/ + if (m_parent != NULL) + m_parent->deleteChild(this); +} + +QString +KGpgNode::getNameComment() const +{ + if (getComment().isEmpty()) + return getName(); + else + return tr("Name of uid (comment) %1 (%2)").arg(getName()).arg(getComment()); + //return QString("Name of uid (comment)", "%1 (%2)", getName(), getComment()); +} + +KGpgExpandableNode * +KGpgNode::toExpandableNode() +{ + Q_ASSERT(((getType() & KgpgCore::ITYPE_GROUP) && !(getType() & KgpgCore::ITYPE_PAIR)) || + (getType() & (KgpgCore::ITYPE_PAIR | KgpgCore::ITYPE_SUB | KgpgCore::ITYPE_UID | KgpgCore::ITYPE_UAT))); + + return qobject_cast(this); +} + +const KGpgExpandableNode * +KGpgNode::toExpandableNode() const +{ + Q_ASSERT(((getType() & KgpgCore::ITYPE_GROUP) && !(getType() & KgpgCore::ITYPE_PAIR)) || + (getType() & (KgpgCore::ITYPE_PAIR | KgpgCore::ITYPE_SUB | KgpgCore::ITYPE_UID | KgpgCore::ITYPE_UAT))); + + return qobject_cast(this); +} + +KGpgSignableNode * +KGpgNode::toSignableNode() +{ + Q_ASSERT(getType() & (KgpgCore::ITYPE_PAIR | KgpgCore::ITYPE_SUB | KgpgCore::ITYPE_UID | KgpgCore::ITYPE_UAT)); + + return qobject_cast(this); +} + +const KGpgSignableNode * +KGpgNode::toSignableNode() const +{ + Q_ASSERT(getType() & (KgpgCore::ITYPE_PAIR | KgpgCore::ITYPE_SUB | KgpgCore::ITYPE_UID | KgpgCore::ITYPE_UAT)); + + return qobject_cast(this); +} + +KGpgKeyNode * +KGpgNode::toKeyNode() +{ + Q_ASSERT(getType() & KgpgCore::ITYPE_PAIR); + Q_ASSERT(!(getType() & KgpgCore::ITYPE_GROUP)); + + return qobject_cast(this); +} + +const KGpgKeyNode * +KGpgNode::toKeyNode() const +{ + Q_ASSERT(getType() & KgpgCore::ITYPE_PAIR); + Q_ASSERT(!(getType() & KgpgCore::ITYPE_GROUP)); + + return qobject_cast(this); +} + +KGpgRootNode * +KGpgNode::toRootNode() +{ + Q_ASSERT((m_parent == NULL) && (getType() == 0)); + + return static_cast(this)->asRootNode(); +} + +const KGpgRootNode * +KGpgNode::toRootNode() const +{ + Q_ASSERT((m_parent == NULL) && (getType() == 0)); + + return static_cast(this)->asRootNode(); +} + +KGpgUidNode * +KGpgNode::toUidNode() +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_UID); + + return static_cast(this); +} + +const KGpgUidNode * +KGpgNode::toUidNode() const +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_UID); + + return static_cast(this); +} + +KGpgSubkeyNode * +KGpgNode::toSubkeyNode() +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_SUB); + + return static_cast(this); +} + +const KGpgSubkeyNode * +KGpgNode::toSubkeyNode() const +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_SUB); + + return static_cast(this); +} + +KGpgUatNode * +KGpgNode::toUatNode() +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_UAT); + + return static_cast(this); +} + +const KGpgUatNode * +KGpgNode::toUatNode() const +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_UAT); + + return static_cast(this); +} + +KGpgGroupNode * +KGpgNode::toGroupNode() +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_GROUP); + + return static_cast(this); +} + +const KGpgGroupNode * +KGpgNode::toGroupNode() const +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_GROUP); + + return static_cast(this); +} + +KGpgRefNode * +KGpgNode::toRefNode() +{ + Q_ASSERT(((getType() & KgpgCore::ITYPE_GROUP) && (getType() & KgpgCore::ITYPE_PAIR)) || (getType() & KgpgCore::ITYPE_SIGN)); + + return qobject_cast(this); +} + +const KGpgRefNode * +KGpgNode::toRefNode() const +{ + Q_ASSERT(((getType() & KgpgCore::ITYPE_GROUP) && (getType() & KgpgCore::ITYPE_PAIR)) || (getType() & KgpgCore::ITYPE_SIGN)); + + return qobject_cast(this); +} + +KGpgGroupMemberNode * +KGpgNode::toGroupMemberNode() +{ + Q_ASSERT((getType() & KgpgCore::ITYPE_GROUP) && (getType() & KgpgCore::ITYPE_PAIR)); + + return static_cast(this); +} + +const KGpgGroupMemberNode * +KGpgNode::toGroupMemberNode() const +{ + Q_ASSERT((getType() & KgpgCore::ITYPE_GROUP) && (getType() & KgpgCore::ITYPE_PAIR)); + + return static_cast(this); +} + +KGpgSignNode * +KGpgNode::toSignNode() +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_SIGN); + + return static_cast(this); +} + +const KGpgSignNode * +KGpgNode::toSignNode() const +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_SIGN); + + return static_cast(this); +} + +KGpgOrphanNode * +KGpgNode::toOrphanNode() +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_SECRET); + + return static_cast(this); +} + +const KGpgOrphanNode * +KGpgNode::toOrphanNode() const +{ + Q_ASSERT(getType() == KgpgCore::ITYPE_SECRET); + + return static_cast(this); +} + +bool +KGpgNode::hasChildren() const +{ + return false; +} + +int +KGpgNode::getChildCount() +{ + return 0; +} + +KGpgNode * +KGpgNode::getChild(const int index) const +{ + Q_UNUSED(index); + return NULL; +} + +int +KGpgNode::getChildIndex(KGpgNode *node) const +{ + Q_UNUSED(node); + return 0; +} + +KgpgCore::KgpgKeyTrust +KGpgNode::getTrust() const +{ + return TRUST_NOKEY; +} + +QString +KGpgNode::getSize() const +{ + return QString(); +} + +QString +KGpgNode::getName() const +{ + return QString(); +} + +QString +KGpgNode::getEmail() const +{ + return QString(); +} + +QDateTime +KGpgNode::getExpiration() const +{ + return QDateTime(); +} + +QDateTime +KGpgNode::getCreation() const +{ + return QDateTime(); +} + +QString +KGpgNode::getId() const +{ + return QString(); +} + +QString +KGpgNode::getComment() const +{ + return QString(); +} + +KGpgExpandableNode * +KGpgNode::getParentKeyNode() const +{ + return m_parent; +} + +//#include "KGpgNode.moc" diff --git a/kgpg/core/KGpgNode.h b/kgpg/core/KGpgNode.h new file mode 100644 index 0000000..1d89875 --- /dev/null +++ b/kgpg/core/KGpgNode.h @@ -0,0 +1,156 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGNODE_H +#define KGPGNODE_H + +#include +#include "kgpgkey.h" + +class KGpgExpandableNode; +class KGpgKeyNode; +class KGpgRootNode; +class KGpgUidNode; +class KGpgSignableNode; +class KGpgSubkeyNode; +class KGpgUatNode; +class KGpgGroupNode; +class KGpgRefNode; +class KGpgGroupMemberNode; +class KGpgSignNode; +class KGpgOrphanNode; +class KGpgItemModel; + +/** + * @brief The abstract base class for all classes representing keyring data + */ +class KGpgNode : public QObject +{ + Q_OBJECT + + friend class KGpgItemModel; + + KGpgNode(); // = delete C++0x +protected: + KGpgExpandableNode *m_parent; + KGpgItemModel *m_model; + + /** + * constructor + * @param parent the parent node in item hierarchy + */ + explicit KGpgNode(KGpgExpandableNode *parent); + +public: + typedef QList List; + + /** + * destructor + */ + virtual ~KGpgNode(); + + /** + * Returns if this node has child nodes + * + * This may be reimplemented by child classes so they can indicate that + * there are child nodes before actually loading them. + */ + virtual bool hasChildren() const; + /** + * Return how many child nodes exist + * + * When the child nodes do not already exist this will create them. + * This is the reason why this method is not const. + */ + virtual int getChildCount(); + /** + * Returns the child node at the given index + * @param index child index + * + * index may be in range 0 to getChildCount() - 1. + */ + virtual KGpgNode *getChild(const int index) const; + /** + * Returns the index for a given child node + * @return -1 if the given node is not a child of this object + */ + virtual int getChildIndex(KGpgNode *node) const; + + /** + * Returns the item type of this object + * + * Since every subclass returns a distinct value you can use the + * result of this function to decide which cast to take. Note that + * there are subclasses (KGpgKeyNode, KGpgGroupMemberNode) that + * can return two different values. + */ + virtual KgpgCore::KgpgItemType getType() const = 0; + virtual KgpgCore::KgpgKeyTrust getTrust() const; + /** + * Returns a string describing the size of this object + * + * Subclasses may return a value that makes sense for whatever + * object they represent. + * + * The default implementation returns an empty string. + */ + virtual QString getSize() const; + virtual QString getName() const; + virtual QString getEmail() const; + virtual QDateTime getExpiration() const; + virtual QDateTime getCreation() const; + virtual QString getId() const; + virtual QString getComment() const; + virtual QString getNameComment() const; + /** + * Returns the parent node in the key hierarchy + * + * For all "primary" items like keys and key groups this will + * return the (invisible) root node. Calling this function for + * the root node will return %NULL. No other node but the root + * node has a %NULL parent. + */ + KGpgExpandableNode *getParentKeyNode() const; + + KGpgExpandableNode *toExpandableNode(); + const KGpgExpandableNode *toExpandableNode() const; + KGpgSignableNode *toSignableNode(); + const KGpgSignableNode *toSignableNode() const; + KGpgKeyNode *toKeyNode(); + const KGpgKeyNode *toKeyNode() const; + KGpgRootNode *toRootNode(); + const KGpgRootNode *toRootNode() const; + KGpgUidNode *toUidNode(); + const KGpgUidNode *toUidNode() const; + KGpgSubkeyNode *toSubkeyNode(); + const KGpgSubkeyNode *toSubkeyNode() const; + KGpgUatNode *toUatNode(); + const KGpgUatNode *toUatNode() const; + KGpgGroupNode *toGroupNode(); + const KGpgGroupNode *toGroupNode() const; + KGpgRefNode *toRefNode(); + const KGpgRefNode *toRefNode() const; + KGpgGroupMemberNode *toGroupMemberNode(); + const KGpgGroupMemberNode *toGroupMemberNode() const; + KGpgSignNode *toSignNode(); + const KGpgSignNode *toSignNode() const; + KGpgOrphanNode *toOrphanNode(); + const KGpgOrphanNode *toOrphanNode() const; +}; + +#endif /* KGPGNODE_H */ diff --git a/kgpg/core/KGpgOrphanNode.cpp b/kgpg/core/KGpgOrphanNode.cpp new file mode 100644 index 0000000..f245121 --- /dev/null +++ b/kgpg/core/KGpgOrphanNode.cpp @@ -0,0 +1,84 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgOrphanNode.h" + +KGpgOrphanNode::KGpgOrphanNode(KGpgExpandableNode *parent, const KgpgKey &k) + : KGpgNode(parent), + m_key(new KgpgKey(k)) +{ +} + +KGpgOrphanNode::~KGpgOrphanNode() +{ + delete m_key; +} + +KgpgItemType +KGpgOrphanNode::getType() const +{ + return ITYPE_SECRET; +} + +QString +KGpgOrphanNode::getName() const +{ + return m_key->name(); +} + +QString +KGpgOrphanNode::getEmail() const +{ + return m_key->email(); +} + +QString +KGpgOrphanNode::getSize() const +{ + return QString::number(m_key->size()); +} + +QDateTime +KGpgOrphanNode::getExpiration() const +{ + return m_key->expirationDate(); +} + +QDateTime +KGpgOrphanNode::getCreation() const +{ + return m_key->creationDate(); +} + +QString +KGpgOrphanNode::getId() const +{ + return m_key->fullId(); +} + +KgpgCore::KgpgKeyTrust +KGpgOrphanNode::getTrust() const +{ + return m_key->trust(); +} + +const QString & +KGpgOrphanNode::getFingerprint() const +{ + return m_key->fingerprint(); +} diff --git a/kgpg/core/KGpgOrphanNode.h b/kgpg/core/KGpgOrphanNode.h new file mode 100644 index 0000000..e3b6132 --- /dev/null +++ b/kgpg/core/KGpgOrphanNode.h @@ -0,0 +1,53 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGORPHANNODE_H +#define KGPGORPHANNODE_H + +#include "KGpgNode.h" + +#include "kgpgkey.h" + +using namespace KgpgCore; + +class KGpgExpandableNode; + +/** + * @brief A lone secret key without public key + */ +class KGpgOrphanNode : public KGpgNode +{ +private: + KgpgCore::KgpgKey *m_key; + +public: + explicit KGpgOrphanNode(KGpgExpandableNode *parent, const KgpgKey &k); + virtual ~KGpgOrphanNode(); + + virtual KgpgCore::KgpgItemType getType() const; + virtual KgpgCore::KgpgKeyTrust getTrust() const; + const QString &getFingerprint() const; + virtual QString getSize() const; + virtual QString getName() const; + virtual QString getEmail() const; + virtual QDateTime getExpiration() const; + virtual QDateTime getCreation() const; + virtual QString getId() const; +}; + +#endif /* KGPGORPHANNODE_H */ diff --git a/kgpg/core/KGpgRefNode.cpp b/kgpg/core/KGpgRefNode.cpp new file mode 100644 index 0000000..a67d6b5 --- /dev/null +++ b/kgpg/core/KGpgRefNode.cpp @@ -0,0 +1,151 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgRefNode.h" + +//#include + +#include "KGpgExpandableNode.h" +#include "KGpgRootNode.h" + +KGpgRefNode::KGpgRefNode(KGpgExpandableNode *parent, const QString &keyid) + : KGpgNode(parent), + m_id(keyid) +{ + Q_ASSERT(!keyid.isEmpty()); + + KGpgRootNode *root = getRootNode(); + KGpgExpandableNode *pnd = parent; + + do { + m_selfsig = (pnd->getId().right(keyid.length()) == keyid); + if (m_selfsig) + m_keynode = pnd->toKeyNode(); + else + pnd = pnd->getParentKeyNode(); + } while (!m_selfsig && (pnd != root)); + + // Self signatures do net need to get notified by their key: if the key is changed + // the key node is deleted, then those refnode would be deleted anyway. This avoids + // crashes when they would try to find the root node by iterating over their parent + // when the parents destructor is already called (see bug 208659). + if (!m_selfsig) { + m_keynode = root->findKey(keyid); + + if (m_keynode != NULL) { + m_keynode->addRef(this); + } else { + connect(root, SIGNAL(newKeyNode(KGpgKeyNode*)), this, SLOT(keyUpdated(KGpgKeyNode*))); + } + } + + parent->children.append(this); +} + +KGpgRefNode::KGpgRefNode(KGpgExpandableNode *parent, KGpgKeyNode *key) + : KGpgNode(parent), + m_id(key->getId()), + m_keynode(key) +{ + Q_ASSERT(key != NULL); + Q_ASSERT(parent != NULL); + m_keynode->addRef(this); + + parent->children.append(this); +} + +KGpgRefNode::~KGpgRefNode() +{ + if (m_keynode && !m_selfsig) + m_keynode->delRef(this); +} + +KGpgRootNode * +KGpgRefNode::getRootNode() const +{ + KGpgExpandableNode *root; + KGpgExpandableNode *pt = m_parent; + + do { + root = pt; + pt = pt->getParentKeyNode(); + } while (pt != NULL); + + return root->toRootNode(); +} + +void +KGpgRefNode::keyUpdated(KGpgKeyNode *nkey) +{ + Q_ASSERT(m_keynode == NULL); + Q_ASSERT(nkey != NULL); + + if (nkey->getId().right(m_id.length()) == m_id) { + disconnect(sender(), NULL, this, SLOT(keyUpdated(KGpgKeyNode*))); + m_keynode = nkey; + m_keynode->addRef(this); + } +} + +void +KGpgRefNode::unRef(KGpgRootNode *root) +{ + if (root != NULL) + connect(root, SIGNAL(newKeyNode(KGpgKeyNode*)), this, SLOT(keyUpdated(KGpgKeyNode*))); + + m_keynode = NULL; +} + +QString +KGpgRefNode::getId() const +{ + if (m_keynode != NULL) + return m_keynode->getId(); + else + return m_id; +} + +QString +KGpgRefNode::getName() const +{ + if (m_keynode != NULL) + return m_keynode->getName(); + return tr("[No user id found]"); +} + +QString +KGpgRefNode::getEmail() const +{ + if (m_keynode != NULL) + return m_keynode->getEmail(); + return QString(); +} + +bool +KGpgRefNode::isUnknown() const +{ + return (m_keynode == NULL); +} + +KGpgKeyNode * +KGpgRefNode::getRefNode() const +{ + return m_keynode; +} + +//#include "KGpgRefNode.moc" diff --git a/kgpg/core/KGpgRefNode.h b/kgpg/core/KGpgRefNode.h new file mode 100644 index 0000000..f977567 --- /dev/null +++ b/kgpg/core/KGpgRefNode.h @@ -0,0 +1,98 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGREFNODE_H +#define KGPGREFNODE_H + +#include "KGpgNode.h" + +class KGpgKeyNode; +class KGpgRootNode; + +/** + * @brief Class for child objects that are only a reference to a primary key + * + * This is the base class for all type of objects that match these criteria: + * -they can not have child objects + * -they are only a reference to a primary key (which needs not to be in the + * key ring) + * + * Do not create instances from this class. Use KGpgGroupMemberNode and + * KGpgSignNode as those represent the existing objects. This class exists + * only to get the hierarchy right. + */ +class KGpgRefNode : public KGpgNode +{ + Q_OBJECT + +private: + const QString m_id; + bool m_selfsig; ///< if this is a reference to it's own parent + +protected: + KGpgKeyNode *m_keynode; + + explicit KGpgRefNode(KGpgExpandableNode *parent, KGpgKeyNode *key); + explicit KGpgRefNode(KGpgExpandableNode *parent, const QString &keyid); + + KGpgRootNode *getRootNode() const; + +public: + virtual ~KGpgRefNode(); + + virtual QString getId() const; + virtual QString getName() const; + virtual QString getEmail() const; + /** + * Get the node of the primary key this node references to + * + * This will return the key node of the primary key this node + * references. This may be %NULL if the primary key is not in the key + * ring, e.g. if this is a signature of an unknown key. + * + * @return the node of the primary key or %NULL + */ + virtual KGpgKeyNode *getRefNode() const; + + /** + * Check if the referenced key exists + * + * @return if getRefNode() will return %NULL or not + */ + bool isUnknown() const; + + /** + * Break the current reference + * @param root root node + * + * This is called when the referenced node is going away. + * + * The root node is passed for two reasons: + * @li it doesn't need to be searched again for every ref node which + * can be many in case of an important key node get's deleted + * @li the ref node may be a child of the deleted node, then we can + * not call the parents functions to find the root anymore. This helps + * simplifying the code + */ + void unRef(KGpgRootNode *root); + +private Q_SLOTS: + void keyUpdated(KGpgKeyNode *); +}; + +#endif /* KGPGREFNODE_H */ diff --git a/kgpg/core/KGpgRootNode.cpp b/kgpg/core/KGpgRootNode.cpp new file mode 100644 index 0000000..9ceb571 --- /dev/null +++ b/kgpg/core/KGpgRootNode.cpp @@ -0,0 +1,189 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgRootNode.h" + +#include "KGpgGroupNode.h" +#include "../kgpginterface.h" +#include "KGpgOrphanNode.h" +//#include "kgpgsettings.h" + +#include +#include + +KGpgRootNode::KGpgRootNode(KGpgItemModel *model) + : KGpgExpandableNode(NULL), + m_groups(0), + m_deleting(false) +{ + m_model = model; +} + +KGpgRootNode::~KGpgRootNode() +{ + m_deleting = true; +} + +void +KGpgRootNode::readChildren() +{ +} + +KgpgCore::KgpgItemType +KGpgRootNode::getType() const +{ + return 0; +} + +void +KGpgRootNode::addGroups(const QStringList &groups) +{ + foreach (const QString &group, groups) { + QStringList members = group.split(QLatin1Char(' ')); + const QString groupName = members.takeFirst(); + new KGpgGroupNode(this, groupName, members); + } +} + +void +KGpgRootNode::addKeys(const QStringList &ids) +{ + KgpgCore::KgpgKeyList publiclist = KgpgInterface::readPublicKeys(ids); + KgpgCore::KgpgKeyList secretlist = KgpgInterface::readSecretKeys(); + + QStringList issec = secretlist; + + for (int i = 0; i < publiclist.size(); ++i) { + KgpgCore::KgpgKey key = publiclist.at(i); + + int index = issec.indexOf(key.fullId()); + if (index != -1) { + key.setSecret(true); + issec.removeAt(index); + secretlist.removeAt(index); + } + + KGpgKeyNode *nd = new KGpgKeyNode(this, key); + emit newKeyNode(nd); + } + + for (int i = 0; i < secretlist.count(); ++i) { + KgpgCore::KgpgKey key = secretlist.at(i); + + new KGpgOrphanNode(this, key); + } +} + +void +KGpgRootNode::refreshKeys(KGpgKeyNode::List nodes) +{ + QStringList ids; + + foreach (const KGpgNode *nd, nodes) + ids << nd->getId(); + + KgpgCore::KgpgKeyList publiclist = KgpgInterface::readPublicKeys(ids); + QStringList issec = KgpgInterface::readSecretKeys(ids); + + for (int i = 0; i < publiclist.size(); ++i) { + KgpgCore::KgpgKey key = publiclist.at(i); + + int index = issec.indexOf(key.fullId()); + if (index != -1) { + key.setSecret(true); + issec.removeAt(index); + } + + for (int j = 0; j < nodes.count(); j++) { + KGpgKeyNode *nd = nodes.at(j); + + if (nd->getId() == key.fingerprint()) { + nodes.removeAt(j); + nd->setKey(key); + break; + } + } + } +} + +KGpgKeyNode * +KGpgRootNode::findKey(const QString &keyId) +{ + int i = findKeyRow(keyId); + if (i >= 0) { + return children[i]->toKeyNode(); + } + + return NULL; +} + +int +KGpgRootNode::findKeyRow(const QString &keyId) +{ + int i = 0; + + foreach (const KGpgNode *node, children) { + if ((node->getType() & ITYPE_PAIR) == 0) { + ++i; + continue; + } + + const KGpgKeyNode *key = node->toKeyNode(); + + if (key->compareId(keyId)) + return i; + ++i; + } + return -1; +} + +int +KGpgRootNode::groupChildren() const +{ + return m_groups; +} + +int +KGpgRootNode::findKeyRow(const KGpgKeyNode *key) +{ + for (int i = 0; i < children.count(); i++) { + if (children[i] == key) + return i; + } + return -1; +} + +KGpgRootNode * +KGpgRootNode::asRootNode() +{ + if (m_deleting) + return NULL; + + return this; +} + +const KGpgRootNode * +KGpgRootNode::asRootNode() const +{ + if (m_deleting) + return NULL; + + return this; +} + +//#include "KGpgRootNode.moc" diff --git a/kgpg/core/KGpgRootNode.h b/kgpg/core/KGpgRootNode.h new file mode 100644 index 0000000..97c597c --- /dev/null +++ b/kgpg/core/KGpgRootNode.h @@ -0,0 +1,129 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGROOTNODE_H +#define KGPGROOTNODE_H + +#include "KGpgExpandableNode.h" +#include "KGpgKeyNode.h" + +class KGpgGroupNode; +class QString; +class QStringList; + +/** + * @brief The parent of all key data objects + * + * This object is invisible to the user but acts as the internal base object for + * everything in the keyring. It is anchestor of all other KGpgNode objects and + * the only one that will ever return NULL when calling getParentKeyNode() on it. + * + * There is only one object of this type around at any time. + */ +class KGpgRootNode : public KGpgExpandableNode +{ + Q_OBJECT + + friend class KGpgGroupNode; + +private: + int m_groups; + int m_deleting; + +protected: + virtual void readChildren(); + +public: + explicit KGpgRootNode(KGpgItemModel *model); + virtual ~KGpgRootNode(); + + virtual KgpgCore::KgpgItemType getType() const; + + /** + * Create new group nodes + * @param groups list of group names to create + */ + void addGroups(const QStringList &groups); + void addKeys(const QStringList &ids = QStringList()); + void refreshKeys(KGpgKeyNode::List nodes); + /** + * Find a key node with the given id + * + * This scans the list of primary keys for a key with the given id + * and returns the corresponding key node. + * + * The key id will be matched against the characters given in keyId. + * If you give only 8 or 16 byte you will still find the key if it + * exists. To be really sure to find the correct node you should pass + * the complete fingerprint whenever possible. + * + * @param keyId the key id to find, any length is permitted + * @return pointer to key node or %NULL if no such key + */ + KGpgKeyNode *findKey(const QString &keyId); + /** + * Return the child number of the key with the given id + * + * This scans the list of direct children for a key with the given + * key id. It returns the number in the internal list of children + * which is identical to the row number in the item model. Since + * proxy models may sort the items you should only call this function + * from the primary model (i.e. KGpgItemModel). + * + * The key id will be matched against the characters given in keyId. + * If you give only 8 or 16 byte you will still find the key if it + * exists. To be really sure to find the correct node you should pass + * the complete fingerprint whenever possible. + * + * @param keyId the key id to find, any length is permitted + * @return the child number or -1 if there is no such key + */ + int findKeyRow(const QString &keyId); + + /** + * Return the child number of the given key + * @param key the key to search for + * + * @overload + */ + int findKeyRow(const KGpgKeyNode *key); + + /** + * Return the group count + * @return the number of group nodes + */ + int groupChildren() const; + + /** + * Return a pointer to this object or NULL + * + * This returns a pointer to this object if the object will persist, + * i.e. is not currently in destruction. If the object is already + * cleaning up NULL is returned. + */ + KGpgRootNode *asRootNode(); + /** + * @overload + */ + const KGpgRootNode *asRootNode() const; + +Q_SIGNALS: + void newKeyNode(KGpgKeyNode *); +}; + +#endif /* KGPGROOTNODE_H */ diff --git a/kgpg/core/KGpgSignNode.cpp b/kgpg/core/KGpgSignNode.cpp new file mode 100644 index 0000000..f35bd9a --- /dev/null +++ b/kgpg/core/KGpgSignNode.cpp @@ -0,0 +1,95 @@ +/* Copyright 2008,2009,2010 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgSignNode.h" + +#include "KGpgSignableNode.h" + +//#include +#include + +class KGpgSignNodePrivate { +public: + KGpgSignNodePrivate(const QStringList &sl); + + QDateTime m_creation; + QDateTime m_expiration; + bool m_local; + bool m_revocation; +}; + +KGpgSignNodePrivate::KGpgSignNodePrivate(const QStringList &sl) +{ + m_revocation = (sl.at(0) == QLatin1String("rev")); + if (sl.count() < 6) + return; + m_creation = QDateTime::fromTime_t(sl.at(5).toUInt()); + if (sl.count() < 7) + return; + if (!sl.at(6).isEmpty()) + m_expiration = QDateTime::fromTime_t(sl.at(6).toUInt()); + if (sl.count() < 11) + return; + m_local = sl.at(10).endsWith(QLatin1Char( 'l' )); +} + +KGpgSignNode::KGpgSignNode(KGpgSignableNode *parent, const QStringList &s) + : KGpgRefNode(parent, s.at(4)), + d_ptr(new KGpgSignNodePrivate(s)) +{ +} + +KGpgSignNode::~KGpgSignNode() +{ + delete d_ptr; +} + +QDateTime +KGpgSignNode::getExpiration() const +{ + const Q_D(KGpgSignNode); + + return d->m_expiration; +} + +QDateTime +KGpgSignNode::getCreation() const +{ + const Q_D(KGpgSignNode); + + return d->m_creation; +} + +QString +KGpgSignNode::getName() const +{ + const Q_D(KGpgSignNode); + const QString name = KGpgRefNode::getName(); + + if (!d->m_local) + return name; + + //return tr("%1 [local signature]", &name.constData()->toAscii()); + return "fixme"; +} + +KgpgCore::KgpgItemType +KGpgSignNode::getType() const +{ + return KgpgCore::ITYPE_SIGN; +} diff --git a/kgpg/core/KGpgSignNode.h b/kgpg/core/KGpgSignNode.h new file mode 100644 index 0000000..398ee57 --- /dev/null +++ b/kgpg/core/KGpgSignNode.h @@ -0,0 +1,54 @@ +/* Copyright 2008,2009,2010 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGSIGNNODE_H +#define KGPGSIGNNODE_H + +#include "KGpgRefNode.h" + +class KGpgSignableNode; + +class KGpgSignNodePrivate; + +/** + * @brief A signature to another key object + */ +class KGpgSignNode : public KGpgRefNode +{ +private: + KGpgSignNodePrivate * const d_ptr; + Q_DECLARE_PRIVATE(KGpgSignNode) + +public: + typedef QList List; + + /** + * @brief constructor for KGpgSignNode + * @param parent the signed node + * @param s GnuPG line describing this signature + */ + explicit KGpgSignNode(KGpgSignableNode *parent, const QStringList &s); + virtual ~KGpgSignNode(); + + virtual KgpgCore::KgpgItemType getType() const; + virtual QDateTime getExpiration() const; + virtual QString getName() const; + virtual QDateTime getCreation() const; +}; + +#endif /* KGPGSIGNNODE_H */ diff --git a/kgpg/core/KGpgSignableNode.cpp b/kgpg/core/KGpgSignableNode.cpp new file mode 100644 index 0000000..e3782c1 --- /dev/null +++ b/kgpg/core/KGpgSignableNode.cpp @@ -0,0 +1,99 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgSignableNode.h" + +//#include + +KGpgSignableNode::KGpgSignableNode(KGpgExpandableNode *parent) + : KGpgExpandableNode(parent) +{ +} + +KGpgSignableNode::~KGpgSignableNode() +{ +} + +KGpgSignNode::List +KGpgSignableNode::getSignatures(void) const +{ + KGpgSignNode::List ret; + + foreach (KGpgNode *kn, children) { + if (kn->getType() == KgpgCore::ITYPE_SIGN) + ret << kn->toSignNode(); + } + + return ret; +} + +QString +KGpgSignableNode::getSignCount() const +{ + //return i18np("1 signature", "%1 signatures", children.count()); + return tr("1 signature", "%1 signatures", children.count()); +} + +bool +KGpgSignableNode::operator<(const KGpgSignableNode &other) const +{ + return operator<(&other); +} + +bool +KGpgSignableNode::operator<(const KGpgSignableNode *other) const +{ + switch (getType()) { + case KgpgCore::ITYPE_PUBLIC: + case KgpgCore::ITYPE_PAIR: { + const QString myid(getId()); + + switch (other->getType()) { + case KgpgCore::ITYPE_PUBLIC: + case KgpgCore::ITYPE_PAIR: + return (myid < other->getId()); + default: { + const QString otherid(other->getParentKeyNode()->getId()); + + if (myid == otherid) + return true; + return (myid < otherid); + } + } + } + default: { + const QString myp(getParentKeyNode()->getId()); + + switch (other->getType()) { + case KgpgCore::ITYPE_PAIR: + case KgpgCore::ITYPE_PUBLIC: + return (myp < other->getId()); + default: { + const QString otherp(other->getParentKeyNode()->getId()); + + if (otherp == myp) + return (getId().toInt() < other->getId().toInt()); + + return (myp < otherp); + } + } + } + } +} + +//#include "KGpgSignableNode.moc" diff --git a/kgpg/core/KGpgSignableNode.h b/kgpg/core/KGpgSignableNode.h new file mode 100644 index 0000000..fddae25 --- /dev/null +++ b/kgpg/core/KGpgSignableNode.h @@ -0,0 +1,62 @@ +/* Copyright 2008,2009,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGSIGNABLENODE_H +#define KGPGSIGNABLENODE_H + +#include "KGpgExpandableNode.h" +#include "KGpgSignNode.h" + +/** + * @brief An object that may have KGpgSignNode children + * + * This class represents an object that may be signed, i.e. key nodes, + * user ids, user attributes, and subkeys. + */ +class KGpgSignableNode : public KGpgExpandableNode +{ + Q_OBJECT + +public: + typedef QList List; + typedef QList const_List; + + KGpgSignableNode(KGpgExpandableNode *parent = NULL); + virtual ~KGpgSignableNode(); + + KGpgSignNode::List getSignatures(void) const; + /** + * @brief count signatures + * @return the number of signatures to this object + * + * This does not include the number of signatures to child objects. + */ + virtual QString getSignCount() const; + + bool operator<(const KGpgSignableNode &other) const; + bool operator<(const KGpgSignableNode *other) const; + + /** + * @brief returns the key node this node belongs to + * @returns this node if the node itself is a key or it's parent otherwise + */ + virtual KGpgKeyNode *getKeyNode(void) = 0; + virtual const KGpgKeyNode *getKeyNode(void) const = 0; +}; + +#endif /* KGPGSIGNABLENODE_H */ diff --git a/kgpg/core/KGpgSubkeyNode.cpp b/kgpg/core/KGpgSubkeyNode.cpp new file mode 100644 index 0000000..571ca35 --- /dev/null +++ b/kgpg/core/KGpgSubkeyNode.cpp @@ -0,0 +1,100 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgSubkeyNode.h" + +//#include + +#include "convert.h" +#include "KGpgKeyNode.h" + +KGpgSubkeyNode::KGpgSubkeyNode(KGpgKeyNode *parent, const KgpgKeySub &k) + : KGpgSignableNode(parent), + m_skey(k) +{ + Q_ASSERT(parent != NULL); +} +KGpgSubkeyNode::~KGpgSubkeyNode() +{ +} + +void +KGpgSubkeyNode::readChildren() +{ +} + +KgpgCore::KgpgItemType +KGpgSubkeyNode::getType() const +{ + return ITYPE_SUB; +} + +KgpgCore::KgpgKeyTrust +KGpgSubkeyNode::getTrust() const +{ + return m_skey.trust(); +} + +QDateTime +KGpgSubkeyNode::getExpiration() const +{ + return m_skey.expirationDate(); +} + +QDateTime +KGpgSubkeyNode::getCreation() const +{ + return m_skey.creationDate(); +} + +QString +KGpgSubkeyNode::getId() const +{ + return m_skey.id(); +} + +KGpgKeyNode * +KGpgSubkeyNode::getKeyNode(void) +{ + return getParentKeyNode()->toKeyNode(); +} + +const KGpgKeyNode * +KGpgSubkeyNode::getKeyNode(void) const +{ + return getParentKeyNode()->toKeyNode(); +} + +QString +KGpgSubkeyNode::getName() const +{ + //return i18n("%1 subkey", Convert::toString(m_skey.algorithm())); + return "TODO"; +} + +QString +KGpgSubkeyNode::getSize() const +{ + return QString::number(m_skey.size()); +} + +KGpgKeyNode * +KGpgSubkeyNode::getParentKeyNode() const +{ + return m_parent->toKeyNode(); +} diff --git a/kgpg/core/KGpgSubkeyNode.h b/kgpg/core/KGpgSubkeyNode.h new file mode 100644 index 0000000..bbe5ab8 --- /dev/null +++ b/kgpg/core/KGpgSubkeyNode.h @@ -0,0 +1,55 @@ +/* Copyright 2008,2009 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGSUBKEYNODE_H +#define KGPGSUBKEYNODE_H + +#include "KGpgSignableNode.h" + +#include "kgpgkey.h" + +using namespace KgpgCore; + +/** + * @brief a subkey of a public key or key pair + */ +class KGpgSubkeyNode : public KGpgSignableNode +{ +private: + KgpgCore::KgpgKeySub m_skey; + +protected: + virtual void readChildren(); + +public: + explicit KGpgSubkeyNode(KGpgKeyNode *parent, const KgpgCore::KgpgKeySub &k); + virtual ~KGpgSubkeyNode(); + + virtual KgpgCore::KgpgItemType getType() const; + virtual KgpgCore::KgpgKeyTrust getTrust() const; + virtual QString getSize() const; + virtual QString getName() const; + virtual QDateTime getExpiration() const; + virtual QDateTime getCreation() const; + virtual QString getId() const; + virtual KGpgKeyNode *getKeyNode(void); + virtual const KGpgKeyNode *getKeyNode(void) const; + virtual KGpgKeyNode *getParentKeyNode() const; +}; + +#endif /* KGPGSUBKEYNODE_H */ diff --git a/kgpg/core/KGpgUatNode.cpp b/kgpg/core/KGpgUatNode.cpp new file mode 100644 index 0000000..174db66 --- /dev/null +++ b/kgpg/core/KGpgUatNode.cpp @@ -0,0 +1,174 @@ +/* Copyright 2008,2009,2010,2012 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgUatNode.h" + +#include "../gpgproc.h" +#include "KGpgKeyNode.h" + +//#include +//#include + +#include +#include +#include +#include +#include + +class KGpgUatNodePrivate { +public: + KGpgUatNodePrivate(const KGpgKeyNode *parent, const unsigned int index, const QStringList &sl); + + const QString m_idx; + const QPixmap m_pixmap; + QDateTime m_creation; + +private: + static QPixmap loadImage(const KGpgKeyNode *parent, const QString &index); +}; + +KGpgUatNodePrivate::KGpgUatNodePrivate(const KGpgKeyNode *parent, const unsigned int index, const QStringList &sl) + : m_idx(QString::number(index)), + m_pixmap(loadImage(parent, m_idx)) +{ + if (sl.count() < 6) + return; + m_creation = QDateTime::fromTime_t(sl.at(5).toUInt()); +} + +QPixmap +KGpgUatNodePrivate::loadImage(const KGpgKeyNode *parent, const QString &index) +{ + QPixmap pixmap; +#ifdef Q_OS_WIN32 //krazy:exclude=cpp + const QString pgpgoutput = QLatin1String("cmd /C \"echo %I\""); +#else + const QString pgpgoutput = QLatin1String("echo %I"); +#endif + + GPGProc workProcess; + workProcess << + QLatin1String("--no-greeting") << + QLatin1String("--status-fd=2") << + QLatin1String("--photo-viewer") << pgpgoutput << + QLatin1String("--edit-key") << parent->getFingerprint() << + QLatin1String( "uid" ) << index << + QLatin1String( "showphoto" ) << + QLatin1String( "quit" ); + + workProcess.start(); + workProcess.waitForFinished(); + if (workProcess.exitCode() != 0) + return pixmap; + + QString tmpfile; + if (workProcess.readln(tmpfile) < 0) + return pixmap; + + QUrl url(tmpfile); + pixmap.load(url.path()); + QFile::remove(url.path()); + QDir dir; + //dir.rmdir(url.directory()); + + return pixmap; +} + +KGpgUatNode::KGpgUatNode(KGpgKeyNode *parent, const unsigned int index, const QStringList &sl) + : KGpgSignableNode(parent), + d_ptr(new KGpgUatNodePrivate(parent, index, sl)) +{ +} + +KGpgUatNode::~KGpgUatNode() +{ + delete d_ptr; +} + +QString +KGpgUatNode::getName() const +{ + return tr("Photo id"); +} + +QString +KGpgUatNode::getSize() const +{ + const Q_D(KGpgUatNode); + + return QString::number(d->m_pixmap.width()) + QLatin1Char( 'x' ) + QString::number(d->m_pixmap.height()); +} + +QDateTime +KGpgUatNode::getCreation() const +{ + const Q_D(KGpgUatNode); + + return d->m_creation; +} + +KGpgKeyNode * +KGpgUatNode::getParentKeyNode() const +{ + return m_parent->toKeyNode(); +} + +void +KGpgUatNode::readChildren() +{ +} + +KgpgCore::KgpgItemType +KGpgUatNode::getType() const +{ + return KgpgCore::ITYPE_UAT; +} + +KgpgCore::KgpgKeyTrust +KGpgUatNode::getTrust() const +{ + return KgpgCore::TRUST_NOKEY; +} + +const QPixmap & +KGpgUatNode::getPixmap() const +{ + const Q_D(KGpgUatNode); + + return d->m_pixmap; +} + +QString +KGpgUatNode::getId() const +{ + const Q_D(KGpgUatNode); + + return d->m_idx; +} + +KGpgKeyNode * +KGpgUatNode::getKeyNode(void) +{ + return getParentKeyNode()->toKeyNode(); +} + +const KGpgKeyNode * +KGpgUatNode::getKeyNode(void) const +{ + return getParentKeyNode()->toKeyNode(); +} diff --git a/kgpg/core/KGpgUatNode.h b/kgpg/core/KGpgUatNode.h new file mode 100644 index 0000000..b4c6775 --- /dev/null +++ b/kgpg/core/KGpgUatNode.h @@ -0,0 +1,61 @@ +/* Copyright 2008,2009,2010 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGUATNODE_H +#define KGPGUATNODE_H + +#include "KGpgSignableNode.h" + +#include +#include + +class KGpgExpandableNode; +class KGpgKeyNode; +class QPixmap; + +class KGpgUatNodePrivate; + +/** + * @brief A user attribute (i.e. photo id) of a public key or key pair + */ +class KGpgUatNode : public KGpgSignableNode +{ +private: + KGpgUatNodePrivate * const d_ptr; + Q_DECLARE_PRIVATE(KGpgUatNode) + +protected: + virtual void readChildren(); + +public: + explicit KGpgUatNode(KGpgKeyNode *parent, const unsigned int index, const QStringList &sl); + virtual ~KGpgUatNode(); + + virtual KgpgCore::KgpgItemType getType() const; + virtual KgpgCore::KgpgKeyTrust getTrust() const; + const QPixmap &getPixmap() const; + virtual QString getId() const; + virtual QString getSize() const; + virtual QString getName() const; + virtual QDateTime getCreation() const; + virtual KGpgKeyNode *getParentKeyNode() const; + virtual KGpgKeyNode *getKeyNode(void); + virtual const KGpgKeyNode *getKeyNode(void) const; +}; + +#endif /* KGPGUATNODE_H */ diff --git a/kgpg/core/KGpgUidNode.cpp b/kgpg/core/KGpgUidNode.cpp new file mode 100644 index 0000000..0be6c10 --- /dev/null +++ b/kgpg/core/KGpgUidNode.cpp @@ -0,0 +1,146 @@ +/* Copyright 2008,2009,2010 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#include "KGpgUidNode.h" + +#include "KGpgKeyNode.h" +#include "convert.h" + +class KGpgUidNodePrivate { +public: + KGpgUidNodePrivate(const unsigned int index, const QStringList &sl); + + const QString m_index; + QString m_email; + QString m_name; + QString m_comment; + KgpgCore::KgpgKeyTrust m_trust; + bool m_valid; +}; + +KGpgUidNodePrivate::KGpgUidNodePrivate(const unsigned int index, const QStringList &sl) + : m_index(QString::number(index)) +{ + QString fullname(sl.at(9)); + if (fullname.contains(QLatin1Char( '<' )) ) { + m_email = fullname; + + if (fullname.contains(QLatin1Char( ')' )) ) + m_email = m_email.section(QLatin1Char( ')' ), 1); + + m_email = m_email.section(QLatin1Char( '<' ), 1); + m_email.truncate(m_email.length() - 1); + + if (m_email.contains(QLatin1Char( '<' ))) { + // several email addresses in the same key + m_email = m_email.replace(QLatin1Char( '>' ), QLatin1Char( ';' )); + m_email.remove(QLatin1Char( '<' )); + } + } + + m_name = fullname.section(QLatin1String( " <" ), 0, 0); + if (fullname.contains(QLatin1Char( '(' )) ) { + m_name = m_name.section(QLatin1String( " (" ), 0, 0); + m_comment = fullname.section(QLatin1Char( '(' ), 1, 1); + m_comment = m_comment.section(QLatin1Char( ')' ), 0, 0); + } + + m_trust = KgpgCore::Convert::toTrust(sl.at(1)); + m_valid = ((sl.count() <= 11) || !sl.at(11).contains(QLatin1Char( 'D' ))); +} + + +KGpgUidNode::KGpgUidNode(KGpgKeyNode *parent, const unsigned int index, const QStringList &sl) + : KGpgSignableNode(parent), + d_ptr(new KGpgUidNodePrivate(index, sl)) +{ +} + +KGpgUidNode::~KGpgUidNode() +{ + delete d_ptr; +} + +QString +KGpgUidNode::getName() const +{ + const Q_D(KGpgUidNode); + + return d->m_name; +} + +QString +KGpgUidNode::getEmail() const +{ + const Q_D(KGpgUidNode); + + return d->m_email; +} + +QString +KGpgUidNode::getId() const +{ + const Q_D(KGpgUidNode); + + return d->m_index; +} + +KGpgKeyNode * +KGpgUidNode::getKeyNode(void) +{ + return getParentKeyNode()->toKeyNode(); +} + +const KGpgKeyNode * +KGpgUidNode::getKeyNode(void) const +{ + return getParentKeyNode()->toKeyNode(); +} + +KGpgKeyNode * +KGpgUidNode::getParentKeyNode() const +{ + return m_parent->toKeyNode(); +} + +void +KGpgUidNode::readChildren() +{ +} + +KgpgCore::KgpgItemType +KGpgUidNode::getType() const +{ + return KgpgCore::ITYPE_UID; +} + +KgpgCore::KgpgKeyTrust +KGpgUidNode::getTrust() const +{ + const Q_D(KGpgUidNode); + + return d->m_trust; +} + +QString +KGpgUidNode::getComment() const +{ + const Q_D(KGpgUidNode); + + return d->m_comment; +} diff --git a/kgpg/core/KGpgUidNode.h b/kgpg/core/KGpgUidNode.h new file mode 100644 index 0000000..cd1b563 --- /dev/null +++ b/kgpg/core/KGpgUidNode.h @@ -0,0 +1,57 @@ +/* Copyright 2008,2009,2010 Rolf Eike Beer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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, see . + */ +#ifndef KGPGUIDNODE_H +#define KGPGUIDNODE_H + +#include "KGpgSignableNode.h" + +#include "kgpgkey.h" + +class KGpgKeyNode; + +class KGpgUidNodePrivate; + +/** + * @brief A user id of a public key or key pair + */ +class KGpgUidNode : public KGpgSignableNode +{ +private: + KGpgUidNodePrivate * const d_ptr; + Q_DECLARE_PRIVATE(KGpgUidNode) + +protected: + virtual void readChildren(); + +public: + explicit KGpgUidNode(KGpgKeyNode *parent, const unsigned int index, const QStringList &sl); + virtual ~KGpgUidNode(); + + virtual KgpgCore::KgpgItemType getType() const; + virtual KgpgCore::KgpgKeyTrust getTrust() const; + virtual QString getName() const; + virtual QString getEmail() const; + virtual QString getId() const; + virtual KGpgKeyNode *getKeyNode(void); + virtual const KGpgKeyNode *getKeyNode(void) const; + virtual KGpgKeyNode *getParentKeyNode() const; + virtual QString getComment() const; +}; + +#endif /* KGPGUIDNODE_H */ diff --git a/kgpg/core/convert.cpp b/kgpg/core/convert.cpp new file mode 100644 index 0000000..934ec02 --- /dev/null +++ b/kgpg/core/convert.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2006 Jimmy Gilles + * Copyright (C) 2010 Rolf Eike Beer + */ +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "convert.h" + +//#include +//#include +#include +//#include "kgpgsettings.h" +#include "images.h" + +namespace KgpgCore +{ + +QString Convert::toString(const KgpgKeyAlgo algorithm) +{ + switch (algorithm) + { + case ALGO_RSA: return QObject::tr("Encryption algorithm", "RSA"); + case ALGO_DSA: return QObject::tr("Encryption algorithm", "DSA"); + case ALGO_ELGAMAL: return QObject::tr("Encryption algorithm", "ElGamal"); + case ALGO_DSA_ELGAMAL: return QObject::tr("Encryption algorithm", "DSA & ElGamal"); + case ALGO_RSA_RSA: return QObject::tr("Encryption algorithm RSA, Signing algorithm RSA", "RSA & RSA"); + case ALGO_UNKNOWN: + default: return QObject::tr("Unknown algorithm", "Unknown"); + } +} + +QString Convert::toString(const KgpgKeyOwnerTrust ownertrust) +{ + switch (ownertrust) + { + case OWTRUST_UNDEFINED: return QObject::tr("Do not Know"); + case OWTRUST_NONE: return QObject::tr("Do NOT Trust"); + case OWTRUST_MARGINAL: return QObject::tr("Marginally"); + case OWTRUST_FULL: return QObject::tr("Fully"); + case OWTRUST_ULTIMATE: return QObject::tr("Ultimately"); + case OWTRUST_UNKNOWN: + default: return QObject::tr("Unknown trust in key owner", "Unknown"); + } +} + +QString Convert::toString(const KgpgKeyTrust trust) +{ + switch (trust) + { + case TRUST_INVALID: return QObject::tr("Invalid key", "Invalid"); + case TRUST_DISABLED: return QObject::tr("Disabled key", "Disabled"); + case TRUST_REVOKED: return QObject::tr("Revoked"); + case TRUST_EXPIRED: return QObject::tr("Expired key", "Expired"); + case TRUST_UNDEFINED: return QObject::tr("Undefined key trust", "Undefined"); + case TRUST_NONE: return QObject::tr("No trust in key", "None"); + case TRUST_MARGINAL: return QObject::tr("Marginal trust in key", "Marginal"); + case TRUST_FULL: return QObject::tr("Full trust in key", "Full"); + case TRUST_ULTIMATE: return QObject::tr("Ultimate trust in key", "Ultimate"); + case TRUST_UNKNOWN: + default: return QObject::tr("Unknown trust in key", "Unknown"); + } +} + +QColor Convert::toColor(const KgpgKeyTrust trust) +{ + switch (trust) + { + case TRUST_INVALID: + /*case TRUST_DISABLED: return KGpgSettings::colorBad(); + case TRUST_EXPIRED: return KGpgSettings::colorExpired(); + case TRUST_MARGINAL: return KGpgSettings::colorMarginal(); + case TRUST_REVOKED: return KGpgSettings::colorRev(); + case TRUST_UNDEFINED: + case TRUST_NONE: return KGpgSettings::colorUnknown(); + case TRUST_FULL: return KGpgSettings::colorGood(); + case TRUST_ULTIMATE: return KGpgSettings::colorUltimate();*/ + case TRUST_UNKNOWN: + default: return QColor(0,0,0); + //return KGpgSettings::colorUnknown(); + } +} + +QString Convert::toString(const QDate &date) +{ + //return KGlobal::locale()->formatDate(date, KLocale::ShortDate); +} + +KgpgKeyAlgo Convert::toAlgo(const uint v) +{ + switch (v) + { + case 1: return ALGO_RSA; + case 16: + case 20: return ALGO_ELGAMAL; + case 17: return ALGO_DSA; + default: return ALGO_UNKNOWN; + } +} + +KgpgKeyAlgo Convert::toAlgo(const QString &s) +{ + bool b; + unsigned int u = s.toUInt(&b); + return b ? toAlgo(u) : ALGO_UNKNOWN; +} + +KgpgKeyTrust Convert::toTrust(const QChar &c) +{ + switch (c.toAscii()) + { + case 'o': return TRUST_UNKNOWN; + case 'i': return TRUST_INVALID; + case 'd': return TRUST_DISABLED; + case 'r': return TRUST_REVOKED; + case 'e': return TRUST_EXPIRED; + case 'q': return TRUST_UNDEFINED; + case 'n': return TRUST_NONE; + case 'm': return TRUST_MARGINAL; + case 'f': return TRUST_FULL; + case 'u': return TRUST_ULTIMATE; + default: return TRUST_UNKNOWN; + } +} + +KgpgKeyTrust Convert::toTrust(const QString &s) +{ + return s.isEmpty() ? TRUST_UNKNOWN : toTrust(s[0]); +} + +KgpgKeyOwnerTrust Convert::toOwnerTrust(const QChar &c) +{ + switch (c.toAscii()) + { + case 'n': return OWTRUST_NONE; + case 'm': return OWTRUST_MARGINAL; + case 'u': return OWTRUST_ULTIMATE; + case 'f': return OWTRUST_FULL; + default: return OWTRUST_UNDEFINED; + } +} + +KgpgKeyOwnerTrust Convert::toOwnerTrust(const QString &s) +{ + return s.isEmpty() ? OWTRUST_UNDEFINED : toOwnerTrust(s[0]); +} + +QPixmap Convert::toPixmap(const KgpgItemType t) +{ + switch (t) + { + case ITYPE_GROUP: return Images::group(); + case ITYPE_GSECRET: + case ITYPE_SECRET: return Images::orphan(); + case ITYPE_GPUBLIC: + case ITYPE_SUB: + case ITYPE_PUBLIC: return Images::single(); + case ITYPE_GPAIR: + case ITYPE_PAIR: return Images::pair(); + case ITYPE_UID: return Images::userId(); + case ITYPE_UAT: return Images::photo(); + case ITYPE_REVSIGN: return Images::revoke(); + case ITYPE_SIGN: return Images::signature(); + default: Q_ASSERT(1); + return NULL; + } +} + +} // namespace KgpgCore diff --git a/kgpg/core/convert.h b/kgpg/core/convert.h new file mode 100644 index 0000000..96043a8 --- /dev/null +++ b/kgpg/core/convert.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2006 Jimmy Gilles + * Copyright (C) 2010 Rolf Eike Beer + */ +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef CONVERT_H +#define CONVERT_H + +#include "kgpgkey.h" + +class QColor; +class QString; +class QPixmap; + +namespace KgpgCore +{ + +class Convert +{ +public: + static QString toString(const KgpgCore::KgpgKeyAlgo algorithm); + static QString toString(const KgpgCore::KgpgKeyOwnerTrust ownertrust); + static QString toString(const KgpgCore::KgpgKeyTrust trust); + static QString toString(const QDate &date); + static QColor toColor(const KgpgCore::KgpgKeyTrust trust); + static KgpgKeyAlgo toAlgo(const uint v); + static KgpgKeyAlgo toAlgo(const QString &s); + static KgpgKeyTrust toTrust(const QChar &c); + static KgpgKeyTrust toTrust(const QString &s); + static KgpgKeyOwnerTrust toOwnerTrust(const QChar &c); + static KgpgKeyOwnerTrust toOwnerTrust(const QString &s); + static QPixmap toPixmap(const KgpgCore::KgpgItemType t); +}; + +} // namespace KgpgCore + +#endif // CONVERT_H diff --git a/kgpg/core/images.cpp b/kgpg/core/images.cpp new file mode 100644 index 0000000..c63dceb --- /dev/null +++ b/kgpg/core/images.cpp @@ -0,0 +1,100 @@ +/*************************************************************************** + * Copyright (C) 2006 by Jimmy Gilles * + * jimmygilles@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "images.h" + +//#include + +namespace KgpgCore +{ + +QPixmap Images::single() +{ + static QPixmap single; +// if (single.isNull()) +// single = KIconLoader::global()->loadIcon(QLatin1String( "key-single" ), KIconLoader::Small, 20); + return single; +} + +QPixmap Images::pair() +{ + static QPixmap pair; +// if (pair.isNull()) +// pair = KIconLoader::global()->loadIcon(QLatin1String( "key-pair" ), KIconLoader::Small, 20); + return pair; +} + +QPixmap Images::group() +{ + static QPixmap group; +// if (group.isNull()) +// group = KIconLoader::global()->loadIcon(QLatin1String( "key-group" ), KIconLoader::Small, 20); + return group; +} + +QPixmap Images::orphan() +{ + static QPixmap oprpan; +// if (oprpan.isNull()) +// oprpan = KIconLoader::global()->loadIcon(QLatin1String( "key-orphan" ), KIconLoader::Small, 20); + return oprpan; +} + +QPixmap Images::signature() +{ + static QPixmap signature; +// if (signature.isNull()) +// signature = KIconLoader::global()->loadIcon(QLatin1String( "application-pgp-signature" ), KIconLoader::Small, 20); + return signature; +} + +QPixmap Images::userId() +{ + static QPixmap userid; +// if (userid.isNull()) +// userid = KIconLoader::global()->loadIcon(QLatin1String( "x-office-contact" ), KIconLoader::Small, 20); + return userid; +} + +QPixmap Images::photo() +{ + static QPixmap photo; +// if (photo.isNull()) +// photo = KIconLoader::global()->loadIcon(QLatin1String( "image-x-generic" ), KIconLoader::Small, 20); + return photo; +} + +QPixmap Images::revoke() +{ + static QPixmap revoke; +// if (revoke.isNull()) +// revoke = KIconLoader::global()->loadIcon(QLatin1String( "dialog-error" ), KIconLoader::Small, 20); + return revoke; +} + +QPixmap Images::kgpg() +{ + static QPixmap kgpg; +// if (kgpg.isNull()) +// kgpg = KIconLoader::global()->loadIcon(QLatin1String( "kgpg" ), KIconLoader::Desktop); + return kgpg; +} + +} // namespace KgpgCore diff --git a/kgpg/core/images.h b/kgpg/core/images.h new file mode 100644 index 0000000..739a618 --- /dev/null +++ b/kgpg/core/images.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2006 by Jimmy Gilles * + * jimmygilles@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef IMAGES_H +#define IMAGES_H + +#include + +namespace KgpgCore +{ + +class Images +{ +public: + static QPixmap single(); + static QPixmap pair(); + static QPixmap group(); + static QPixmap orphan(); + static QPixmap signature(); + static QPixmap userId(); + static QPixmap photo(); + static QPixmap revoke(); + + /* Desktop image */ + static QPixmap kgpg(); +}; + +} // namespace KgpgCore + +#endif // IMAGES_H diff --git a/kgpg/core/kgpgkey.cpp b/kgpg/core/kgpgkey.cpp new file mode 100644 index 0000000..57ed820 --- /dev/null +++ b/kgpg/core/kgpgkey.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2006,2007 Jimmy Gilles + * Copyright (C) 2007,2008,2009,2010,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgkey.h" + +#include "convert.h" + +//#include + +#include + +namespace KgpgCore +{ + +//BEGIN KeySub +KgpgKeySubPrivate::KgpgKeySubPrivate(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, + const KgpgSubKeyType type, const QDateTime &date) + : gpgsubid(id), + gpgsubsize(size), + gpgsubcreation(date), + gpgsubtrust(trust), + gpgsubalgo(algo), + gpgsubtype(type) +{ +} + +bool KgpgKeySubPrivate::operator==(const KgpgKeySubPrivate &other) const +{ + if (gpgsubvalid != other.gpgsubvalid) return false; + if (gpgsubalgo != other.gpgsubalgo) return false; + if (gpgsubid != other.gpgsubid) return false; + if (gpgsubsize != other.gpgsubsize) return false; + if (gpgsubexpiration != other.gpgsubexpiration) return false; + if (gpgsubcreation != other.gpgsubcreation) return false; + if (gpgsubtrust != other.gpgsubtrust) return false; + if (gpgsubtype != other.gpgsubtype) return false; + return true; +} + +KgpgKeySub::KgpgKeySub(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const KgpgSubKeyType type, + const QDateTime &date) + : d(new KgpgKeySubPrivate(id, size, trust, algo, type, date)) +{ + d->gpgsubvalid = false; +} + +KgpgKeySub::KgpgKeySub(const KgpgKeySub &other) +{ + d = other.d; +} + +void KgpgKeySub::setExpiration(const QDateTime &date) +{ + d->gpgsubexpiration = date; +} + +void KgpgKeySub::setValid(const bool valid) +{ + d->gpgsubvalid = valid; +} + +QString KgpgKeySub::id() const +{ + return d->gpgsubid; +} + +uint KgpgKeySub::size() const +{ + return d->gpgsubsize; +} + +bool KgpgKeySub::unlimited() const +{ + return d->gpgsubexpiration.isNull(); +} + +QDateTime KgpgKeySub::expirationDate() const +{ + return d->gpgsubexpiration; +} + +QDateTime KgpgKeySub::creationDate() const +{ + return d->gpgsubcreation; +} + +KgpgKeyTrust KgpgKeySub::trust() const +{ + return d->gpgsubtrust; +} + +KgpgKeyAlgo KgpgKeySub::algorithm() const +{ + return d->gpgsubalgo; +} + +bool KgpgKeySub::valid() const +{ + return d->gpgsubvalid; +} + +KgpgSubKeyType KgpgKeySub::type() const +{ + return d->gpgsubtype; +} + +bool KgpgKeySub::operator==(const KgpgKeySub &other) const +{ + if (d == other.d) return true; + if ((*d) == (*(other.d))) return true; + return false; +} + +KgpgKeySub& KgpgKeySub::operator=(const KgpgKeySub &other) +{ + d = other.d; + return *this; +} + +//END KeySub + + +//BEGIN Key + +KgpgKeyPrivate::KgpgKeyPrivate(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const QDateTime &date) + : gpgkeysecret(false), + gpgkeyvalid(false), + gpgkeyid(id), + gpgkeysize(size), + gpgkeytrust(trust), + gpgkeycreation(date), + gpgkeyalgo(algo), + gpgsublist(new KgpgKeySubList()) +{ +} + +bool KgpgKeyPrivate::operator==(const KgpgKeyPrivate &other) const +{ + if (gpgkeysecret != other.gpgkeysecret) return false; + if (gpgkeyvalid != other.gpgkeyvalid) return false; + if (gpgkeymail != other.gpgkeymail) return false; + if (gpgkeyname != other.gpgkeyname) return false; + if (gpgkeycomment != other.gpgkeycomment) return false; + if (gpgkeyfingerprint != other.gpgkeyfingerprint) return false; + if (gpgkeyid != other.gpgkeyid) return false; + if (gpgkeysize != other.gpgkeysize) return false; + if (gpgkeyownertrust != other.gpgkeyownertrust) return false; + if (gpgkeytrust != other.gpgkeytrust) return false; + if (gpgkeycreation != other.gpgkeycreation) return false; + if (gpgkeyexpiration != other.gpgkeyexpiration) return false; + if (gpgkeyalgo != other.gpgkeyalgo) return false; + if (gpgsublist != other.gpgsublist) return false; + return true; +} + +KgpgKey::KgpgKey(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const QDateTime &date) + : d(new KgpgKeyPrivate(id, size, trust, algo, date)) +{ +} + +KgpgKey::KgpgKey(const KgpgKey &other) +{ + d = other.d; +} + +void KgpgKey::setSecret(const bool secret) +{ + d->gpgkeysecret = secret; +} + +void KgpgKey::setValid(const bool valid) +{ + d->gpgkeyvalid = valid; +} + +void KgpgKey::setName(const QString &name) +{ + d->gpgkeyname = name; +} + +void KgpgKey::setEmail(const QString &email) +{ + d->gpgkeymail = email; +} + +void KgpgKey::setComment(const QString &comment) +{ + d->gpgkeycomment = comment; +} + +void KgpgKey::setFingerprint(const QString &fingerprint) +{ + d->gpgkeyfingerprint = fingerprint; +} + +void KgpgKey::setOwnerTrust(const KgpgKeyOwnerTrust &owtrust) +{ + d->gpgkeyownertrust = owtrust; +} + +void KgpgKey::setExpiration(const QDateTime &date) +{ + d->gpgkeyexpiration = date; +} + +bool KgpgKey::secret() const +{ + return d->gpgkeysecret; +} + +bool KgpgKey::valid() const +{ + return d->gpgkeyvalid; +} + +QString KgpgKey::id() const +{ + return d->gpgkeyid.right(8); +} + +QString KgpgKey::fullId() const +{ + return d->gpgkeyid; +} + +QString KgpgKey::name() const +{ + return d->gpgkeyname; +} + +QString KgpgKey::email() const +{ + return d->gpgkeymail; +} + +QString KgpgKey::comment() const +{ + return d->gpgkeycomment; +} + +const QString &KgpgKey::fingerprint() const +{ + return d->gpgkeyfingerprint; +} + +QString KgpgKey::fingerprintBeautified() const +{ + QString fingervalue =d->gpgkeyfingerprint; + uint len = fingervalue.length(); + if ((len > 0) && (len % 4 == 0)) + for (uint n = 0; 4 * (n + 1) < len; ++n) + fingervalue.insert(5 * n + 4, QLatin1Char( ' ' )); + return fingervalue; +} + +uint KgpgKey::size() const +{ + return d->gpgkeysize; +} + +uint KgpgKey::encryptionSize() const +{ + // Get the first encryption subkey + for (int i = 0; i < d->gpgsublist->count(); ++i) { + KgpgKeySub temp = d->gpgsublist->at(i); + if (temp.type() & SKT_ENCRYPTION) { + return temp.size(); + } + } + return 0; +} + +KgpgKeyOwnerTrust KgpgKey::ownerTrust() const +{ + return d->gpgkeyownertrust; +} + +KgpgKeyTrust KgpgKey::trust() const +{ + return d->gpgkeytrust; +} + +QDateTime KgpgKey::creationDate() const +{ + return d->gpgkeycreation; +} + +QDateTime KgpgKey::expirationDate() const +{ + return d->gpgkeyexpiration; +} + +bool KgpgKey::unlimited() const +{ + return d->gpgkeyexpiration.isNull(); +} + +KgpgKeyAlgo KgpgKey::algorithm() const +{ + return d->gpgkeyalgo; +} + +KgpgKeyAlgo KgpgKey::encryptionAlgorithm() const +{ + // Get the first encryption subkey + for (int i = 0; i < d->gpgsublist->count(); ++i) { + KgpgKeySub temp = d->gpgsublist->at(i); + if (temp.type() & SKT_ENCRYPTION) { + return temp.algorithm(); + } + } + return ALGO_UNKNOWN; +} + +KgpgKeySubListPtr KgpgKey::subList() const +{ + return d->gpgsublist; +} + +bool KgpgKey::operator==(const KgpgKey &other) const +{ + if (d == other.d) return true; + if ((*d) == (*(other.d))) return true; + return false; +} + +KgpgKey& KgpgKey::operator=(const KgpgKey &other) +{ + d = other.d; + return *this; +} + +KgpgKeyList::operator QStringList() const +{ + QStringList res; + foreach(const KgpgKey &key, *this) + res << key.fullId(); + return res; +} + +//END Key + +} // namespace KgpgCore diff --git a/kgpg/core/kgpgkey.h b/kgpg/core/kgpgkey.h new file mode 100644 index 0000000..f16907c --- /dev/null +++ b/kgpg/core/kgpgkey.h @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2006,2007 Jimmy Gilles + * Copyright (C) 2007,2008,2009,2010,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGKEY_H +#define KGPGKEY_H + +#include +#include +#include +#include +#include +#include + +class QStringList; + +namespace KgpgCore +{ + +//BEGIN Enums + +enum KgpgKeyAlgoFlag +{ + ALGO_UNKNOWN = 0, + ALGO_RSA = 1, + ALGO_DSA = 2, + ALGO_ELGAMAL = 4, + ALGO_DSA_ELGAMAL = ALGO_DSA | ALGO_ELGAMAL, + ALGO_RSA_RSA = 0x10001 +}; +Q_DECLARE_FLAGS(KgpgKeyAlgo, KgpgKeyAlgoFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(KgpgKeyAlgo) + +/*! \brief trust levels of keys, uids and uats + * + * These values represent the trust that you have in a public key or obe if it's + * user ids or attributes (i.e. photo ids). They are more or less ordered by + * the level of trust. Every value but the first and the last matches one trust + * value that is + */ +enum KgpgKeyTrustFlag +{ + TRUST_MINIMUM = 0, //!< internal value for use in filters + TRUST_INVALID = 1, //!< key is invalid + TRUST_DISABLED = 2, //!< key is disabled by user (not owner) + TRUST_REVOKED = 3, //!< key is revoked by owner + TRUST_EXPIRED = 4, //!< key is beyond it's expiry date + TRUST_UNDEFINED = 5, //!< trust value undefined (i.e. you did not set a trust level) + TRUST_UNKNOWN = 6, //!< trust value unknown (i.e. no entry in gpg's trust database) + TRUST_NONE = 7, //!< there is no trusted path to this key + TRUST_MARGINAL = 8, //!< there is a minimal level of trust + TRUST_FULL = 9, //!< you can fully trust this key + TRUST_ULTIMATE = 10, //!< this key has highest possible level of trust (e.g. your own secret keys) + TRUST_NOKEY = 11 //!< internal value, e.g. for key groups +}; +Q_DECLARE_FLAGS(KgpgKeyTrust, KgpgKeyTrustFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(KgpgKeyTrust) + +/*! \brief trust levels for trust in other key owners + * + * These values represent the trust that you have in other people when they + * sign keys. Once you have signed someones keys you can benefit from the + * keys they have signed if you trust them to carefully check which keys they + * sign. + */ +enum KgpgKeyOwnerTrustFlag +{ + OWTRUST_UNKNOWN = 0, //!< Trust value is unknown (e.g. no entry in trust database). + OWTRUST_UNDEFINED = 1, //!< Trust value undefined (e.g. not trust level set). + OWTRUST_NONE = 2, //!< You do not trust the key owner, keys signed by him are untrusted. + OWTRUST_MARGINAL = 3, //!< You have a minimum level of trust in the key owner. + OWTRUST_FULL = 4, //!< You believe the key owner does good checking. Keys signed by him are trusted by you, too. + OWTRUST_ULTIMATE = 5 //!< There is no doubt in this key owner. This level is used for your own secret keys. +}; +Q_DECLARE_FLAGS(KgpgKeyOwnerTrust, KgpgKeyOwnerTrustFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(KgpgKeyOwnerTrust) + +enum KgpgSubKeyTypeFlag +{ + SKT_ENCRYPTION = 0x1, + SKT_SIGNATURE = 0x2, + SKT_AUTHENTICATION = 0x4, + SKT_CERTIFICATION = 0x8 +}; +Q_DECLARE_FLAGS(KgpgSubKeyType, KgpgSubKeyTypeFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(KgpgSubKeyType) + +/*! \brief types of items in the item models + * + * Every item in the item models is of one of the following types. Some of the + * items can have properties of more than one basic type, e.g. a key pair can + * act both as a secret and a public key. Because of this the value for key + * pairs is a composite of the two "elementary" types for secret and public + * keys. Other compositions than the ones defined here must not be used to set + * an item type, but may of course be used as a mask for comparison. + */ +enum KgpgItemTypeFlag +{ + ITYPE_GROUP = 1, //!< the element is a GnuPG key group + ITYPE_SECRET = 2, //!< secret key + ITYPE_PUBLIC = 4, //!< public key + ITYPE_PAIR = ITYPE_SECRET | ITYPE_PUBLIC, //!< key pair + ITYPE_GSECRET = ITYPE_GROUP | ITYPE_SECRET, //!< secret key as member of a key group + ITYPE_GPUBLIC = ITYPE_GROUP | ITYPE_PUBLIC, //!< public key as member of a key group + ITYPE_GPAIR = ITYPE_GROUP | ITYPE_PAIR, //!< key pair as member of a key group + ITYPE_SUB = 8, //!< subkey of a public or secret key + ITYPE_UID = 16, //!< additional user id + ITYPE_UAT = 32, //!< user attribute to a key (i.e. photo id) + ITYPE_REVSIGN = 64, //!< revokation signature + ITYPE_SIGN = 128 //!< signature (to a key, uid or uat) +}; +Q_DECLARE_FLAGS(KgpgItemType, KgpgItemTypeFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(KgpgItemType) + +//END Enums + +//BEGIN KeySub + +class KgpgKeySubPrivate : public QSharedData +{ + KgpgKeySubPrivate(); +public: + KgpgKeySubPrivate(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const KgpgSubKeyType type, + const QDateTime &date); + + bool gpgsubvalid; + const QString gpgsubid; + const uint gpgsubsize; + QDateTime gpgsubexpiration; + const QDateTime gpgsubcreation; + const KgpgKeyTrust gpgsubtrust; + const KgpgKeyAlgo gpgsubalgo; + const KgpgSubKeyType gpgsubtype; + + bool operator==(const KgpgKeySubPrivate &other) const; + inline bool operator!=(const KgpgKeySubPrivate &other) const + { return !operator==(other); } +}; + +class KgpgKeySub +{ + KgpgKeySub(); +public: + KgpgKeySub(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const KgpgSubKeyType type, + const QDateTime &date); + KgpgKeySub(const KgpgKeySub &other); + + void setExpiration(const QDateTime &date); + void setValid(const bool valid); // FIXME : is it possible to have a subkey that is not valid (disabled)? Please give an example. Thx. If not, this method should be removed. + + QString id() const; + uint size() const; + bool unlimited() const; + QDateTime expirationDate() const; + QDateTime creationDate() const; + KgpgKeyTrust trust() const; + KgpgKeyAlgo algorithm() const; + bool valid() const; + KgpgSubKeyType type() const; + + bool operator==(const KgpgKeySub &other) const; + inline bool operator!=(const KgpgKeySub &other) const + { return !operator==(other); } + KgpgKeySub& operator=(const KgpgKeySub &other); + +private: + QSharedDataPointer d; +}; + +class KgpgKeySubList : public QList, public QObject +{ +public: + inline KgpgKeySubList() { } + inline explicit KgpgKeySubList(const KgpgKeySub &sub) { append(sub); } + inline KgpgKeySubList(const KgpgKeySubList &other) : QList(other), QObject() { } + inline KgpgKeySubList(const QList &other) : QList(other), QObject() { } + + inline KgpgKeySubList operator+(const KgpgKeySubList &other) const + { + KgpgKeySubList n = *this; + n += other; + return n; + } + + inline KgpgKeySubList &operator<<(KgpgKeySub sub) + { + append(sub); + return *this; + } + + inline KgpgKeySubList &operator<<(const KgpgKeySubList &l) + { + *this += l; + return *this; + } +}; +typedef QPointer KgpgKeySubListPtr; + +//END KeySub + + +//BEGIN Key + +class KgpgKeyPrivate : public QSharedData +{ + KgpgKeyPrivate(); +public: + KgpgKeyPrivate(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const QDateTime &date); + + bool gpgkeysecret; + bool gpgkeyvalid; + QString gpgkeymail; + QString gpgkeyname; + QString gpgkeycomment; + QString gpgkeyfingerprint; + const QString gpgkeyid; + const uint gpgkeysize; + KgpgKeyOwnerTrust gpgkeyownertrust; + const KgpgKeyTrust gpgkeytrust; + const QDateTime gpgkeycreation; + QDateTime gpgkeyexpiration; + const KgpgKeyAlgo gpgkeyalgo; + + KgpgKeySubListPtr gpgsublist; + + bool operator==(const KgpgKeyPrivate &other) const; + inline bool operator!=(const KgpgKeyPrivate &other) const + { return !operator==(other); } +}; + +class KgpgKey +{ + KgpgKey(); +public: + KgpgKey(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const QDateTime &date); + KgpgKey(const KgpgKey &other); + + void setSecret(const bool secret); + void setValid(const bool valid); + void setName(const QString &name); + void setEmail(const QString &email); + void setComment(const QString &comment); + void setFingerprint(const QString &fingerprint); + void setOwnerTrust(const KgpgKeyOwnerTrust &owtrust); + void setExpiration(const QDateTime &date); + + bool secret() const; + bool valid() const; + QString id() const; + QString fullId() const; + QString name() const; + QString email() const; + QString comment() const; + const QString &fingerprint() const; + QString fingerprintBeautified() const; + uint size() const; + uint encryptionSize() const; + KgpgKeyOwnerTrust ownerTrust() const; + KgpgKeyTrust trust() const; + QDateTime creationDate() const; + QDateTime expirationDate() const; + bool unlimited() const; + KgpgKeyAlgo algorithm() const; + KgpgKeyAlgo encryptionAlgorithm() const; + + KgpgKeySubListPtr subList() const; + + bool operator==(const KgpgKey &other) const; + inline bool operator!=(const KgpgKey &other) const + { return !operator==(other); } + KgpgKey& operator=(const KgpgKey &other); + +private: + QSharedDataPointer d; +}; + +class KgpgKeyList : public QList, public QObject +{ +public: + inline KgpgKeyList() { } + inline explicit KgpgKeyList(const KgpgKey &key) { append(key); } + inline KgpgKeyList(const KgpgKeyList &other) : QList(other), QObject() { } + inline KgpgKeyList(const QList &other) : QList(other), QObject() { } + + inline KgpgKeyList& operator=(const KgpgKeyList &other) + { + QList::operator=(static_cast >(other)); + return *this; + } + + inline KgpgKeyList operator+(const KgpgKeyList &other) const + { + KgpgKeyList n = *this; + n += other; + return n; + } + + inline KgpgKeyList &operator<<(KgpgKey key) + { + append(key); + return *this; + } + + inline KgpgKeyList &operator<<(const KgpgKeyList &l) + { + *this += l; + return *this; + } + + operator QStringList() const; +}; + +//END Key + +} // namespace + +#endif // KGPGKEY_H diff --git a/kgpg/gpgproc.cpp b/kgpg/gpgproc.cpp new file mode 100644 index 0000000..10f2845 --- /dev/null +++ b/kgpg/gpgproc.cpp @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2007,2008,2009,2010,2011,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "gpgproc.h" + +//#include "kgpgsettings.h" + +//#include +#include +//#include +#include "kprocess.h" +//#include +#include +#include + +class GnupgBinary { +public: + GnupgBinary(); + + const QString &binary() const; + void setBinary(const QString &executable); + const QStringList &standardArguments() const; + unsigned int version() const; + bool supportsDebugLevel() const; + //static GnupgBinary* instance(); + +private: + QString m_binary; + QStringList m_standardArguments; + unsigned int m_version; + bool m_useDebugLevel; +}; + +GnupgBinary::GnupgBinary() + : m_useDebugLevel(false) +{ +} + +const QString &GnupgBinary::binary() const +{ + return m_binary; +} + +/** + * @brief check if GnuPG returns an error for this arguments + * @param executable the GnuPG executable to call + * @param arguments the arguments to pass to executable + * + * The arguments will be used together with "--version", so they should not + * be any commands. + */ +static bool checkGnupgArguments(const QString &executable, const QStringList &arguments) +{ + KProcess gpg; + + // We ignore the output anyway, just make sure it doesn't clutter the output of + // the parent process. Simplify the handling by putting all trash in one can. + gpg.setOutputChannelMode(KProcess::MergedChannels); + + QStringList allArguments = arguments; + allArguments << QLatin1String("--version"); + gpg.setProgram(executable, allArguments); + + return (gpg.execute() == 0); +} + +static QString getGpgProcessHome(const QString &binary) +{ + GPGProc process(0, binary); + process << QLatin1String( "--version" ); + process.start(); + process.waitForFinished(-1); + + if (process.exitCode() == 255) { + return QString(); + } + + QString line; + while (process.readln(line) != -1) { + if (line.startsWith(QLatin1String("Home: "))) { + line.remove(0, 6); + return line; + } + } + + return QString(); +} + + +void GnupgBinary::setBinary(const QString &executable) +{ + qDebug() << "checking version of GnuPG executable" << executable; + // must be set first as gpgVersionString() uses GPGProc to parse the output + m_binary = executable; + const QString verstr = GPGProc::gpgVersionString(executable); + m_version = GPGProc::gpgVersion(verstr); + qDebug() << "version is" << verstr << m_version; + + m_useDebugLevel = (m_version > 0x20000); + + const QString gpgConfigFile = "";//KGpgSettings::gpgConfigPath(); + + m_standardArguments.clear(); + m_standardArguments << QLatin1String( "--no-secmem-warning" ) + << QLatin1String( "--no-tty" ) + << QLatin1String("--no-greeting") + << QLatin1String("--homedir") << GPGProc::getGpgHome(""); + + if (!gpgConfigFile.isEmpty()) + m_standardArguments << QLatin1String("--options") + << gpgConfigFile; + + QStringList debugLevelArguments(QLatin1String("--debug-level")); + debugLevelArguments << QLatin1String("none"); + if (checkGnupgArguments(executable, debugLevelArguments)) + m_standardArguments << debugLevelArguments; +} + +const QStringList& GnupgBinary::standardArguments() const +{ + return m_standardArguments; +} + +unsigned int GnupgBinary::version() const +{ + return m_version; +} + +bool GnupgBinary::supportsDebugLevel() const +{ + return m_useDebugLevel; +} + +Q_GLOBAL_STATIC(GnupgBinary, lastBinary) + +GPGProc::GPGProc(QObject *parent, const QString &binary) + : KLineBufferedProcess(parent) +{ + resetProcess(binary); +} + +GPGProc::~GPGProc() +{ +} + +void +GPGProc::resetProcess(const QString &binary) +{ + GnupgBinary *bin = lastBinary(); + QString executable; + + //qDebug() << "bin:" << binary; + + if (binary.isEmpty()) { + //executable = KGpgSettings::gpgBinaryPath(); + QString appPath = qApp->applicationDirPath(); + QString gpgBin; + #ifdef Q_WS_WIN + gpgBin = appPath + "/bin/gpg.exe"; + #endif + #ifdef Q_WS_MAC + gpgBin = appPath + "/gpg-mac"; + #endif + #ifdef Q_WS_X11 + gpgBin = appPath + "/bin/gpg"; + #endif + executable = gpgBin; + } else + executable = binary; + + if (bin->binary() != executable) + bin->setBinary(executable); + //qDebug() << "ex: " << executable; + setProgram(executable, bin->standardArguments()); + + setOutputChannelMode(OnlyStdoutChannel); + + disconnect(SIGNAL(finished(int,QProcess::ExitStatus))); + disconnect(SIGNAL(lineReadyStandardOutput())); +} + +void GPGProc::start() +{ + // make sure there is exactly one connection from us to that signal + connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(finished()), Qt::UniqueConnection); + connect(this, SIGNAL(lineReadyStandardOutput()), this, SLOT(received()), Qt::UniqueConnection); + KProcess::start(); +} + +void GPGProc::received() +{ + emit readReady(); +} + +void GPGProc::finished() +{ + emit processExited(); +} + +int GPGProc::readln(QString &line, const bool colons) +{ + QByteArray a; + if (!readLineStandardOutput(&a)) + return -1; + + line = recode(a, colons); + + return line.length(); +} + +int GPGProc::readln(QStringList &l) +{ + QString s; + + int len = readln(s); + if (len < 0) + return len; + + l = s.split(QLatin1Char( ':' )); + + for (int i = 0; i < l.count(); ++i) + { + int j = 0; + while ((j = l[i].indexOf(QLatin1String( "\\x3a" ), j, Qt::CaseInsensitive)) >= 0) + { + l[i].replace(j, 4, QLatin1Char( ':' )); + j++; + } + } + + return l.count(); +} + +QString +GPGProc::recode(QByteArray a, const bool colons) +{ + int pos = 0; + + while ((pos = a.indexOf("\\x", pos)) >= 0) { + if (pos > a.length() - 4) + break; + + const QByteArray pattern(a.mid(pos, 4)); + const QByteArray hexnum(pattern.right(2)); + bool ok; + char n[2]; + n[0] = hexnum.toUShort(&ok, 16); + n[1] = '\0'; // to use n as a 0-terminated string + if (!ok) + continue; + + // QLatin1Char( ':' ) must be skipped, it is used as column delimiter + // since it is pure ascii it can be replaced in QString. + if (!colons && (n[0] == ':' )) { + pos += 3; + continue; + } + + // it is likely to find the same byte sequence more than once + int npos = pos; + do { + a.replace(npos, 4, n); + } while ((npos = a.indexOf(pattern, npos)) >= 0); + } + + return QTextCodec::codecForName("utf8")->toUnicode(a); +} + +int GPGProc::gpgVersion(const QString &vstr) +{ + if (vstr.isEmpty()) + return -1; + + QStringList values(vstr.split(QLatin1Char( '.' ))); + if (values.count() < 3) + return -2; + + return (0x10000 * values[0].toInt() + 0x100 * values[1].toInt() + values[2].toInt()); +} + +QString GPGProc::gpgVersionString(const QString &binary) +{ + GPGProc process(0, binary); + process << QLatin1String( "--version" ); + process.start(); + process.waitForFinished(-1); + + if (process.exitCode() == 255) { + qDebug() << "exit255"; + return QString(); + } + + QString line; + if (process.readln(line) != -1) { + qDebug() << line; + return line.simplified().section(QLatin1Char( ' ' ), -1); + } else { + qDebug() << "no readln"; + return QString(); + } +} + +QString GPGProc::getGpgStartupError(const QString &binary) +{ + GPGProc process(0, binary); + process << QLatin1String( "--version" ); + process.start(); + process.waitForFinished(-1); + + QString result; + + while (process.hasLineStandardError()) { + QByteArray tmp; + process.readLineStandardError(&tmp); + tmp += '\n'; + result += QString::fromUtf8(tmp); + } + + return result; +} + +QString GPGProc::getGpgHome(const QString &binary) +{ + // First try: if environment is set GnuPG will use that directory + // We can use this directly without starting a new process +/* QByteArray env(qgetenv("GNUPGHOME")); + QString gpgHome; + if (!env.isEmpty()) { + gpgHome = QLatin1String( env ); + } else if (!binary.isEmpty()) { + // Second try: start GnuPG and ask what it is + gpgHome = getGpgProcessHome(binary); + } + + // Third try: guess what it is. + if (gpgHome.isEmpty()) { +#ifdef Q_OS_WIN32 //krazy:exclude=cpp + gpgHome = qgetenv("APPDATA") + QLatin1String( "/gnupg/" ); + gpgHome.replace(QLatin1Char( '\\' ), QLatin1Char( '/' )); +#else + gpgHome = QDir::homePath() + QLatin1String( "/.gnupg/" ); +#endif + } + + gpgHome.replace(QLatin1String( "//" ), QLatin1String( "/" )); + + if (!gpgHome.endsWith(QLatin1Char( '/' ))) + gpgHome.append(QLatin1Char( '/' )); + + if (gpgHome.startsWith(QLatin1Char( '~' ))) + gpgHome.replace(0, 1, QDir::homePath()); + + //KStandardDirs::makeDir(gpgHome, 0700);*/ + QString appPath = qApp->applicationDirPath(); + QString gpgHome = appPath + "/keydb"; + + return gpgHome; +} + +//#include "gpgproc.moc" diff --git a/kgpg/gpgproc.h b/kgpg/gpgproc.h new file mode 100644 index 0000000..7f9ae9b --- /dev/null +++ b/kgpg/gpgproc.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2007 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef GPGPROC_H +#define GPGPROC_H + +#include +#include +#include + +#include "klinebufferedprocess.h" + +/** + * @brief A interface to GnuPG handling UTF8 recoding correctly + * + * This class handles the GnuPG formatted UTF8 output correctly. + * GnuPG recodes some characters as \\xnn where nn is the hex representation + * of the character. This can't be fixed up simply when using QString as + * QString already did it's own UTF8 conversion. Therefore we replace this + * sequences by their corresponding character so QString will work just fine. + * + * As we know that GnuPG limits it's columns by QLatin1Char( ':' ) we skip \\x3a. Since this + * is an ascii character (single byte) the replacement can be done later without + * problems after the line has been split into pieces. + * + * @author Rolf Eike Beer + */ +class GPGProc : public KLineBufferedProcess +{ + Q_OBJECT + +public: + /** + * Constructor + * @param parent parent object + * @param binary path to GnuPG binary or QString() to use the configured + */ + explicit GPGProc(QObject *parent = 0, const QString &binary = QString()); + + /** + * Destructor + */ + ~GPGProc(); + + /** + * Starts the process + */ + void start(); + + /** + * Reads a line of text (excluding '\\n'). + * + * Use readln() in response to a readReady() signal. + * You may use it multiple times if more than one line of data is + * available. + * + * readln() never blocks. + * + * @param line is used to store the line that was read. + * @param colons recode also colons + * @return the number of characters read, or -1 if no data is available. + */ + int readln(QString &line, const bool colons = false); + + /** + * Reads a line of text and splits it into parts. + * + * Use readln() in response to a readReady() signal. + * You may use it multiple times if more than one line of data is + * available. + * + * readln() never blocks. + * + * @param l is used to store the parts of the line that was read. + * @return the number of characters read, or -1 if no data is available. + */ + int readln(QStringList &l); + + /** + * Recode a line from GnuPG encoding to UTF8 + * + * @param a data to recode + * @param colons recode also colons + * @return recoded string + */ + static QString recode(QByteArray a, const bool colons = true); + + /** + * Reset the class to the state it had right after creation + * @param binary path to GnuPG binary or empty string to use the configured one + */ + void resetProcess(const QString &binary = QString()); + + /** + * @brief parse GnuPG version string and return version as number + * @param vstr version string + * @return -1 if vstr is empty, -2 on parse error, parsed number on success + * + * The version string must be in format A.B.C with A, B, and C numbers. The + * returned number is A * 65536 + B * 256 + C. + */ + static int gpgVersion(const QString &vstr); + /** + * @brief get the GnuPG version string of the given binary + * @param binary name or path to GnuPG binary + * @return version string or empty string on error + * + * This starts a GnuPG process and asks the binary for version information. + * The returned string is the version information without any leading text. + */ + static QString gpgVersionString(const QString &binary); + /** + * @brief find users GnuPG directory + * @param binary name or path to GnuPG binary + * @return path to directory + * + * Use this function to find out where GnuPG would store it's configuration + * and data files. The returned path always ends with a '/'. + */ + static QString getGpgHome(const QString &binary); + + /** + * @brief run GnuPG and check if it complains about anything + * @param binary the GnuPG binary to run + * @return the error message GnuPG gave out (if any) + */ + static QString getGpgStartupError(const QString &binary); + +signals: + /** + * Emitted when the process is ready for reading. + * The signal is only emitted if at least one complete line of data is ready. + * @param p the process that emitted the signal + */ + void readReady(); + + /** + * Emitted when the process has finished + * @param p the process that emitted the signal + */ + void processExited(); + +protected slots: + void finished(); + void received(); +}; + +#endif // GPGPROC_H diff --git a/kgpg/kgpginterface.cpp b/kgpg/kgpginterface.cpp new file mode 100644 index 0000000..8632897 --- /dev/null +++ b/kgpg/kgpginterface.cpp @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2002 Jean-Baptiste Mardelle + * Copyright (C) 2007,2008,2009,2010,2011,2012 + * Rolf Eike Beer + */ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpginterface.h" + +#include "gpgproc.h" +#include "core/convert.h" +#include "core/KGpgKeyNode.h" +#include "core/KGpgSignNode.h" +#include "core/KGpgSubkeyNode.h" +#include "core/KGpgUatNode.h" +#include "core/KGpgUidNode.h" + +/*#include +#include +#include +#include +#include +#include +#include +#include */ +#include +#include +#include +#include +#include +#include + +using namespace KgpgCore; + +QString KgpgInterface::getGpgSetting(const QString &name, const QString &configfile) +{ + const QString tmp(name.simplified() + QLatin1Char( ' ' )); + QFile qfile(configfile); + + if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) { + QTextStream t(&qfile); + while (!t.atEnd()) { + QString result(t.readLine().simplified()); + if (result.startsWith(tmp)) { + result = result.mid(tmp.length()).simplified(); + return result.section(QLatin1Char( ' ' ), 0, 0); + } + } + qfile.close(); + } + + return QString(); +} + +void KgpgInterface::setGpgSetting(const QString &name, const QString &value, const QString &url) +{ + QFile qfile(url); + + if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) { + const QString temp(name + QLatin1Char( ' ' )); + QString texttowrite; + bool found = false; + QTextStream t(&qfile); + + while (!t.atEnd()) { + QString result = t.readLine(); + if (result.simplified().startsWith(temp)) { + if (!value.isEmpty()) + result = temp + QLatin1Char( ' ' ) + value; + else + result.clear(); + found = true; + } + + texttowrite += result + QLatin1Char( '\n' ); + } + + qfile.close(); + if ((!found) && (!value.isEmpty())) + texttowrite += QLatin1Char( '\n' ) + temp + QLatin1Char( ' ' ) + value; + + if (qfile.open(QIODevice::WriteOnly)) { + QTextStream t(&qfile); + t << texttowrite; + qfile.close(); + } + } +} + +bool KgpgInterface::getGpgBoolSetting(const QString &name, const QString &configfile) +{ + QFile qfile(configfile); + if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) { + QTextStream t(&qfile); + while (!t.atEnd()) { + if (t.readLine().simplified().startsWith(name)) + return true; + } + qfile.close(); + } + return false; +} + +void KgpgInterface::setGpgBoolSetting(const QString &name, const bool enable, const QString &url) +{ + QFile qfile(url); + + if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) { + QString texttowrite; + bool found = false; + QTextStream t(&qfile); + + while (!t.atEnd()) { + QString result(t.readLine()); + + if (result.simplified().startsWith(name)) { + if (enable) + result = name; + else + result.clear(); + + found = true; + } + + texttowrite += result + QLatin1Char( '\n' ); + } + qfile.close(); + + if ((!found) && (enable)) + texttowrite += name; + + if (qfile.open(QIODevice::WriteOnly)) { + QTextStream t(&qfile); + t << texttowrite; + qfile.close(); + } + } +} + +int KgpgInterface::sendPassphrase(const QString &text, KProcess *process, QWidget *widget) +{ + qDebug() << "KgpgInterface::sendPassphrase called"; + + QPointer gpgprocess = process; + QByteArray passphrase; + //int code; + bool ok; + + /*QPointer dlg = new KPasswordDialog(widget); + QObject::connect(process, SIGNAL(processExited()), dlg->button(KDialog::Cancel), SLOT(click())); + dlg->setPrompt(text); + code = dlg->exec(); + + if (!dlg.isNull()) + passphrase = dlg->password().toUtf8(); + delete dlg; + + if (code != KPasswordDialog::Accepted) + return 1; +*/ + + QString password = QInputDialog::getText(QApplication::activeWindow(), QObject::tr("Enter Password"), + text, QLineEdit::Password, + "", &ok); + + if(!ok) return 1; + + passphrase = password.toAscii(); + + if (!gpgprocess.isNull()) { + gpgprocess->write(passphrase + '\n'); + } + + return 0; +} + +/** + * @param p the process that reads the GnuPG data + * @param readNode the node where the signatures are read for + */ +static KgpgCore::KgpgKeyList +readPublicKeysProcess(GPGProc &p, KGpgKeyNode *readNode) +{ + QStringList lsp; + int items; + KgpgCore::KgpgKeyList publiclistkeys; + KgpgCore::KgpgKey *publickey = NULL; + unsigned int idIndex = 0; + QString log; + KGpgSignableNode *currentSNode = NULL; ///< the current (sub)node signatures are read for + + while ((items = p.readln(lsp)) >= 0) { + if ((lsp.at(0) == QLatin1String( "pub" )) && (items >= 10)) { + publiclistkeys << KgpgKey(lsp.at(4), lsp.at(2).toUInt(), Convert::toTrust(lsp.at(1)), + Convert::toAlgo(lsp.at(3).toInt()), QDateTime::fromTime_t(lsp.at(5).toUInt())); + + publickey = &publiclistkeys.last(); + + publickey->setOwnerTrust(Convert::toOwnerTrust(lsp.at(8))); + + if (lsp.at(6).isEmpty()) + publickey->setExpiration(QDateTime()); + else + publickey->setExpiration(QDateTime::fromTime_t(lsp.at(6).toUInt())); + + publickey->setValid((items <= 11) || !lsp.at(11).contains(QLatin1Char( 'D' ), Qt::CaseSensitive)); // disabled key + + idIndex = 0; + } else if ((lsp.at(0) == QLatin1String( "fpr" )) && (items >= 10)) { + const QString fingervalue(lsp.at(9)); + + publickey->setFingerprint(fingervalue); + } else if ((lsp.at(0) == QLatin1String( "sub" )) && (items >= 7)) { + KgpgSubKeyType subtype; + + if (items > 11) { + if (lsp.at(11).contains(QLatin1Char( 's' ))) + subtype |= SKT_SIGNATURE; + if (lsp.at(11).contains(QLatin1Char( 'e' ))) + subtype |= SKT_ENCRYPTION; + if (lsp.at(11).contains(QLatin1Char( 'e' ))) + subtype |= SKT_AUTHENTICATION; + if (lsp.at(11).contains(QLatin1Char( 'e' ))) + subtype |= SKT_CERTIFICATION; + } + + KgpgKeySub sub(lsp.at(4), lsp.at(2).toUInt(), Convert::toTrust(lsp.at(1)), + Convert::toAlgo(lsp.at(3).toInt()), subtype, QDateTime::fromTime_t(lsp.at(5).toUInt())); + + // FIXME: Please see kgpgkey.h, KgpgSubKey class + if (items <= 11) + sub.setValid(true); + else + sub.setValid(!lsp.at(11).contains(QLatin1Char( 'D' ))); + + if (lsp.at(6).isEmpty()) + sub.setExpiration(QDateTime()); + else + sub.setExpiration(QDateTime::fromTime_t(lsp.at(6).toUInt())); + + publickey->subList()->append(sub); + if (readNode == NULL) + currentSNode = NULL; + else + currentSNode = new KGpgSubkeyNode(readNode, sub); + } else if (lsp.at(0) == QLatin1String( "uat" )) { + idIndex++; + if (readNode != NULL) { + currentSNode = new KGpgUatNode(readNode, idIndex, lsp); + } + } else if ((lsp.at(0) == QLatin1String( "uid" )) && (items >= 10)) { + if (idIndex == 0) { + QString fullname(lsp.at(9)); + QString kmail; + if (fullname.contains(QLatin1Char( '<' )) ) { + kmail = fullname; + + if (fullname.contains(QLatin1Char( ')' )) ) + kmail = kmail.section(QLatin1Char( ')' ), 1); + + kmail = kmail.section(QLatin1Char( '<' ), 1); + kmail.truncate(kmail.length() - 1); + + if (kmail.contains(QLatin1Char( '<' ))) { + // several email addresses in the same key + kmail = kmail.replace(QLatin1Char( '>' ), QLatin1Char( ';' )); + kmail.remove(QLatin1Char( '<' )); + } + } + + QString kname(fullname.section( QLatin1String( " <" ), 0, 0)); + QString comment; + if (fullname.contains(QLatin1Char( '(' )) ) { + kname = kname.section( QLatin1String( " (" ), 0, 0); + comment = fullname.section(QLatin1Char( '(' ), 1, 1); + comment = comment.section(QLatin1Char( ')' ), 0, 0); + } + + idIndex++; + publickey->setEmail(kmail); + publickey->setComment(comment); + publickey->setName(kname); + + currentSNode = readNode; + } else { + idIndex++; + if (readNode != NULL) { + currentSNode = new KGpgUidNode(readNode, idIndex, lsp); + } + } + } else if (((lsp.at(0) == QLatin1String( "sig" )) || (lsp.at(0) == QLatin1String( "rev" ))) && (items >= 11)) { + // there are no strings here that could have a recoded QLatin1Char( ':' ) in them + const QString signature = lsp.join(QLatin1String(":")); + + if (currentSNode != NULL) + (void) new KGpgSignNode(currentSNode, lsp); + } else { + log += lsp.join(QString(QLatin1Char( ':' ))) + QLatin1Char( '\n' ); + } + } + + if (p.exitCode() != 0) { +// KMessageBox::detailedError(NULL, i18n("An error occurred while scanning your keyring"), log); + qDebug() << "An error occurred while scanning your keyring" << " - " << log; + log.clear(); + } + + return publiclistkeys; +} + +KgpgKeyList KgpgInterface::readPublicKeys(const QStringList &ids) +{ + GPGProc process; + process << + QLatin1String("--with-colons") << + QLatin1String("--with-fingerprint") << + QLatin1String("--fixed-list-mode") << + QLatin1String("--homedir") << GPGProc::getGpgHome("") << + QLatin1String("--list-keys") << + ids; + + process.setOutputChannelMode(KProcess::MergedChannels); + + process.start(); + process.waitForFinished(-1); + return readPublicKeysProcess(process, NULL); +} + +void KgpgInterface::readSignatures(KGpgKeyNode *node) +{ + GPGProc process; + process << + QLatin1String("--with-colons") << + QLatin1String("--with-fingerprint") << + QLatin1String("--fixed-list-mode") << + QLatin1String("--list-sigs") << + node->getId(); + + process.setOutputChannelMode(KProcess::MergedChannels); + + process.start(); + process.waitForFinished(-1); + + readPublicKeysProcess(process, node); +} + +static KgpgCore::KgpgKeyList +readSecretKeysProcess(GPGProc &p) +{ + QStringList lsp; + int items; + bool hasuid = true; + KgpgCore::KgpgKeyList result; + KgpgCore::KgpgKey *secretkey = NULL; + + while ( (items = p.readln(lsp)) >= 0 ) { + if ((lsp.at(0) == QLatin1String( "sec" )) && (items >= 10)) { + result << KgpgKey(lsp.at(4), lsp.at(2).toUInt(), Convert::toTrust(lsp.at(1)), + Convert::toAlgo(lsp.at(3).toInt()), QDateTime::fromTime_t(lsp.at(5).toUInt())); + + secretkey = &result.last(); + + secretkey->setSecret(true); + + if (lsp.at(6).isEmpty()) + secretkey->setExpiration(QDateTime()); + else + secretkey->setExpiration(QDateTime::fromTime_t(lsp.at(6).toUInt())); + hasuid = true; + } else if ((lsp.at(0) == QLatin1String( "uid" )) && (items >= 10)) { + if (hasuid) + continue; + + hasuid = true; + + const QString fullname(lsp.at(9)); + if (fullname.contains(QLatin1Char( '<' ) )) { + QString kmail(fullname); + + if (fullname.contains(QLatin1Char( ')' ) )) + kmail = kmail.section(QLatin1Char( ')' ), 1); + + kmail = kmail.section(QLatin1Char( '<' ), 1); + kmail.truncate(kmail.length() - 1); + + if (kmail.contains(QLatin1Char( '<' ) )) { // several email addresses in the same key + kmail = kmail.replace(QLatin1Char( '>' ), QLatin1Char( ';' )); + kmail.remove(QLatin1Char( '<' )); + } + + secretkey->setEmail(kmail); + } else { + secretkey->setEmail(QString()); + } + + QString kname(fullname.section( QLatin1String( " <" ), 0, 0)); + if (fullname.contains(QLatin1Char( '(' ) )) { + kname = kname.section( QLatin1String( " (" ), 0, 0); + QString comment = fullname.section(QLatin1Char( '(' ), 1, 1); + comment = comment.section(QLatin1Char( ')' ), 0, 0); + + secretkey->setComment(comment); + } else { + secretkey->setComment(QString()); + } + secretkey->setName(kname); + } else if ((lsp.at(0) == QLatin1String( "fpr" )) && (items >= 10)) { + secretkey->setFingerprint(lsp.at(9)); + } + } + + return result; +} + +KgpgKeyList KgpgInterface::readSecretKeys(const QStringList &ids) +{ + GPGProc process; + process << + QLatin1String("--with-colons") << + QLatin1String("--list-secret-keys") << + QLatin1String("--with-fingerprint") << + QLatin1String("--fixed-list-mode") << + ids; + + process.start(); + process.waitForFinished(-1); + KgpgCore::KgpgKeyList result = readSecretKeysProcess(process); + + return result; +} + +//#include "kgpginterface.moc" diff --git a/kgpg/kgpginterface.h b/kgpg/kgpginterface.h new file mode 100644 index 0000000..1ed0e53 --- /dev/null +++ b/kgpg/kgpginterface.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2002 Jean-Baptiste Mardelle + * Copyright (C) 2007,2008,2009,2010,2011,2012 + * Rolf Eike Beer + */ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGINTERFACE_H +#define KGPGINTERFACE_H + +#include "core/kgpgkey.h" +#include + +class KGpgKeyNode; +class KProcess; +class QString; +class QApplication; + +/** + * GnuPG interface functions + */ +namespace KgpgInterface { + QString getGpgSetting(const QString &name, const QString &configfile); + void setGpgSetting(const QString &name, const QString &value, const QString &url); + + bool getGpgBoolSetting(const QString &name, const QString &configfile); + void setGpgBoolSetting(const QString &name, const bool enable, const QString &url); + + /** + * @brief ask the user for a passphrase and send it to the given gpg process + * @param text text is the message that must be displayed in the MessageBox + * @param process GnuPG process + * @param isnew if the password is a \e new password that must be confirmed. Default is true + * @param widget parent widget of this dialog or NULL + * @return 0 if there is no error + * @return 1 if there is an error + */ + int sendPassphrase(const QString &text, KProcess *process, QWidget *widget = NULL); + + KgpgCore::KgpgKeyList readPublicKeys(const QStringList &ids = QStringList()); + void readSignatures(KGpgKeyNode *node); + KgpgCore::KgpgKeyList readSecretKeys(const QStringList &ids = QStringList()); +}; + +#endif // KGPGINTERFACE_H diff --git a/kgpg/klinebufferedprocess.cpp b/kgpg/klinebufferedprocess.cpp new file mode 100644 index 0000000..00099af --- /dev/null +++ b/kgpg/klinebufferedprocess.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2008 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "klinebufferedprocess.h" + + +KLineBufferedProcessPrivate::KLineBufferedProcessPrivate(KLineBufferedProcess *parent) + : m_newlineInStdout(-1), + m_newlineInStderr(-1), + m_parent(parent), +#ifdef Q_OS_WIN32 //krazy:exclude=cpp + m_lineEnd("\r\n") +#else + m_lineEnd("\n") +#endif +{ +} + +KLineBufferedProcess::KLineBufferedProcess(QObject *parent) + : KProcess(parent), + d(new KLineBufferedProcessPrivate(this)) +{ + connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(_k_receivedStdout())); + connect(this, SIGNAL(readyReadStandardError()), this, SLOT(_k_receivedStderr())); +} + +KLineBufferedProcess::~KLineBufferedProcess() +{ + delete d; +} + +void KLineBufferedProcessPrivate::_k_receivedStdout() +{ + QByteArray ndata = m_parent->readAllStandardOutput(); + int oldBufferSize = m_stdoutBuffer.size(); + m_stdoutBuffer.append(ndata); + + if (m_newlineInStdout < 0) { + m_newlineInStdout = ndata.indexOf(m_lineEnd); + if (m_newlineInStdout >= 0) { + m_newlineInStdout += oldBufferSize; + emit m_parent->lineReadyStandardOutput(); + } + } +} + +void KLineBufferedProcessPrivate::_k_receivedStderr() +{ + QByteArray ndata = m_parent->readAllStandardError(); + int oldBufferSize = m_stderrBuffer.size(); + m_stderrBuffer.append(ndata); + + if (m_newlineInStderr < 0) { + m_newlineInStderr = ndata.indexOf(m_lineEnd); + if (m_newlineInStderr >= 0) { + m_newlineInStderr += oldBufferSize; + emit m_parent->lineReadyStandardError(); + } + } +} + +bool KLineBufferedProcess::readLineStandardOutput(QByteArray *line) +{ + if (d->m_newlineInStdout < 0) { + return false; + } + + // don't copy '\n' + *line = d->m_stdoutBuffer.left(d->m_newlineInStdout); + d->m_stdoutBuffer.remove(0, d->m_newlineInStdout + d->m_lineEnd.length()); + + d->m_newlineInStdout = d->m_stdoutBuffer.indexOf(d->m_lineEnd); + + return true; +} + +bool KLineBufferedProcess::readLineStandardError(QByteArray *line) +{ + if (d->m_newlineInStderr < 0) { + return false; + } + + // don't copy '\n' + *line = d->m_stderrBuffer.left(d->m_newlineInStderr); + d->m_stderrBuffer.remove(0, d->m_newlineInStderr + d->m_lineEnd.length()); + + d->m_newlineInStderr = d->m_stderrBuffer.indexOf(d->m_lineEnd); + + return true; +} + +bool KLineBufferedProcess::hasLineStandardOutput() const +{ + return d->m_newlineInStdout >= 0; +} + +bool KLineBufferedProcess::hasLineStandardError() const +{ + return d->m_newlineInStderr >= 0; +} + +//#include "moc_klinebufferedprocess.cpp" diff --git a/kgpg/klinebufferedprocess.h b/kgpg/klinebufferedprocess.h new file mode 100644 index 0000000..eab360b --- /dev/null +++ b/kgpg/klinebufferedprocess.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2008 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KLINEBUFFEREDPROCESS_H +#define KLINEBUFFEREDPROCESS_H + +#include "kprocess.h" + +class QByteArray; +//class KLineBufferedProcessPrivate; +class KLineBufferedProcess; +class KLineBufferedProcessPrivate +{ +public: + KLineBufferedProcessPrivate(KLineBufferedProcess *parent); + +//private slot implementations + void _k_receivedStdout(); + void _k_receivedStderr(); + + QByteArray m_stdoutBuffer; + QByteArray m_stderrBuffer; + int m_newlineInStdout; + int m_newlineInStderr; + KLineBufferedProcess * const m_parent; + const QByteArray m_lineEnd; +}; + +/** + * Read output of a process split into lines + * + * This class reads the output of a process and splits it up into lines. This + * is especially useful if you try to parse the output of a command line tool. + * + * \b Usage \n + * + * The class is created and set up like a KProcess. After this you can do + * something like this: + * + * \code + * connect(m_linebufprocess, SIGNAL(lineReadyStandardOutput()), SLOT(dataStdout())); + * ... + * void myobj::dataStdout() + * { + * while (m_linebufprocess->hasLineStandardOutput()) { + * QByteArray line; + * m_linebufprocess->readLineStandardOutput(line); + * ... + * } + * } + * \endcode + * + * Never use the read functionality of KProcess with this class. This class + * needs to read all data from the process into an internal buffer first. If + * you try to use the read functions of the parent classes you would normally + * get no output at all. + * + * The write functions of the parent classes are not effected. You can use + * them exactly the same way as in KProcess. + * + * @author Rolf Eike Beer + */ +class KLineBufferedProcess : public KProcess +{ + Q_OBJECT + friend class KLineBufferedProcessPrivate; + +public: + /** + * Constructor + */ + explicit KLineBufferedProcess(QObject *parent = 0); + + /** + * Destructor + */ + ~KLineBufferedProcess(); + + /** + * Reads a line of text (excluding '\\n') from stdout. + * + * Use readLineStdout() in response to a lineReadyStdout() signal or + * when hasLineStdout() returns true. You may use it multiple times if + * more than one line of data is available. If no complete line is + * available the content of line is undefined and the function returns + * false. + * + * @param line is used to store the line that was read. + * @return if data was read or not + */ + bool readLineStandardOutput(QByteArray *line); + + /** + * Reads a line of text (excluding '\\n') from stderr. + * + * Use readLineStderr() in response to a lineReadyStderr() signal or + * when hasLineStderr() returns true. You may use it multiple times if + * more than one line of data is available. If no complete line is + * available the content of line is undefined and the function returns + * false. + * + * @param line is used to store the line that was read. + * @return if data was read or not + */ + bool readLineStandardError(QByteArray *line); + + /** + * Checks if a line is ready on stdout + * + * @return true if a complete line can be read + */ + bool hasLineStandardOutput() const; + + /** + * Checks if a line is ready on stdout + * + * @return true if a complete line can be read + */ + bool hasLineStandardError() const; + +signals: + /** + * Emitted when there is a line of data available from stdout when there was + * previously none. + * There may or may not be more than one line available for reading when this + * signal is emitted. + */ + void lineReadyStandardOutput(); + + /** + * Emitted when there is a line of data available from stderr when there was + * previously none. + * There may or may not be more than one line available for reading when this + * signal is emitted. + */ + void lineReadyStandardError(); + +private: + KLineBufferedProcessPrivate* const d; + + Q_PRIVATE_SLOT(d, void _k_receivedStdout()) + Q_PRIVATE_SLOT(d, void _k_receivedStderr()) +}; + +#endif // KLINEBUFFEREDPROCESS_H diff --git a/kgpg/kprocess.cpp b/kgpg/kprocess.cpp new file mode 100644 index 0000000..907c75c --- /dev/null +++ b/kgpg/kprocess.cpp @@ -0,0 +1,411 @@ +/* + This file is part of the KDE libraries + + Copyright (C) 2007 Oswald Buddenhagen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kprocess_p.h" + +//#include +//#include +//#ifdef Q_OS_WIN +//# include +//#endif + +#include +#include + +#ifdef Q_OS_WIN +# include +#else +# include +# include +#endif + +#ifndef Q_OS_WIN +# define STD_OUTPUT_HANDLE 1 +# define STD_ERROR_HANDLE 2 +#endif + +#ifdef _WIN32_WCE +#include +#endif + +void KProcessPrivate::writeAll(const QByteArray &buf, int fd) +{ +#ifdef Q_OS_WIN +#ifndef _WIN32_WCE + HANDLE h = GetStdHandle(fd); + if (h) { + DWORD wr; + WriteFile(h, buf.data(), buf.size(), &wr, 0); + } +#else + fwrite(buf.data(), 1, buf.size(), (FILE*)fd); +#endif +#else + int off = 0; + do { + int ret = ::write(fd, buf.data() + off, buf.size() - off); + if (ret < 0) { + if (errno != EINTR) + return; + } else { + off += ret; + } + } while (off < buf.size()); +#endif +} + +void KProcessPrivate::forwardStd(KProcess::ProcessChannel good, int fd) +{ + Q_Q(KProcess); + + QProcess::ProcessChannel oc = q->readChannel(); + q->setReadChannel(good); + writeAll(q->readAll(), fd); + q->setReadChannel(oc); +} + +void KProcessPrivate::_k_forwardStdout() +{ +#ifndef _WIN32_WCE + forwardStd(KProcess::StandardOutput, STD_OUTPUT_HANDLE); +#else + forwardStd(KProcess::StandardOutput, (int)stdout); +#endif +} + +void KProcessPrivate::_k_forwardStderr() +{ +#ifndef _WIN32_WCE + forwardStd(KProcess::StandardError, STD_ERROR_HANDLE); +#else + forwardStd(KProcess::StandardError, (int)stderr); +#endif +} + +///////////////////////////// +// public member functions // +///////////////////////////// + +KProcess::KProcess(QObject *parent) : + QProcess(parent), + d_ptr(new KProcessPrivate) +{ + d_ptr->q_ptr = this; + setOutputChannelMode(ForwardedChannels); +} + +KProcess::KProcess(KProcessPrivate *d, QObject *parent) : + QProcess(parent), + d_ptr(d) +{ + d_ptr->q_ptr = this; + setOutputChannelMode(ForwardedChannels); +} + +KProcess::~KProcess() +{ + delete d_ptr; +} + +void KProcess::setOutputChannelMode(OutputChannelMode mode) +{ + Q_D(KProcess); + + d->outputChannelMode = mode; + disconnect(this, SIGNAL(readyReadStandardOutput())); + disconnect(this, SIGNAL(readyReadStandardError())); + switch (mode) { + case OnlyStdoutChannel: + connect(this, SIGNAL(readyReadStandardError()), SLOT(_k_forwardStderr())); + break; + case OnlyStderrChannel: + connect(this, SIGNAL(readyReadStandardOutput()), SLOT(_k_forwardStdout())); + break; + default: + QProcess::setProcessChannelMode((ProcessChannelMode)mode); + return; + } + QProcess::setProcessChannelMode(QProcess::SeparateChannels); +} + +KProcess::OutputChannelMode KProcess::outputChannelMode() const +{ + Q_D(const KProcess); + + return d->outputChannelMode; +} + +void KProcess::setNextOpenMode(QIODevice::OpenMode mode) +{ + Q_D(KProcess); + + d->openMode = mode; +} + +#define DUMMYENV "_KPROCESS_DUMMY_=" + +void KProcess::clearEnvironment() +{ + setEnvironment(QStringList() << QString::fromLatin1(DUMMYENV)); +} + +void KProcess::setEnv(const QString &name, const QString &value, bool overwrite) +{ + QStringList env = environment(); + if (env.isEmpty()) { + env = systemEnvironment(); + env.removeAll(QString::fromLatin1(DUMMYENV)); + } + QString fname(name); + fname.append(QLatin1Char('=')); + for (QStringList::Iterator it = env.begin(); it != env.end(); ++it) + if ((*it).startsWith(fname)) { + if (overwrite) { + *it = fname.append(value); + setEnvironment(env); + } + return; + } + env.append(fname.append(value)); + setEnvironment(env); +} + +void KProcess::unsetEnv(const QString &name) +{ + QStringList env = environment(); + if (env.isEmpty()) { + env = systemEnvironment(); + env.removeAll(QString::fromLatin1(DUMMYENV)); + } + QString fname(name); + fname.append(QLatin1Char('=')); + for (QStringList::Iterator it = env.begin(); it != env.end(); ++it) + if ((*it).startsWith(fname)) { + env.erase(it); + if (env.isEmpty()) + env.append(QString::fromLatin1(DUMMYENV)); + setEnvironment(env); + return; + } +} + +void KProcess::setProgram(const QString &exe, const QStringList &args) +{ + Q_D(KProcess); + + d->prog = exe; + d->args = args; +#ifdef Q_OS_WIN + setNativeArguments(QString()); +#endif +} + +void KProcess::setProgram(const QStringList &argv) +{ + Q_D(KProcess); + + Q_ASSERT( !argv.isEmpty() ); + d->args = argv; + d->prog = d->args.takeFirst(); +#ifdef Q_OS_WIN + setNativeArguments(QString()); +#endif +} + +KProcess &KProcess::operator<<(const QString &arg) +{ + Q_D(KProcess); + + if (d->prog.isEmpty()) + d->prog = arg; + else + d->args << arg; + return *this; +} + +KProcess &KProcess::operator<<(const QStringList &args) +{ + Q_D(KProcess); + + if (d->prog.isEmpty()) + setProgram(args); + else + d->args << args; + return *this; +} + +void KProcess::clearProgram() +{ + Q_D(KProcess); + + d->prog.clear(); + d->args.clear(); +#ifdef Q_OS_WIN + setNativeArguments(QString()); +#endif +} + +/*void KProcess::setShellCommand(const QString &cmd) +{ + Q_D(KProcess); + + KShell::Errors err; + d->args = KShell::splitArgs( + cmd, KShell::AbortOnMeta | KShell::TildeExpand, &err); + if (err == KShell::NoError && !d->args.isEmpty()) { + d->prog = KStandardDirs::findExe(d->args[0]); + if (!d->prog.isEmpty()) { + d->args.removeFirst(); +#ifdef Q_OS_WIN + setNativeArguments(QString()); +#endif + return; + } + } + + d->args.clear(); + +#ifdef Q_OS_UNIX +// #ifdef NON_FREE // ... as they ship non-POSIX /bin/sh +# if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__GNU__) + // If /bin/sh is a symlink, we can be pretty sure that it points to a + // POSIX shell - the original bourne shell is about the only non-POSIX + // shell still in use and it is always installed natively as /bin/sh. + d->prog = QFile::symLinkTarget(QString::fromLatin1("/bin/sh")); + if (d->prog.isEmpty()) { + // Try some known POSIX shells. + d->prog = KStandardDirs::findExe(QString::fromLatin1("ksh")); + if (d->prog.isEmpty()) { + d->prog = KStandardDirs::findExe(QString::fromLatin1("ash")); + if (d->prog.isEmpty()) { + d->prog = KStandardDirs::findExe(QString::fromLatin1("bash")); + if (d->prog.isEmpty()) { + d->prog = KStandardDirs::findExe(QString::fromLatin1("zsh")); + if (d->prog.isEmpty()) + // We're pretty much screwed, to be honest ... + d->prog = QString::fromLatin1("/bin/sh"); + } + } + } + } +# else + d->prog = QString::fromLatin1("/bin/sh"); +# endif + + d->args << QString::fromLatin1("-c") << cmd; +#else // Q_OS_UNIX + // KMacroExpander::expandMacrosShellQuote(), KShell::quoteArg() and + // KShell::joinArgs() may generate these for security reasons. + setEnv(PERCENT_VARIABLE, QLatin1String("%")); + +#ifndef _WIN32_WCE + WCHAR sysdir[MAX_PATH + 1]; + UINT size = GetSystemDirectoryW(sysdir, MAX_PATH + 1); + d->prog = QString::fromUtf16((const ushort *) sysdir, size); + d->prog += QLatin1String("\\cmd.exe"); + setNativeArguments(QLatin1String("/V:OFF /S /C \"") + cmd + QLatin1Char('"')); +#else + d->prog = QLatin1String("\\windows\\cmd.exe"); + setNativeArguments(QLatin1String("/S /C \"") + cmd + QLatin1Char('"')); +#endif +#endif +}*/ + +QStringList KProcess::program() const +{ + Q_D(const KProcess); + + QStringList argv = d->args; + argv.prepend(d->prog); + return argv; +} + +void KProcess::start() +{ + Q_D(KProcess); + qDebug() << "prog: " << d->prog << " | args: " << d->args; + QProcess::start(d->prog, d->args, d->openMode); +} + +int KProcess::execute(int msecs) +{ + start(); + if (!waitForFinished(msecs)) { + kill(); + waitForFinished(-1); + return -2; + } + return (exitStatus() == QProcess::NormalExit) ? exitCode() : -1; +} + +// static +int KProcess::execute(const QString &exe, const QStringList &args, int msecs) +{ + KProcess p; + p.setProgram(exe, args); + return p.execute(msecs); +} + +// static +int KProcess::execute(const QStringList &argv, int msecs) +{ + KProcess p; + p.setProgram(argv); + return p.execute(msecs); +} + +int KProcess::startDetached() +{ + Q_D(KProcess); + + qint64 pid; + if (!QProcess::startDetached(d->prog, d->args, workingDirectory(), &pid)) + return 0; + return (int) pid; +} + +// static +int KProcess::startDetached(const QString &exe, const QStringList &args) +{ + qint64 pid; + if (!QProcess::startDetached(exe, args, QString(), &pid)) + return 0; + return (int) pid; +} + +// static +int KProcess::startDetached(const QStringList &argv) +{ + QStringList args = argv; + QString prog = args.takeFirst(); + return startDetached(prog, args); +} + +int KProcess::pid() const +{ +#ifdef Q_OS_UNIX + return (int) QProcess::pid(); +#else + return QProcess::pid() ? QProcess::pid()->dwProcessId : 0; +#endif +} + +#include "moc_kprocess.cpp" diff --git a/kgpg/kprocess.h b/kgpg/kprocess.h new file mode 100644 index 0000000..6f28e24 --- /dev/null +++ b/kgpg/kprocess.h @@ -0,0 +1,341 @@ +/* + This file is part of the KDE libraries + + Copyright (C) 2007 Oswald Buddenhagen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KPROCESS_H +#define KPROCESS_H + +//#include + +#include + +class KProcessPrivate; +//#include "kprocess_p.h" +/** + * \class KProcess kprocess.h + * + * Child process invocation, monitoring and control. + * + * This class extends QProcess by some useful functionality, overrides + * some defaults with saner values and wraps parts of the API into a more + * accessible one. + * This is the preferred way of spawning child processes in KDE; don't + * use QProcess directly. + * + * @author Oswald Buddenhagen + **/ +class KProcess : public QProcess +{ + Q_OBJECT + Q_DECLARE_PRIVATE(KProcess) + +public: + + /** + * Modes in which the output channels can be opened. + */ + enum OutputChannelMode { + SeparateChannels = QProcess::SeparateChannels, + /**< Standard output and standard error are handled by KProcess + as separate channels */ + MergedChannels = QProcess::MergedChannels, + /**< Standard output and standard error are handled by KProcess + as one channel */ + ForwardedChannels = QProcess::ForwardedChannels, + /**< Both standard output and standard error are forwarded + to the parent process' respective channel */ + OnlyStdoutChannel, + /**< Only standard output is handled; standard error is forwarded */ + OnlyStderrChannel /**< Only standard error is handled; standard output is forwarded */ + }; + + /** + * Constructor + */ + explicit KProcess(QObject *parent = 0); + + /** + * Destructor + */ + virtual ~KProcess(); + + /** + * Set how to handle the output channels of the child process. + * + * The default is ForwardedChannels, which is unlike in QProcess. + * Do not request more than you actually handle, as this output is + * simply lost otherwise. + * + * This function must be called before starting the process. + * + * @param mode the output channel handling mode + */ + void setOutputChannelMode(OutputChannelMode mode); + + /** + * Query how the output channels of the child process are handled. + * + * @return the output channel handling mode + */ + OutputChannelMode outputChannelMode() const; + + /** + * Set the QIODevice open mode the process will be opened in. + * + * This function must be called before starting the process, obviously. + * + * @param mode the open mode. Note that this mode is automatically + * "reduced" according to the channel modes and redirections. + * The default is QIODevice::ReadWrite. + */ + void setNextOpenMode(QIODevice::OpenMode mode); + + /** + * Adds the variable @p name to the process' environment. + * + * This function must be called before starting the process. + * + * @param name the name of the environment variable + * @param value the new value for the environment variable + * @param overwrite if @c false and the environment variable is already + * set, the old value will be preserved + */ + void setEnv(const QString &name, const QString &value, bool overwrite = true); + + /** + * Removes the variable @p name from the process' environment. + * + * This function must be called before starting the process. + * + * @param name the name of the environment variable + */ + void unsetEnv(const QString &name); + + /** + * Empties the process' environment. + * + * Note that LD_LIBRARY_PATH/DYLD_LIBRARY_PATH is automatically added + * on *NIX. + * + * This function must be called before starting the process. + */ + void clearEnvironment(); + + /** + * Set the program and the command line arguments. + * + * This function must be called before starting the process, obviously. + * + * @param exe the program to execute + * @param args the command line arguments for the program, + * one per list element + */ + void setProgram(const QString &exe, const QStringList &args = QStringList()); + + /** + * @overload + * + * @param argv the program to execute and the command line arguments + * for the program, one per list element + */ + void setProgram(const QStringList &argv); + + /** + * Append an element to the command line argument list for this process. + * + * If no executable is set yet, it will be set instead. + * + * For example, doing an "ls -l /usr/local/bin" can be achieved by: + * \code + * KProcess p; + * p << "ls" << "-l" << "/usr/local/bin"; + * ... + * \endcode + * + * This function must be called before starting the process, obviously. + * + * @param arg the argument to add + * @return a reference to this KProcess + */ + KProcess &operator<<(const QString& arg); + + /** + * @overload + * + * @param args the arguments to add + * @return a reference to this KProcess + */ + KProcess &operator<<(const QStringList& args); + + /** + * Clear the program and command line argument list. + */ + void clearProgram(); + + /** + * Set a command to execute through a shell (a POSIX sh on *NIX + * and cmd.exe on Windows). + * + * Using this for anything but user-supplied commands is usually a bad + * idea, as the command's syntax depends on the platform. + * Redirections including pipes, etc. are better handled by the + * respective functions provided by QProcess. + * + * If KProcess determines that the command does not really need a + * shell, it will trasparently execute it without one for performance + * reasons. + * + * This function must be called before starting the process, obviously. + * + * @param cmd the command to execute through a shell. + * The caller must make sure that all filenames etc. are properly + * quoted when passed as argument. Failure to do so often results in + * serious security holes. See KShell::quoteArg(). + */ + void setShellCommand(const QString &cmd); + + /** + * Obtain the currently set program and arguments. + * + * @return a list, the first element being the program, the remaining ones + * being command line arguments to the program. + */ + QStringList program() const; + + /** + * Start the process. + * + * @see QProcess::start(const QString &, const QStringList &, OpenMode) + */ + void start(); + + /** + * Start the process, wait for it to finish, and return the exit code. + * + * This method is roughly equivalent to the sequence: + * + * start(); + * waitForFinished(msecs); + * return exitCode(); + * + * + * Unlike the other execute() variants this method is not static, + * so the process can be parametrized properly and talked to. + * + * @param msecs time to wait for process to exit before killing it + * @return -2 if the process could not be started, -1 if it crashed, + * otherwise its exit code + */ + int execute(int msecs = -1); + + /** + * @overload + * + * @param exe the program to execute + * @param args the command line arguments for the program, + * one per list element + * @param msecs time to wait for process to exit before killing it + * @return -2 if the process could not be started, -1 if it crashed, + * otherwise its exit code + */ + static int execute(const QString &exe, const QStringList &args = QStringList(), int msecs = -1); + + /** + * @overload + * + * @param argv the program to execute and the command line arguments + * for the program, one per list element + * @param msecs time to wait for process to exit before killing it + * @return -2 if the process could not be started, -1 if it crashed, + * otherwise its exit code + */ + static int execute(const QStringList &argv, int msecs = -1); + + /** + * Start the process and detach from it. See QProcess::startDetached() + * for details. + * + * Unlike the other startDetached() variants this method is not static, + * so the process can be parametrized properly. + * @note Currently, only the setProgram()/setShellCommand() and + * setWorkingDirectory() parametrizations are supported. + * + * The KProcess object may be re-used immediately after calling this + * function. + * + * @return the PID of the started process or 0 on error + */ + int startDetached(); + + /** + * @overload + * + * @param exe the program to start + * @param args the command line arguments for the program, + * one per list element + * @return the PID of the started process or 0 on error + */ + static int startDetached(const QString &exe, const QStringList &args = QStringList()); + + /** + * @overload + * + * @param argv the program to start and the command line arguments + * for the program, one per list element + * @return the PID of the started process or 0 on error + */ + static int startDetached(const QStringList &argv); + + /** + * Obtain the process' ID as known to the system. + * + * Unlike with QProcess::pid(), this is a real PID also on Windows. + * + * This function can be called only while the process is running. + * It cannot be applied to detached processes. + * + * @return the process ID + */ + int pid() const; + +protected: + /** + * @internal + */ + KProcess(KProcessPrivate *d, QObject *parent); + + /** + * @internal + */ + KProcessPrivate * const d_ptr; + +private: + // hide those + using QProcess::setReadChannelMode; + using QProcess::readChannelMode; + using QProcess::setProcessChannelMode; + using QProcess::processChannelMode; + + Q_PRIVATE_SLOT(d_func(), void _k_forwardStdout()) + Q_PRIVATE_SLOT(d_func(), void _k_forwardStderr()) +}; + +#endif + diff --git a/kgpg/kprocess_p.h b/kgpg/kprocess_p.h new file mode 100644 index 0000000..11d3356 --- /dev/null +++ b/kgpg/kprocess_p.h @@ -0,0 +1,50 @@ +/* + This file is part of the KDE libraries + + Copyright (C) 2007 Oswald Buddenhagen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KPROCESS_P_H +#define KPROCESS_P_H + +#include "kprocess.h" + +//class KProcess; + +class KProcessPrivate { + Q_DECLARE_PUBLIC(KProcess) +protected: + KProcessPrivate() : + openMode(QIODevice::ReadWrite) + { + } + void writeAll(const QByteArray &buf, int fd); + void forwardStd(KProcess::ProcessChannel good, int fd); + void _k_forwardStdout(); + void _k_forwardStderr(); + + QString prog; + QStringList args; + KProcess::OutputChannelMode outputChannelMode; + QIODevice::OpenMode openMode; + + KProcess *q_ptr; +}; + + +#endif diff --git a/kgpg/transactions/kgpgdecrypt.cpp b/kgpg/transactions/kgpgdecrypt.cpp new file mode 100644 index 0000000..20f0c50 --- /dev/null +++ b/kgpg/transactions/kgpgdecrypt.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2010,2011,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgdecrypt.h" + +#include "../gpgproc.h" +//#include "kgpgsettings.h" + +//#include + +KGpgDecrypt::KGpgDecrypt(QObject *parent, const QString &text) + : KGpgTextOrFileTransaction(parent, text), + m_fileIndex(-1), + m_plainLength(-1) +{ +} + +KGpgDecrypt::KGpgDecrypt(QObject *parent, const QList &files) + : KGpgTextOrFileTransaction(parent, files), + m_fileIndex(0), + m_plainLength(-1) +{ +} + +KGpgDecrypt::KGpgDecrypt(QObject* parent, const QUrl& infile, const QUrl& outfile) + : KGpgTextOrFileTransaction(parent, QList() << infile ), + m_fileIndex(0), + m_plainLength(-1), + m_outFilename(outfile.toLocalFile()) +{ +} + +KGpgDecrypt::~KGpgDecrypt() +{ +} + +QStringList +KGpgDecrypt::command() const +{ + QStringList ret; + + ret << QLatin1String("--decrypt") << QLatin1String("--command-fd=0"); + + if (!m_outFilename.isEmpty()) + ret << QLatin1String("-o") << m_outFilename; + + //ret << KGpgSettings::customDecrypt().simplified().split(QLatin1Char(' '), QString::SkipEmptyParts); + + return ret; +} + +QStringList +KGpgDecrypt::decryptedText() const +{ + QStringList result; + int txtlength = 0; + + foreach (const QString &line, getMessages()) + if (!line.startsWith(QLatin1String("[GNUPG:] "))) { + result.append(line); + txtlength += line.length() + 1; + } + + if (result.isEmpty()) + return result; + + QString last = result.last(); + // this may happen when the original text did not end with a newline + if (last.endsWith(QLatin1String("[GNUPG:] DECRYPTION_OKAY"))) { + // if GnuPG doesn't tell us the length assume that this happend + // if it told us the length then check if it _really_ happend + if (((m_plainLength != -1) && (txtlength != m_plainLength)) || + (m_plainLength == -1)) { + last.chop(24); + result[result.count() - 1] = last; + } + } + + return result; +} + +bool +KGpgDecrypt::isEncryptedText(const QString &text, int *startPos, int *endPos) +{ + int posStart = text.indexOf(QLatin1String("-----BEGIN PGP MESSAGE-----")); + if (posStart == -1) + return false; + + int posEnd = text.indexOf(QLatin1String("-----END PGP MESSAGE-----"), posStart); + if (posEnd == -1) + return false; + + if (startPos != NULL) + *startPos = posStart; + if (endPos != NULL) + *endPos = posEnd; + + return true; +} + +bool +KGpgDecrypt::nextLine(const QString& line) +{ + const QList &inputFiles = getInputFiles(); + + if (!inputFiles.isEmpty()) { + if (line == QLatin1String("[GNUPG:] BEGIN_DECRYPTION")) { + emit statusMessage(tr("Status message 'Decrypting ' (operation starts)", "Decrypting %1").arg(inputFiles.at(m_fileIndex).toLocalFile())); + emit infoProgress(2 * m_fileIndex + 1, inputFiles.count() * 2); + } else if (line == QLatin1String("[GNUPG:] END_DECRYPTION")) { + emit statusMessage(tr("Status message 'Decrypted ' (operation was completed)", "Decrypted %1").arg(inputFiles.at(m_fileIndex).toLocalFile())); + m_fileIndex++; + emit infoProgress(2 * m_fileIndex, inputFiles.count() * 2); + } + } else { + if (line.startsWith(QLatin1String("[GNUPG:] PLAINTEXT_LENGTH "))) { + bool ok; + m_plainLength = line.mid(26).toInt(&ok); + if (!ok) + m_plainLength = -1; + } else if (line == QLatin1String("[GNUPG:] BEGIN_DECRYPTION")) { + // close the command channel (if any) to signal GnuPG that it + // can start sending the output. + getProcess()->closeWriteChannel(); + } + } + + return KGpgTextOrFileTransaction::nextLine(line); +} + +//#include "kgpgdecrypt.moc" diff --git a/kgpg/transactions/kgpgdecrypt.h b/kgpg/transactions/kgpgdecrypt.h new file mode 100644 index 0000000..aa28c19 --- /dev/null +++ b/kgpg/transactions/kgpgdecrypt.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010,2011 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGDECRYPT_H +#define KGPGDECRYPT_H + +#include + +#include + +#include "kgpgtextorfiletransaction.h" + +class QProcess; +class QStringList; + +/** + * @brief decrypt the given text or files + */ +class KGpgDecrypt: public KGpgTextOrFileTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgDecrypt) + KGpgDecrypt(); // = delete C++0x +public: + /** + * @brief decrypt given text + * @param parent parent object + * @param text text to decrypt + */ + explicit KGpgDecrypt(QObject *parent, const QString &text = QString()); + + /** + * @brief decrypt file(s) + * @param parent parent object + * @param files list of file locations to decrypt + */ + KGpgDecrypt(QObject *parent, const QList &files); + + /** + * @brief decrypt file to given output filename + * @param parent parent object + * @param infile name of file to decrypt + * @param outfile name of file to write output to (will be overwritten) + */ + KGpgDecrypt(QObject *parent, const QUrl &infile, const QUrl &outfile); + + /** + * @brief destructor + */ + virtual ~KGpgDecrypt(); + + /** + * @brief get decryption result + * @return decrypted text + */ + QStringList decryptedText() const; + + /** + * @brief check if the given text contains an encoded message + * @param text text to check + * @param startPos if not NULL start offset of encoded text will be returned here + * @param endPos if not NULL end offset of encoded text will be returned here + */ + static bool isEncryptedText(const QString &text, int *startPos = NULL, int *endPos = NULL); + +protected: + virtual QStringList command() const; + virtual bool nextLine(const QString &line); + +private: + int m_fileIndex; + int m_plainLength; ///< length of decrypted plain text if given by GnuPG + const QString m_outFilename; ///< name of file to write output to +}; + +#endif // KGPGDECRYPT_H diff --git a/kgpg/transactions/kgpgdelkey.cpp b/kgpg/transactions/kgpgdelkey.cpp new file mode 100644 index 0000000..ac09610 --- /dev/null +++ b/kgpg/transactions/kgpgdelkey.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008,2009,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgdelkey.h" + +#include "../gpgproc.h" + +#include +#include + +/*KGpgDelKey::KGpgDelKey(QObject *parent, KGpgKeyNode *key) + : KGpgTransaction(parent) +{ + m_keys << key; + setCmdLine(); +}*/ + +KGpgDelKey::KGpgDelKey(QObject *parent, const QStringList &uids) + : KGpgTransaction(parent), + m_uids(uids) +{ + setCmdLine(); +} + +KGpgDelKey::~KGpgDelKey() +{ +} + +QStringList +KGpgDelKey::keys() const +{ + return m_uids; +} + +bool +KGpgDelKey::nextLine(const QString &line) +{ + if (!line.startsWith(QLatin1String("[GNUPG:] GOT_IT"))) + setSuccess(KGpgTransaction::TS_MSG_SEQUENCE); + + return false; +} + +KGpgTransaction::ts_boolanswer +KGpgDelKey::boolQuestion(const QString &line) +{ + if (line.startsWith(QLatin1String("delete_key.okay"))) + return KGpgTransaction::BA_YES; + + if (line.startsWith(QLatin1String("delete_key.secret.okay"))) + return KGpgTransaction::BA_YES; + + return KGpgTransaction::boolQuestion(line); +} + +bool +KGpgDelKey::preStart() +{ + GPGProc *proc = getProcess(); + QStringList args = proc->program(); + + /*foreach (const KGpgKeyNode *key, m_keys) + args << key->getFingerprint();*/ + foreach (const QString uid, m_uids) + args << uid; + + proc->setProgram(args); + + setSuccess(KGpgTransaction::TS_OK); + + return true; +} + +void +KGpgDelKey::setCmdLine() +{ + addArgument(QLatin1String( "--status-fd=1" )); + addArgument(QLatin1String( "--command-fd=0" )); + addArgument(QLatin1String( "--delete-secret-and-public-key" )); + + m_argscount = getProcess()->program().count(); +} + +//#include "kgpgdelkey.moc" diff --git a/kgpg/transactions/kgpgdelkey.h b/kgpg/transactions/kgpgdelkey.h new file mode 100644 index 0000000..c7a35ae --- /dev/null +++ b/kgpg/transactions/kgpgdelkey.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008,2009 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGDELKEY_H +#define KGPGDELKEY_H + +#include "kgpgtransaction.h" + +#include "../core/KGpgKeyNode.h" + +#include + +/** + * @brief delete a public key + */ +class KGpgDelKey: public KGpgTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgDelKey) + KGpgDelKey(); // = delete C++0x +public: + //KGpgDelKey(QObject *parent, KGpgKeyNode *key); + KGpgDelKey(QObject *parent, const QStringList &uids); + virtual ~KGpgDelKey(); + + /** + * @brief the keys that were requested to be removed + * @return the list of key nodes + */ + QStringList keys() const; + +protected: + virtual bool nextLine(const QString &line); + virtual ts_boolanswer boolQuestion(const QString &line); + virtual bool preStart(); + +private: + //KGpgKeyNode::List m_keys; + QStringList m_uids; + int m_argscount; + + void setCmdLine(); +}; + +#endif // KGPGDELKEY_H diff --git a/kgpg/transactions/kgpgencrypt.cpp b/kgpg/transactions/kgpgencrypt.cpp new file mode 100644 index 0000000..4891bf0 --- /dev/null +++ b/kgpg/transactions/kgpgencrypt.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2011,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include "kgpgencrypt.h" + +//#include "kgpgsettings.h" +#include "../gpgproc.h" + +//#include +//#include +#include + +static QStringList trustOptions(const QString &binary) +{ + const int gpgver = GPGProc::gpgVersion(GPGProc::gpgVersionString(binary)); + QStringList args; + if (gpgver >= 0x10302) + args << QLatin1String("--trust-model") + << QLatin1String("always"); + else + args << QLatin1String("--always-trust"); + + return args; +} + +KGpgEncrypt::KGpgEncrypt(QObject *parent, const QStringList &userIds, const QString &text, const EncryptOptions &options, const QStringList &extraOptions) + : KGpgTextOrFileTransaction(parent, text), + m_fileIndex(-1), + m_options(options), + m_userIds(userIds), + m_extraOptions(extraOptions) +{ + if ((m_options & AllowUntrustedEncryption) && !m_userIds.isEmpty()) + m_extraOptions << trustOptions(getProcess()->program().at(0)); +} + +KGpgEncrypt::KGpgEncrypt(QObject *parent, const QStringList &userIds, const QList &files, const EncryptOptions &options, const QStringList &extraOptions) + : KGpgTextOrFileTransaction(parent, files), + m_fileIndex(0), + m_options(options), + m_userIds(userIds), + m_extraOptions(extraOptions) +{ + if ((m_options & AllowUntrustedEncryption) && !m_userIds.isEmpty()) + m_extraOptions << trustOptions(getProcess()->program().at(0)); +} + +KGpgEncrypt::~KGpgEncrypt() +{ +} + +QStringList +KGpgEncrypt::command() const +{ + QStringList ret = m_extraOptions; + + if (m_options.testFlag(AsciiArmored)) + ret << QLatin1String("--armor"); + + if (m_userIds.isEmpty()) { + ret << QLatin1String( "--symmetric" ); + } else { + if (m_options.testFlag(HideKeyId)) + ret << QLatin1String("--throw-keyid"); + + foreach (const QString &uid, m_userIds) + ret << QLatin1String( "--recipient" ) << uid; + ret << QLatin1String( "--encrypt" ); + } + + return ret; +} + +QStringList +KGpgEncrypt::encryptedText() const +{ + QStringList result; + int txtlength = 0; + + foreach (const QString &line, getMessages()) + if (!line.startsWith(QLatin1String("[GNUPG:] "))) { + result.append(line); + txtlength += line.length() + 1; + } + + return result; +} + +bool +KGpgEncrypt::nextLine(const QString &line) +{ + const QList &inputFiles = getInputFiles(); + + if (line.startsWith(QLatin1String("[GNUPG:] MISSING_PASSPHRASE"))) { + setSuccess(KGpgTransaction::TS_BAD_PASSPHRASE); + return true; + } + + if (!inputFiles.isEmpty()) { + static const QString encStart = QLatin1String("[GNUPG:] FILE_START 2 "); + static const QString encDone = QLatin1String("[GNUPG:] FILE_DONE"); + static const QString askName = QLatin1String("[GNUPG:] GET_LINE openfile.askoutname"); + + if (line.startsWith(encStart)) { + m_currentFile = line.mid(encStart.length()); + emit statusMessage(tr("Status message 'Encrypting ' (operation starts)", "Encrypting %1").arg(m_currentFile)); + emit infoProgress(2 * m_fileIndex + 1, inputFiles.count() * 2); + } else if (line == encDone) { + emit statusMessage(tr("Status message 'Encrypted ' (operation was completed)", "Encrypted %1").arg(m_currentFile)); + m_fileIndex++; + emit infoProgress(2 * m_fileIndex, inputFiles.count() * 2); +// TODO +/* } else if (line == askName) { + QPointer over = new KIO::RenameDialog(qobject_cast(parent()), + i18n("File Already Exists"), KUrl(), + KUrl::fromPath(m_currentFile + encryptExtension(m_options.testFlag(AsciiArmored))), + KIO::M_OVERWRITE); + + if (over->exec() != QDialog::Accepted) { + delete over; + setSuccess(KGpgTransaction::TS_USER_ABORTED); + return true; + } + write(over->newDestUrl().path().toUtf8()); + delete over;*/ + } + } + + return KGpgTextOrFileTransaction::nextLine(line); +} + +QString +KGpgEncrypt::encryptExtension(const bool ascii) +{ + if (ascii) + return QLatin1String( ".asc" ); + /*else if (KGpgSettings::pgpExtension()) + return QLatin1String( ".pgp" );*/ + else + return QLatin1String( ".gpg" ); +} + +//#include "kgpgencrypt.moc" diff --git a/kgpg/transactions/kgpgencrypt.h b/kgpg/transactions/kgpgencrypt.h new file mode 100644 index 0000000..ad9d89c --- /dev/null +++ b/kgpg/transactions/kgpgencrypt.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGENCRYPT_H +#define KGPGENCRYPT_H + +#include +#include +#include + +#include + +#include "kgpgtextorfiletransaction.h" + +class QProcess; + +/** + * @brief encrypt the given text or files + */ +class KGpgEncrypt: public KGpgTextOrFileTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgEncrypt) + KGpgEncrypt(); // = delete C++0x +public: + enum EncryptOption { + DefaultEncryption = 0, ///< use whatever GnuPGs defaults are + AsciiArmored = 0x1, ///< output the data as printable ASCII as opposed to binary data + AllowUntrustedEncryption = 0x2, ///< allow encryption with untrusted keys, ignored for symmetric encryption + HideKeyId = 0x4 ///< remove anything that shows which key ids this data is encrypted to, ignored for symmetric encryption + }; + Q_DECLARE_FLAGS(EncryptOptions, EncryptOption); + + /** + * @brief encrypt given text + * @param parent parent object + * @param userIds ids to encrypt to or empty list to use symmetric encryption with passphrase + * @param text text to encrypt + * @param options encryption options + */ + explicit KGpgEncrypt(QObject *parent, const QStringList &userIds = QStringList(), const QString &text = QString(), const EncryptOptions &options = DefaultEncryption, const QStringList &extraOptions = QStringList()); + + /** + * @brief encrypt file(s) + * @param parent parent object + * @param userIds ids to encrypt to or empty list to use symmetric encryption with passphrase + * @param files list of file locations to encrypt + * @param options encryption options + */ + KGpgEncrypt(QObject *parent, const QStringList &userIds, const QList &files, const EncryptOptions &options = DefaultEncryption, const QStringList &extraOptions = QStringList()); + + /** + * @brief destructor + */ + virtual ~KGpgEncrypt(); + + /** + * @brief get decryption result + * @return decrypted text + */ + QStringList encryptedText() const; + + /** + * @brief return the preferred extension for encrypted files + * @param ascii if the file is encrypted with ASCII armor + * @return the file extension with leading dot + */ + static QString encryptExtension(const bool ascii); + +protected: + virtual QStringList command() const; + virtual bool nextLine(const QString &line); + +private: + int m_fileIndex; + const EncryptOptions m_options; + const QStringList m_userIds; + QStringList m_extraOptions; + QString m_currentFile; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(KGpgEncrypt::EncryptOptions); + +#endif // KGPGENCRYPT_H diff --git a/kgpg/transactions/kgpgexport.cpp b/kgpg/transactions/kgpgexport.cpp new file mode 100644 index 0000000..79f6afe --- /dev/null +++ b/kgpg/transactions/kgpgexport.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2009,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgexport.h" + +#include "../gpgproc.h" + +#include +#include + +KGpgExport::KGpgExport(QObject *parent, const QStringList &ids, QProcess *outp, const QStringList &options, const bool secret) + : KGpgTransaction(parent), + m_keyids(ids), + m_outp(outp), + m_outputmode(ModeProcess) +{ + procSetup(options, secret); +} + +KGpgExport::KGpgExport(QObject *parent, const QStringList &ids, const QString &file, const QStringList &options, const bool secret) + : KGpgTransaction(parent), + m_keyids(ids), + m_outp(NULL), + m_outf(file), + m_outputmode(ModeFile) +{ + procSetup(options, secret); +} + +KGpgExport::KGpgExport(QObject *parent, const QStringList &ids, const QStringList &options, const bool secret) + : KGpgTransaction(parent), + m_keyids(ids), + m_outp(NULL), + m_outputmode(ModeStdout) +{ + procSetup(options, secret); +} + +KGpgExport::KGpgExport(QObject *parent, const QStringList &ids, KGpgTransaction *outt, const QStringList &options, const bool secret) + : KGpgTransaction(parent), + m_keyids(ids), + m_outp(NULL), + m_outputmode(ModeTransaction) +{ + procSetup(options, secret); + outt->setInputTransaction(this); +} + +KGpgExport::~KGpgExport() +{ +} + +void +KGpgExport::setKeyId(const QString &id) +{ + m_keyids.clear(); + m_keyids.append(id); +} + +void +KGpgExport::setKeyIds(const QStringList &ids) +{ + m_keyids = ids; +} + +const QStringList & +KGpgExport::getKeyIds() const +{ + return m_keyids; +} + +void +KGpgExport::setOutputProcess(QProcess *outp) +{ + m_outf.clear(); + m_outp = outp; + m_outputmode = ModeProcess; +} + +void +KGpgExport::setOutputFile(const QString &filename) +{ + m_outp = NULL; + m_outf = filename; + if (filename.isEmpty()) + m_outputmode = ModeStdout; + else + m_outputmode = ModeFile; +} + +void +KGpgExport::setOutputTransaction(KGpgTransaction *outt) +{ + m_outp = NULL; + m_outf.clear(); + m_outputmode = ModeTransaction; + outt->setInputTransaction(this); +} + +const QString & +KGpgExport::getOutputFile() const +{ + return m_outf; +} + +const QByteArray & +KGpgExport::getOutputData() const +{ + return m_data; +} + +bool +KGpgExport::preStart() +{ + setSuccess(TS_OK); + + switch (m_outputmode) { + case ModeFile: + { + Q_ASSERT(!m_outf.isEmpty()); + Q_ASSERT(m_outp == NULL); + + addArgument(QLatin1String( "--output" )); + addArgument(m_outf); + + QFile ofile(m_outf); + if (ofile.exists()) + ofile.remove(); + + break; + } + case ModeProcess: + Q_ASSERT(m_outf.isEmpty()); + Q_ASSERT(m_outp != NULL); + + getProcess()->setStandardOutputProcess(m_outp); + + break; + case ModeStdout: + Q_ASSERT(m_outf.isEmpty()); + Q_ASSERT(m_outp == NULL); + break; + case ModeTransaction: + Q_ASSERT(m_outf.isEmpty()); + Q_ASSERT(m_outp == NULL); + break; + default: + Q_ASSERT(0); + } + + addArguments(m_keyids); + + m_data.clear(); + + return true; +} + +bool +KGpgExport::nextLine(const QString &line) +{ + // key exporting does not send any messages + + m_data.append(line.toAscii() + '\n'); + + if (m_outputmode != 2) + setSuccess(TS_MSG_SEQUENCE); + + return false; +} + +void +KGpgExport::procSetup(const QStringList &options, const bool secret) +{ + getProcess()->resetProcess(); + + if (secret) + addArgument(QLatin1String( "--export-secret-key" )); + else + addArgument(QLatin1String( "--export" )); + + if ((m_outputmode == 2) && !options.contains(QLatin1String( "--armor" ))) + addArgument(QLatin1String( "--armor" )); + + addArguments(options); +} + +//#include "kgpgexport.moc" diff --git a/kgpg/transactions/kgpgexport.h b/kgpg/transactions/kgpgexport.h new file mode 100644 index 0000000..63aeaac --- /dev/null +++ b/kgpg/transactions/kgpgexport.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2009 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGEXPORT_H +#define KGPGEXPORT_H + +#include +#include + +#include + +#include "kgpgtransaction.h" + +class QProcess; + +/** + * @brief export one or more keys from keyring + * + * The exported keys can be written to a file or sent to standard input of another + * QProcess. + */ +class KGpgExport: public KGpgTransaction { + Q_OBJECT + + KGpgExport(); // = delete C++0x + Q_DISABLE_COPY(KGpgExport) +public: + /** + * @brief export keys to QProcess + * @param parent parent object + * @param ids ids to export + * @param outp process to write into + * @param options additional options to pass to GnuPG (e.g. export ascii armored) + * @param secret if secret key exporting is allowed + */ + KGpgExport(QObject *parent, const QStringList &ids, QProcess *outp, const QStringList &options = QStringList(), const bool secret = false); + + /** + * @brief export keys to KGpgTransaction + * @param parent parent object + * @param ids ids to export + * @param outt transaction to write into + * @param options additional options to pass to GnuPG (e.g. export ascii armored) + * @param secret if secret key exporting is allowed + */ + KGpgExport(QObject *parent, const QStringList &ids, KGpgTransaction *outt, const QStringList &options = QStringList(), const bool secret = false); + + /** + * @brief export keys to file + * @param parent parent object + * @param ids ids to export + * @param file filename to write into + * @param options additional options to pass to GnuPG (e.g. export ascii armored) + * @param secret if secret key exporting is allowed + */ + KGpgExport(QObject *parent, const QStringList &ids, const QString &file, const QStringList &options = QStringList(), const bool secret = false); + + /** + * @brief export keys to standard output + * @param parent parent object + * @param ids ids to export + * @param options additional options to pass to GnuPG (e.g. export ascii armored) + * @param secret if secret key exporting is allowed + * + * Only ascii-armored export is supported in standard output mode. If it is not + * already set in the given option it will be added automatically. + */ + KGpgExport(QObject *parent, const QStringList &ids, const QStringList &options = QStringList(), const bool secret = false); + + /** + * @brief destructor + */ + virtual ~KGpgExport(); + + /** + * @brief set key id to export + * @param id key fingerprint + */ + void setKeyId(const QString &id); + /** + * @brief set key ids to export + * @param ids key fingerprints + */ + void setKeyIds(const QStringList &ids); + /** + * @brief return the key ids to export + * @return list of key fingerprints + */ + const QStringList &getKeyIds() const; + /** + * @brief set the process the output is sent to + * @param outp process to send output to + */ + void setOutputProcess(QProcess *outp); + /** + * @brief set the transaction the output is sent to + * @param outd transaction to send output to + */ + void setOutputTransaction(KGpgTransaction *outt); + /** + * @brief set filename to send output to + * @param filename file to send output to + */ + void setOutputFile(const QString &filename); + /** + * @brief return the output filename currently set + * @return filename key will get written to + */ + const QString &getOutputFile() const; + /** + * @brief return the data read from standard output + * @return standard output data + */ + const QByteArray &getOutputData() const; + +protected: + virtual bool preStart(); + virtual bool nextLine(const QString &line); + +private: + QStringList m_keyids; + QProcess *m_outp; + QString m_outf; + QByteArray m_data; + + enum OutputMode { + ModeFile = 0, + ModeProcess = 1, + ModeStdout = 2, + ModeTransaction = 3 + }; + enum OutputMode m_outputmode; + + void procSetup(const QStringList &options, const bool secret); +}; + +#endif // KGPGEXPORT_H diff --git a/kgpg/transactions/kgpggeneratekey.cpp b/kgpg/transactions/kgpggeneratekey.cpp new file mode 100644 index 0000000..d95f1e0 --- /dev/null +++ b/kgpg/transactions/kgpggeneratekey.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpggeneratekey.h" + +#include "../gpgproc.h" + +//#include +//#include +//#include +#include + +KGpgGenerateKey::KGpgGenerateKey(QObject *parent, const QString &name, const QString &email, const QString &comment, + const KgpgCore::KgpgKeyAlgo &algorithm, const uint size, const unsigned int expire, + const char expireunit) + : KGpgTransaction(parent) +{ + addArgument(QLatin1String( "--status-fd=1" )); + addArgument(QLatin1String( "--command-fd=0" )); + addArgument(QLatin1String( "--no-verbose" )); + addArgument(QLatin1String( "--gen-key" )); + addArgument(QLatin1String( "--batch" )); + + setName(name); + setEmail(email); + setComment(comment); + setAlgorithm(algorithm); + setSize(size); + setExpire(expire, expireunit); + + getProcess()->setOutputChannelMode(KProcess::SeparateChannels); +} + +KGpgGenerateKey::~KGpgGenerateKey() +{ +} + +bool +KGpgGenerateKey::preStart() +{ + /*if (!m_email.isEmpty() && !KPIMUtils::isValidSimpleAddress(m_email)) { + setSuccess(TS_INVALID_EMAIL); + return false; + }*/ + + m_fingerprint.clear(); + m_namesent = false; + + setSuccess(TS_MSG_SEQUENCE); + + setDescription(QObject::tr("Generating New Key for %1").arg(m_name)); + + return true; +} + +void +KGpgGenerateKey::postStart() +{ + QByteArray keymessage("Key-Type: "); + switch (m_algorithm) { + case KgpgCore::ALGO_RSA: + keymessage.append("RSA"); + break; + case KgpgCore::ALGO_RSA_RSA: + keymessage.append("RSA\nSubkey-Type: RSA"); + break; + case KgpgCore::ALGO_DSA_ELGAMAL: + keymessage.append("DSA\nSubkey-Type: ELG-E"); + break; + default: + Q_ASSERT(m_algorithm == KgpgCore::ALGO_RSA); + return; + } + + const QByteArray keylen = QByteArray::number(m_size); + + keymessage.append("\nKey-Length: "); + keymessage.append(keylen); + keymessage.append("\nSubkey-Length: "); + keymessage.append(keylen); + keymessage.append("\nName-Real: "); + keymessage.append(m_name.toUtf8()); + if (!m_email.isEmpty()) { + keymessage.append("\nName-Email: "); + keymessage.append(m_email.toAscii()); + } + if (!m_comment.isEmpty()) { + keymessage.append("\nName-Comment: "); + keymessage.append(m_comment.toUtf8()); + } + if (m_expire != 0) { + keymessage.append("\nExpire-Date: "); + keymessage.append(QByteArray::number(m_expire)); + keymessage.append(m_expireunit); + } + keymessage.append("\nPassphrase: "); + write(keymessage, false); + + QString passdlgmessage; + if (!m_email.isEmpty()) { + passdlgmessage = QObject::tr("

Enter passphrase for %1 <%2>:
Passphrase should include non alphanumeric characters and random sequences.

").arg(m_name).arg(m_email); + } else { + passdlgmessage = QObject::tr("

Enter passphrase for %1:
Passphrase should include non alphanumeric characters and random sequences.

").arg(m_name); + } + + QApplication::restoreOverrideCursor(); + askNewPassphrase(passdlgmessage); +} + +bool +KGpgGenerateKey::nextLine(const QString &line) +{ + QString msg(QObject::tr("Generating Key")); + + if (!line.startsWith(QLatin1String("[GNUPG:] "))) + return false; + + int result = false; + + if (line.contains(QLatin1String( "PROGRESS" ))) { + QStringList parts(line.mid(18).split(QLatin1Char( ' ' ))); + if (parts.count() >= 4) { + const QString p0(parts.at(0)); + if (p0 == QLatin1String( "primegen" )) { + msg = tr("Generating prime numbers"); + } else if (p0 == QLatin1String( "pk_dsa" )) { + msg = tr("Generating DSA key"); + } else if (p0 == QLatin1String( "pk_elg" )) { + msg = tr("Generating ElGamal key"); + } else if (p0 == QLatin1String( "need_entropy" )) { + msg = tr("Waiting for entropy"); + + // This message is currenlty not displayed. Nevertheless it's + // included here so string freeze is not broken if it will be + // displayed later on. + QString msglong = tr("The entropy pool ran empty. The key generation process is stalled until enough entropy is present. You can generate entropy e.g. by moving the mouse or typing at the keyboard. The easiest way is by using another application until the key generation continues."); + } + if (parts.at(3) != QLatin1String( "0" )) + emit infoProgress(parts.at(2).toUInt(), parts.at(3).toUInt()); + } + } else if (line.contains(QLatin1String( "GOOD_PASSPHRASE" ))) { + setSuccess(TS_MSG_SEQUENCE); + } else if (line.contains(QLatin1String( "KEY_CREATED" ))) { + m_fingerprint = line.right(40); + setSuccess(TS_OK); + result = true; + } else if (line.contains(QLatin1String( "NEED_PASSPHRASE" ))) { + setSuccess(TS_USER_ABORTED); + } else if (line.contains(QLatin1String( "GET_" ))) { + setSuccess(TS_MSG_SEQUENCE); + result = true; + } else if (line.contains(QLatin1String("KEY_NOT_CREATED"))) { + result = true; + } + + emit statusMessage(msg); + + return result; +} + +void +KGpgGenerateKey::finish() +{ + switch (getSuccess()) { + case TS_BAD_PASSPHRASE: + emit statusMessage(tr("Bad passphrase. Cannot generate a new key pair.")); + break; + case TS_USER_ABORTED: + emit statusMessage(tr("Aborted by the user. Cannot generate a new key pair.")); + break; + case TS_INVALID_EMAIL: + emit statusMessage(tr("The email address is not valid. Cannot generate a new key pair.")); + break; + case TS_INVALID_NAME: + emit statusMessage(tr("The name is not accepted by gpg. Cannot generate a new key pair.")); + break; + case TS_OK: + emit statusMessage(tr("Key %1 generated").arg(getFingerprint())); + break; + default: + { + QStringList errorLines; + + while (getProcess()->hasLineStandardError()) { + QByteArray b; + getProcess()->readLineStandardError(&b); + errorLines << QString::fromUtf8(b); + } + + m_errorOutput = errorLines.join(QLatin1String("\n")); + emit statusMessage(tr("gpg process did not finish. Cannot generate a new key pair.")); + } + } +} + +void +KGpgGenerateKey::newPasswordEntered() +{ + QApplication::setOverrideCursor(Qt::BusyCursor); + write("%commit"); +} + +void +KGpgGenerateKey::setName(const QString &name) +{ + m_name = name; +} + +QString +KGpgGenerateKey::getName() const +{ + return m_name; +} + +void +KGpgGenerateKey::setEmail(const QString &email) +{ + m_email = email; +} + +QString +KGpgGenerateKey::getEmail() const +{ + return m_email; +} + +void +KGpgGenerateKey::setComment(const QString &comment) +{ + m_comment = comment; +} + +void +KGpgGenerateKey::setAlgorithm(const KgpgCore::KgpgKeyAlgo &algorithm) +{ + m_algorithm = algorithm; +} + +void +KGpgGenerateKey::setSize(const unsigned int size) +{ + m_size = size; +} + +void +KGpgGenerateKey::setExpire(const unsigned int expire, const char expireunit) +{ + Q_ASSERT((expireunit == 'd') || (expireunit == 'w') || + (expireunit == 'm') || (expireunit == 'y')); + m_expire = expire; + m_expireunit = expireunit; +} + +QString +KGpgGenerateKey::getFingerprint() const +{ + return m_fingerprint; +} + +QString +KGpgGenerateKey::gpgErrorMessage() const +{ + return m_errorOutput; +} + +//#include "kgpggeneratekey.moc" diff --git a/kgpg/transactions/kgpggeneratekey.h b/kgpg/transactions/kgpggeneratekey.h new file mode 100644 index 0000000..3649d8f --- /dev/null +++ b/kgpg/transactions/kgpggeneratekey.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008,2009,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGGENERATEKEY_H +#define KGPGGENERATEKEY_H + +#include "kgpgtransaction.h" + +#include "../core/kgpgkey.h" + +#include + +class QString; + +/** + * @brief generate a new key pair + */ +class KGpgGenerateKey: public KGpgTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgGenerateKey) + KGpgGenerateKey(); // = delete C++0x +public: + enum ts_generatekey { + TS_INVALID_NAME = TS_COMMON_END + 1 ///< the owners name is not accepted by GnuPG + }; + /** + * @brief KGpgGenerateKey's constructor + * @param parent parent object + * @param name the name of the key, it is also the user's name. + * @param email email MUST be a valid email address or an empty string. + * @param comment is a comment, it can be an empty string + * @param algorithm this is the type of the key, RSA or DSA & ELGAMAL (\see Kgpg::KeyAlgo ). + * @param size this is the length of the key (1024, 2048, ...) + * @param expire defines the key expiry time together with \em expireunit, 0 for unlimited key lifetime + * @param expireunit is the unit of the number given as \em expire. \see setExpire + */ + KGpgGenerateKey(QObject *parent, const QString &name, const QString &email, const QString &comment, + const KgpgCore::KgpgKeyAlgo &algorithm, const uint size, const unsigned int expire = 0, + const char expireunit = 'd'); + virtual ~KGpgGenerateKey(); + + void setName(const QString &name); + QString getName() const; + void setEmail(const QString &email); + QString getEmail() const; + void setComment(const QString &comment); + void setAlgorithm(const KgpgCore::KgpgKeyAlgo &algorithm); + void setSize(const unsigned int size); + /** + * @brief set expire date for key + * @param expire defines the key expiry time together with \em expireunit, 0 for unlimited key lifetime + * @param expireunit is the unit of the number given as \em expire. + * + * Valid units are 'd', 'w', 'm' and 'y'. The unit is ignored if expire is 0. + */ + void setExpire(const unsigned int expire, const char expireunit); + + QString getFingerprint() const; + + /** + * @brief get error output of GnuPG + * @return the messages GnuPG printed to standard error + * + * This will only return data after the done() signal has been emitted. + */ + QString gpgErrorMessage() const; + +protected: + virtual bool preStart(); + virtual void postStart(); + virtual bool nextLine(const QString &line); + virtual void finish(); + virtual void newPasswordEntered(); + +private: + QString m_name; + QString m_email; + QString m_comment; + KgpgCore::KgpgKeyAlgo m_algorithm; + unsigned int m_size; + unsigned int m_expire; + unsigned int m_expireunit; + QString m_fingerprint; + bool m_namesent; + QString m_errorOutput; +}; + +#endif // KGPGGENERATEKEY_H diff --git a/kgpg/transactions/kgpgimport.cpp b/kgpg/transactions/kgpgimport.cpp new file mode 100644 index 0000000..4a3041c --- /dev/null +++ b/kgpg/transactions/kgpgimport.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2008,2009,2010,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgimport.h" + +//#include "model/kgpgitemmodel.h" +#include "../core/KGpgKeyNode.h" + +#include +//#include + +KGpgImport::KGpgImport(QObject *parent, const QString &text) + : KGpgTextOrFileTransaction(parent, text, true) +{ +} + +KGpgImport::KGpgImport(QObject *parent, const QList &files) + : KGpgTextOrFileTransaction(parent, files, true) +{ +} + +KGpgImport::~KGpgImport() +{ +} + +QStringList +KGpgImport::command() const +{ + QStringList ret; + + ret << QLatin1String( "--import" ) << QLatin1String( "--allow-secret-key-import" ); + + return ret; +} + +QStringList +KGpgImport::getImportedKeys() const +{ + QStringList res; + + foreach (const QString &str, getMessages()) + if (str.startsWith(QLatin1String("[GNUPG:] IMPORTED "))) + res << str.mid(18); + + return res; +} + +QStringList +KGpgImport::getImportedIds(const QStringList &log, const int reason) +{ + QStringList res; + + foreach (const QString &str, log) { + if (!str.startsWith(QLatin1String("[GNUPG:] IMPORT_OK "))) + continue; + + QString tmpstr(str.mid(19).simplified()); + + int space = tmpstr.indexOf(QLatin1Char( ' ' )); + if (space <= 0) { + qDebug() << __LINE__ << "invalid format:" << str; + continue; + } + + bool ok; + unsigned char code = tmpstr.left(space).toUInt(&ok); + if (!ok) { + qDebug() << __LINE__ << "invalid format:" << str << space << tmpstr.left(space - 1); + continue; + } + + if ((reason == -1) || ((reason == 0) && (code == 0)) || ((reason & code) != 0)) + res << tmpstr.mid(space + 1); + } + + return res; +} + +QStringList +KGpgImport::getImportedIds(const int reason) const +{ + return getImportedIds(getMessages(), reason); +} + +QString +KGpgImport::getImportMessage() const +{ + return getImportMessage(getMessages()); +} + +QString +KGpgImport::getImportMessage(const QStringList &log) +{ +#define RESULT_PARTS 14 + unsigned long rcode[RESULT_PARTS]; + unsigned int i = 0; + int line = 0; + bool fine; + + memset(rcode, 0, sizeof(rcode)); + + foreach (const QString &str, log) { + line++; + if (!str.startsWith(QLatin1String("[GNUPG:] IMPORT_RES "))) + continue; + + const QStringList rstr(str.mid(20).simplified().split(QLatin1Char( ' ' ))); + + fine = (rstr.count() == RESULT_PARTS); + + i = 0; + while (fine && (i < RESULT_PARTS)) { + rcode[i] += rstr.at(i).toULong(&fine); + i++; + } + + if (!fine) + return tr("The import result string has an unsupported format in line %1.
Please see the detailed log for more information.").arg(line); + } + + fine = false; + i = 0; + while (!fine && (i < RESULT_PARTS)) { + fine = (rcode[i] != 0); + i++; + } + + if (!fine) + return tr("No key imported.
Please see the detailed log for more information."); + + QString resultMessage(tr("%1 key processed.", "%1 keys processed.", rcode[0])); + + if (rcode[1]) + resultMessage += tr("
One key without ID.
", "
%1 keys without ID.
", rcode[1]); + if (rcode[2]) + resultMessage += tr("
One key imported:
", "
%1 keys imported:
", rcode[2]); + if (rcode[3]) + resultMessage += tr("
One RSA key imported.
", "
%1 RSA keys imported.
", rcode[3]); + if (rcode[4]) + resultMessage += tr("
One key unchanged.
", "
%1 keys unchanged.
", rcode[4]); + if (rcode[5]) + resultMessage += tr("
One user ID imported.
", "
%1 user IDs imported.
", rcode[5]); + if (rcode[6]) + resultMessage += tr("
One subkey imported.
", "
%1 subkeys imported.
", rcode[6]); + if (rcode[7]) + resultMessage += tr("
One signature imported.
", "
%1 signatures imported.
", rcode[7]); + if (rcode[8]) + resultMessage += tr("
One revocation certificate imported.
", "
%1 revocation certificates imported.
", rcode[8]); + if (rcode[9]) + resultMessage += tr("
One secret key processed.
", "
%1 secret keys processed.
", rcode[9]); + if (rcode[10]) + resultMessage += tr("
One secret key imported.
", "
%1 secret keys imported.
", rcode[10]); + if (rcode[11]) + resultMessage += tr("
One secret key unchanged.
", "
%1 secret keys unchanged.
", rcode[11]); + if (rcode[12]) + resultMessage += tr("
One secret key not imported.
", "
%1 secret keys not imported.
", rcode[12]); + + if (rcode[9]) + resultMessage += tr("
You have imported a secret key.
" + "Please note that imported secret keys are not trusted by default.
" + "To fully use this secret key for signing and encryption, you must edit the key (double click on it) and set its trust to Full or Ultimate.
"); + + return resultMessage; +} + +/*static QString +beautifyKeyList(const QStringList &keyIds, const KGpgItemModel *model) +{ + QString result; + + result.append(QLatin1String("\n")); + if (model == NULL) { + result.append(QLatin1String(" ") + keyIds.join(QLatin1String("\n "))); + } else { + foreach (const QString &changed, keyIds) { + const KGpgKeyNode *node = model->findKeyNode(changed); + QString line; + + if (node == NULL) { + line = changed; + } else { + if (node->getEmail().isEmpty()) + line = trc("ID: Name", "%1: %2", node->getFingerprint(), node->getName()); + else + line = trc("ID: Name ", "%1: %2 <%3>", node->getFingerprint(), node->getName(), node->getEmail()); + } + + result.append(QLatin1String(" ") + line + QLatin1String("\n")); + } + } + + return result; +}*/ + +QString +KGpgImport::getDetailedImportMessage(const QStringList &log, const KGpgItemModel *model) +{ + QString result; + QMap resultcodes; + + foreach (const QString &keyresult, log) { + if (!keyresult.startsWith(QLatin1String("[GNUPG:] IMPORT_OK "))) + continue; + + QStringList rc(keyresult.mid(19).split(QLatin1Char( ' ' ))); + if (rc.count() < 2) { + qDebug() << "unexpected syntax:" << keyresult; + continue; + } + + resultcodes[rc.at(1)] = rc.at(0).toUInt(); + } + + QMap::const_iterator iterend = resultcodes.constEnd(); + + for (unsigned int flag = 1; flag <= 16; flag <<= 1) { + QStringList thischanged; + + for (QMap::const_iterator iter = resultcodes.constBegin(); iter != iterend; ++iter) { + if (iter.value() & flag) + thischanged << iter.key(); + } + + if (thischanged.isEmpty()) + continue; + + switch (flag) { + case 1: + result.append(tr("New Key", "New Keys", thischanged.count())); + break; + case 2: + result.append(tr("Key with new User Id", "Keys with new User Ids", thischanged.count())); + break; + case 4: + result.append(tr("Key with new Signatures", "Keys with new Signatures", thischanged.count())); + break; + case 8: + result.append(tr("Key with new Subkeys", "Keys with new Subkeys", thischanged.count())); + break; + case 16: + result.append(tr("New Private Key", "New Private Keys", thischanged.count())); + break; + default: + Q_ASSERT(flag == 1); + } + +// result.append(beautifyKeyList(thischanged, model)); + result.append(QLatin1String("\n\n")); + } + + QStringList unchanged(resultcodes.keys(0)); + + if (unchanged.isEmpty()) { + // remove empty line at end + result.chop(1); + } else { + result.append(tr("Unchanged Key", "Unchanged Keys", unchanged.count())); +// result.append(beautifyKeyList(unchanged, model)); + result.append(QLatin1String("\n")); + } + + return result; +} + +int +KGpgImport::isKey(const QString &text, const bool incomplete) +{ + int markpos = text.indexOf(QLatin1String("-----BEGIN PGP PUBLIC KEY BLOCK-----")); + if (markpos >= 0) { + markpos = text.indexOf(QLatin1String("-----END PGP PUBLIC KEY BLOCK-----"), markpos); + return ((markpos > 0) || incomplete) ? 1 : 0; + } + + markpos = text.indexOf(QLatin1String("-----BEGIN PGP PRIVATE KEY BLOCK-----")); + if (markpos < 0) + return 0; + + markpos = text.indexOf(QLatin1String("-----END PGP PRIVATE KEY BLOCK-----"), markpos); + if ((markpos < 0) && !incomplete) + return 0; + + return 2; +} + +//#include "kgpgimport.moc" diff --git a/kgpg/transactions/kgpgimport.h b/kgpg/transactions/kgpgimport.h new file mode 100644 index 0000000..7fe6deb --- /dev/null +++ b/kgpg/transactions/kgpgimport.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008,2009,2010 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGIMPORT_H +#define KGPGIMPORT_H + +#include +#include +#include +#include + +#include + +#include "kgpgtextorfiletransaction.h" + +class KGpgItemModel; + +/** + * @brief import one or more keys into the keyring + */ +class KGpgImport: public KGpgTextOrFileTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgImport) +public: + /** + * @brief import given text + * @param parent parent object + * @param text key text to import + */ + explicit KGpgImport(QObject *parent, const QString &text = QString()); + + /** + * @brief import key(s) from file(s) + * @param parent parent object + * @param files list of file locations to import from + */ + KGpgImport(QObject *parent, const QList &files); + + /** + * @brief destructor + */ + virtual ~KGpgImport(); + + /** + * @brief get the names and short fingerprints of the imported keys + * @return list of keys that were imported + */ + QStringList getImportedKeys() const; + + /** + * @brief get the full fingerprints of the imported keys + * @param log transaction log to scan + * @param reason key import reason + * @return list of ids that were imported + * + * You can filter the list of keys returned by the status of that key + * as reported by GnuPG. See doc/DETAILS of GnuPG for the meaning of + * the different flags. + * + * If reason is -1 (the default) all processed key ids are returned. + * If reason is 0 only keys of status 0 (unchanged) are returned. For + * any other value a key is returned if one of his status bits matched + * one of the bits in reason (i.e. (reason & status) != 0). + */ + static QStringList getImportedIds(const QStringList &log, const int reason = -1); + /** + * @brief get the full fingerprints of the imported keys + * + * This is an overloaded member. It calls the static function with the + * result log from this transaction object. + */ + QStringList getImportedIds(const int reason = -1) const; + + /** + * @brief get textual summary of the import events + * @return messages describing what was imported + * + * This is an overloaded member. It calls the static function with the + * result log from this transaction object. + */ + QString getImportMessage() const; + + /** + * @brief get textual summary of the import events + * @param log import log + * @return messages describing what was imported + * + * The log must contain a "IMPORT_RES" line. If this is not present + * the result string will contain an error message. + */ + static QString getImportMessage(const QStringList &log); + + /** + * @brief get detailed summary of import + * @param log import log + * @return message describing which keys changed and how + * + * The log must contain a "IMPORT_RES" line. If this is not present + * the result string will contain an error message. + */ + static QString getDetailedImportMessage(const QStringList &log, const KGpgItemModel *model = NULL); + + /** + * @brief check if the given text contains a private or public key + * @param text text to check + * @param incomplete assume text is only the beginning of the data + * @return if text contains a key or not + * @retval 0 no key found + * @retval 1 public key found + * @retval 2 private key found + */ + static int isKey(const QString &text, const bool incomplete = false); + +protected: + virtual QStringList command() const; +}; + +#endif // KGPGIMPORT_H diff --git a/kgpg/transactions/kgpgsigntext.cpp b/kgpg/transactions/kgpgsigntext.cpp new file mode 100644 index 0000000..c971214 --- /dev/null +++ b/kgpg/transactions/kgpgsigntext.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgsigntext.h" +#include +#include "../gpgproc.h" + +//#include "kgpgsettings.h" + +KGpgSignText::KGpgSignText(QObject *parent, const QString &signId, const QString &text, const SignOptions &options, const QStringList &extraOptions) + : KGpgTextOrFileTransaction(parent, text), + m_fileIndex(-1), + m_options(options), + m_signId(signId), + m_extraOptions(extraOptions), + m_text(text) +{ +} + +KGpgSignText::KGpgSignText(QObject *parent, const QString &signId, const QList &files, const SignOptions &options, const QStringList &extraOptions) + : KGpgTextOrFileTransaction(parent, files), + m_fileIndex(0), + m_options(options), + m_signId(signId), + m_extraOptions(extraOptions) +{ + /* GnuPG can only handle one file at a time when signing */ + Q_ASSERT(files.count() == 1); +} + +KGpgSignText::~KGpgSignText() +{ +} + +QStringList +KGpgSignText::command() const +{ + QStringList ret = m_extraOptions; + + const QList &files = getInputFiles(); + QString fileName; + + if (!files.isEmpty()) + fileName = files.first().path(); + + ret << QLatin1String("-u") << m_signId; + + if (m_options & AsciiArmored) { + if (fileName.isEmpty()) + ret << QLatin1String("--clearsign"); + else + ret << QLatin1String("--armor"); + } + /*if (KGpgSettings::pgpCompatibility()) + ret << QLatin1String("--pgp6");*/ + + if (!fileName.isEmpty()) { + if (m_options & DetachedSignature) + ret << QLatin1String("--detach-sign") << + QLatin1String("--output") << fileName + QLatin1String(".sig"); + + ret << fileName; + } + + // command-fd for pass? + ret << QLatin1String("--command-fd=0"); + + return ret; +} + +QStringList +KGpgSignText::signedText() const +{ + QStringList result; + + foreach (const QString &line, getMessages()) + if (!line.startsWith(QLatin1String("[GNUPG:] "))) { + result.append(line); + } + + return result; +} + +void +KGpgSignText::postStart() +{ + // do nothing, its to early +} + +bool KGpgSignText::nextLine(const QString &line) { + + if (line.startsWith(QLatin1String("[GNUPG:] BEGIN_SIGNING")) &! m_text.isEmpty()) { + GPGProc *proc = getProcess(); + proc->write(m_text.toUtf8()); + proc->closeWriteChannel(); + } else if (!line.startsWith(QLatin1String("[GNUPG:] SIGEXPIRED")) && !line.startsWith(QLatin1String("[GNUPG:] KEYEXPIRED "))) + m_messages.append(line); + + return false; +} + +const QStringList & +KGpgSignText::getMessages() const +{ + return m_messages; +} + +//#include "kgpgsigntext.moc" diff --git a/kgpg/transactions/kgpgsigntext.h b/kgpg/transactions/kgpgsigntext.h new file mode 100644 index 0000000..14459af --- /dev/null +++ b/kgpg/transactions/kgpgsigntext.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGSIGNTEXT_H +#define KGPGSIGNTEXT_H + +#include "kgpgtextorfiletransaction.h" + +#include +#include +#include +#include + +class QProcess; + +/** + * @brief sign the given text or files + */ +class KGpgSignText: public KGpgTextOrFileTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgSignText) + KGpgSignText(); // = delete C++0x +public: + enum SignOption { + DefaultSignature = 0, ///< use whatever GnuPGs defaults are + AsciiArmored = 0x1, ///< output the data as printable ASCII as opposed to binary data + DetachedSignature = 0x2, ///< save the signature in a separate file + }; + Q_DECLARE_FLAGS(SignOptions, SignOption); + + /** + * @brief sign given text + * @param parent parent object + * @param signId the key to use for signing + * @param text text to sign + * @param options signing options + */ + KGpgSignText(QObject *parent, const QString &signId, const QString &text = QString(), const SignOptions &options = AsciiArmored, const QStringList &extraOptions = QStringList()); + + /** + * @brief sign file + * @param parent parent object + * @param signId the key to use for signing + * @param files list of file locations to sign (must only be 1 file) + * @param options signing options + * + * @warning GnuPG can currently handle only one file per invocation for + * signing, so files may only contain one single file. + */ + KGpgSignText(QObject *parent, const QString &signId, const QList &files, const SignOptions &options = DefaultSignature, const QStringList &extraOptions = QStringList()); + + /** + * @brief destructor + */ + virtual ~KGpgSignText(); + + /** + * @brief get signing result + * @return signed text + */ + QStringList signedText() const; + + /** + * @brief get gpg info message + * @return the raw messages from gpg during the operation + */ + const QStringList &getMessages() const; + +protected: + virtual QStringList command() const; + virtual bool nextLine(const QString &line); + +private: + int m_fileIndex; + const SignOptions m_options; + const QString m_signId; + QStringList m_extraOptions; + const QString m_text; + QStringList m_messages; + +private slots: + void postStart(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(KGpgSignText::SignOptions); + +#endif // KGPGSIGNTEXT_H diff --git a/kgpg/transactions/kgpgtextorfiletransaction.cpp b/kgpg/transactions/kgpgtextorfiletransaction.cpp new file mode 100644 index 0000000..036d911 --- /dev/null +++ b/kgpg/transactions/kgpgtextorfiletransaction.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgtextorfiletransaction.h" + +#include "../gpgproc.h" + +//#include +//#include +#include + +KGpgTextOrFileTransaction::KGpgTextOrFileTransaction(QObject *parent, const QString &text, const bool allowChaining) + : KGpgTransaction(parent, allowChaining), + m_text(text) +{ +} + +KGpgTextOrFileTransaction::KGpgTextOrFileTransaction(QObject *parent, const QList &files, const bool allowChaining) + : KGpgTransaction(parent, allowChaining) +{ + setUrls(files); +} + +KGpgTextOrFileTransaction::~KGpgTextOrFileTransaction() +{ + cleanUrls(); +} + +void +KGpgTextOrFileTransaction::setText(const QString &text) +{ + m_text = text; + cleanUrls(); +} + +void +KGpgTextOrFileTransaction::setUrls(const QList &files) +{ + m_text.clear(); + m_inpfiles = files; + qDebug() << "files set:"; + foreach(QUrl file, m_inpfiles) { + qDebug() << file.toString(); + } +} + +bool +KGpgTextOrFileTransaction::preStart() +{ + QStringList locfiles; + + foreach (const QUrl &url, m_inpfiles) { + // qt 4.8 ! todo mac + qDebug() << "what the loc:" << url.isLocalFile(); + + if (url.isLocalFile()) { + locfiles.append(url.toLocalFile()); + } else { + /* QString tmpfile; + //TODO: QIODevice ...? + if (KIO::NetAccess::download(url, tmpfile, 0)) { + m_tempfiles.append(tmpfile); + } else { + m_messages.append(KIO::NetAccess::lastErrorString()); + cleanUrls(); + setSuccess(TS_KIO_FAILED); + return false; + }*/ + } + } + + qDebug() << "m_text: " << m_text; + qDebug() << "hasInputTransaction: " << hasInputTransaction(); + + if (locfiles.isEmpty() && m_tempfiles.isEmpty() && m_text.isEmpty() && !hasInputTransaction()) { + setSuccess(TS_MSG_SEQUENCE); + return false; + } + + QStringList args(QLatin1String("--status-fd=1")); + + args << command(); + // if the input is not stdin set command-fd so GnuPG + // can ask if e.g. the file already exists + if (!locfiles.isEmpty() && !m_tempfiles.isEmpty()) { + args << QLatin1String("--command-fd=0"); + m_closeInput = false; + qDebug() << "if"; + } else { + m_closeInput = !args.contains(QLatin1String("--command-fd=0")); + qDebug() << "else"; + } + if (locfiles.count() + m_tempfiles.count() > 1) + args << QLatin1String("--multifile"); + args << locfiles << m_tempfiles; + addArguments(args); + + return true; +} + +void +KGpgTextOrFileTransaction::postStart() +{ + qDebug() << "post-start! " << m_text; + if (!m_text.isEmpty()){ + GPGProc *proc = getProcess(); + proc->write(m_text.toUtf8()); + if (m_closeInput) + proc->closeWriteChannel(); + } +} + +bool +KGpgTextOrFileTransaction::nextLine(const QString &line) +{ + qDebug() << "nextline called: " << line; + if (!line.startsWith(QLatin1String("[GNUPG:] SIGEXPIRED")) && !line.startsWith(QLatin1String("[GNUPG:] KEYEXPIRED "))) + m_messages.append(line); + + return false; +} + +void +KGpgTextOrFileTransaction::finish() +{ + if (getProcess()->exitCode() != 0) { + setSuccess(TS_MSG_SEQUENCE); + } +} + +const QStringList & +KGpgTextOrFileTransaction::getMessages() const +{ + return m_messages; +} + +void +KGpgTextOrFileTransaction::cleanUrls() +{ +// TODO +/* foreach (const QString &u, m_tempfiles) + KIO::NetAccess::removeTempFile(u); +*/ + m_tempfiles.clear(); + m_locfiles.clear(); + m_inpfiles.clear(); +} + +const QList & +KGpgTextOrFileTransaction::getInputFiles() const +{ + return m_inpfiles; +} + +//#include "kgpgtextorfiletransaction.moc" diff --git a/kgpg/transactions/kgpgtextorfiletransaction.h b/kgpg/transactions/kgpgtextorfiletransaction.h new file mode 100644 index 0000000..46bf190 --- /dev/null +++ b/kgpg/transactions/kgpgtextorfiletransaction.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008,2009,2010 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGTEXTORFILETRANSACTION_H +#define KGPGTEXTORFILETRANSACTION_H + +#include +#include +#include +#include + +#include + +#include "kgpgtransaction.h" + +/** + * @brief feed a text or file through gpg + */ +class KGpgTextOrFileTransaction: public KGpgTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgTextOrFileTransaction) + +public: + /** + * @brief additional status codes for KGpgImport + */ + enum ts_import { + TS_KIO_FAILED = TS_COMMON_END + 1 ///< download of remote file failed + }; + +protected: + /** + * @brief work with given text + * @param parent parent object + * @param text text to work with + */ + explicit KGpgTextOrFileTransaction(QObject *parent = 0, const QString &text = QString(), const bool allowChaining = false); + + /** + * @brief work with given file(s) + * @param parent parent object + * @param keys list of file locations to work with + */ + KGpgTextOrFileTransaction(QObject *parent, const QList &files, const bool allowChaining = false); + +public: + /** + * @brief destructor + */ + virtual ~KGpgTextOrFileTransaction(); + + /** + * @brief set text to work with + * @param text text to work with + */ + void setText(const QString &text); + /** + * @brief set file locations to work with + * @param keys list of file locations to work with + */ + void setUrls(const QList &files); + + /** + * @brief get gpg info message + * @return the raw messages from gpg during the operation + */ + const QStringList &getMessages() const; + +protected: + /** + * @brief construct the command line of the process + */ + virtual bool preStart(); + virtual bool nextLine(const QString &line); + /** + * @brief implement special handling for GnuPG return codes + */ + virtual void finish(); + + virtual QStringList command() const = 0; + + const QList &getInputFiles() const; + +private: + QStringList m_tempfiles; + QStringList m_locfiles; + QList m_inpfiles; + QString m_text; + QStringList m_messages; + bool m_closeInput; ///< if input channel of GnuPG should be closed after m_text is written + + void cleanUrls(); + +private slots: + void postStart(); +}; + +#endif // KGPGTEXTORFILETRANSACTION_H diff --git a/kgpg/transactions/kgpgtransaction.cpp b/kgpg/transactions/kgpgtransaction.cpp new file mode 100644 index 0000000..241252c --- /dev/null +++ b/kgpg/transactions/kgpgtransaction.cpp @@ -0,0 +1,558 @@ +/* + * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgtransaction.h" + +#include "../gpgproc.h" +#include "../kgpginterface.h" + +//#include +#include +//#include +//#include +//#include +#include +#include +#include +#include + + + +KGpgTransactionPrivate::KGpgTransactionPrivate(KGpgTransaction *parent, bool allowChaining) + : QObject(parent), + m_parent(parent), + m_process(new GPGProc()), + m_inputTransaction(NULL), + //m_passwordDialog(NULL), + m_success(KGpgTransaction::TS_OK), + m_tries(3), + m_chainingAllowed(allowChaining), + m_passphraseAction(KGpgTransaction::PA_NONE), + m_inputProcessDone(false), + m_inputProcessResult(KGpgTransaction::TS_OK), + m_ownProcessFinished(false), + m_quitTries(0) +{ +} + +KGpgTransactionPrivate::~KGpgTransactionPrivate() +{ + /*if (m_passwordDialog) { + m_passwordDialog->close(); + m_passwordDialog->deleteLater(); + }*/ + if (m_process->state() == QProcess::Running) { + m_process->closeWriteChannel(); + m_process->terminate(); + } + delete m_inputTransaction; + delete m_process; +} + +KGpgTransaction::KGpgTransaction(QObject *parent, const bool allowChaining) + : QObject(parent), + d(new KGpgTransactionPrivate(this, allowChaining)) +{ + connect(d->m_process, SIGNAL(readReady()), SLOT(slotReadReady())); + connect(d->m_process, SIGNAL(processExited()), SLOT(slotProcessExited())); + connect(d->m_process, SIGNAL(started()), SLOT(slotProcessStarted())); +} + +KGpgTransaction::~KGpgTransaction() +{ + delete d; +} + +void +KGpgTransactionPrivate::slotReadReady() +{ + QString line; + + QWeakPointer process(m_process); + QWeakPointer par(m_parent); + + while (!process.isNull() && (m_process->readln(line, true) >= 0)) { + if (m_quitTries) + m_quitLines << line; +#ifdef KGPG_DEBUG_TRANSACTIONS + qDebug() << m_parent << line; +#endif /* KGPG_DEBUG_TRANSACTIONS */ + //qDebug() << "trans-read: " << m_parent << line; + + + if (line.startsWith(QLatin1String("[GNUPG:] USERID_HINT "))) { + m_parent->addIdHint(line); + } else if (line.startsWith(QLatin1String("[GNUPG:] BAD_PASSPHRASE "))) { + m_success = KGpgTransaction::TS_BAD_PASSPHRASE; + } else if (line.startsWith(QLatin1String("[GNUPG:] GET_HIDDEN passphrase.enter"))) { + // Do not directly assign to the member here, the object could + // get deleted while waiting for the result + const KGpgTransaction::ts_passphrase_actions action = m_parent->passphraseRequested(); + + if (par.isNull()) + return; + + m_passphraseAction = action; + + switch (action) { + case KGpgTransaction::PA_USER_ABORTED: + m_parent->setSuccess(KGpgTransaction::TS_USER_ABORTED); + // sending "quit" here is useless as it would be interpreted as the passphrase + m_process->closeWriteChannel(); + break; + default: + break; + } + } else if ((m_passphraseAction == KGpgTransaction::PA_CLOSE_GOOD) && + line.startsWith(QLatin1String("[GNUPG:] GOOD_PASSPHRASE"))) { + // signal GnuPG that there will be no further input and it can + // begin sending output. + + // except when signing text... + if(QString::fromAscii(m_parent->metaObject()->className()) != "KGpgSignText"){ + m_process->closeWriteChannel(); + } + } else if (line.startsWith(QLatin1String("[GNUPG:] GET_BOOL "))) { + switch (m_parent->boolQuestion(line.mid(18))) { + case KGpgTransaction::BA_YES: + write("YES\n"); + break; + case KGpgTransaction::BA_NO: + write("NO\n"); + break; + case KGpgTransaction::BA_UNKNOWN: + m_parent->setSuccess(KGpgTransaction::TS_MSG_SEQUENCE); + m_parent->unexpectedLine(line); + sendQuit(); + } + } else if (line.startsWith(QLatin1String("[GNUPG:] CARDCTRL "))) { + // just ignore them, pinentry should handle that + } else if (m_parent->nextLine(line)) { + sendQuit(); + } + } +} + +void +KGpgTransactionPrivate::slotProcessExited() +{ + Q_ASSERT(m_parent->sender() == m_process); + m_ownProcessFinished = true; + + if (m_inputProcessDone) + processDone(); +} + +void +KGpgTransactionPrivate::slotProcessStarted() +{ + m_parent->postStart(); +} + +void +KGpgTransactionPrivate::sendQuit(void) +{ + write("quit\n"); + +#ifdef KGPG_DEBUG_TRANSACTIONS + if (m_quitTries == 0) + qDebug() << "sending quit"; +#endif /* KGPG_DEBUG_TRANSACTIONS */ + + if (m_quitTries++ >= 3) { + qDebug() << "tried" << m_quitTries << "times to quit the GnuPG session"; + qDebug() << "last input was" << m_quitLines; + qDebug() << "please file a bug report at https://bugs.kde.org"; + m_process->closeWriteChannel(); + m_success = KGpgTransaction::TS_MSG_SEQUENCE; + } +} + +void +KGpgTransactionPrivate::slotInputTransactionDone(int result) +{ + Q_ASSERT(m_parent->sender() == m_inputTransaction); + + m_inputProcessDone = true; + m_inputProcessResult = result; + + if (m_ownProcessFinished) + processDone(); +} + +void +KGpgTransactionPrivate::slotPasswordEntered(const QString &password) +{ + sender()->deleteLater(); + //m_passwordDialog = NULL; + m_process->write(password.toUtf8() + '\n'); + m_parent->newPasswordEntered(); +} + +void +KGpgTransactionPrivate::slotPasswordAborted() +{ + sender()->deleteLater(); + //m_passwordDialog = NULL; + m_process->closeWriteChannel(); + m_success = KGpgTransaction::TS_USER_ABORTED; +} + +void +KGpgTransactionPrivate::write(const QByteArray &a) +{ + m_process->write(a); +#ifdef KGPG_DEBUG_TRANSACTIONS + qDebug() << m_parent << a; +#endif /* KGPG_DEBUG_TRANSACTIONS */ + qDebug() << "trans-write: " << m_parent << a; +} + +void +KGpgTransactionPrivate::processDone() +{ + m_parent->finish(); + emit m_parent->infoProgress(100, 100); + emit m_parent->done(m_success); +} + +void +KGpgTransaction::start() +{ + d->m_inputProcessResult = false; + d->m_inputProcessDone = (d->m_inputTransaction == NULL); + + setSuccess(TS_OK); + d->m_idhints.clear(); + d->m_tries = 3; + if (preStart()) { + d->m_ownProcessFinished = false; + if (d->m_inputTransaction != NULL) + d->m_inputTransaction->start(); +#ifdef KGPG_DEBUG_TRANSACTIONS + kDebug(2100) << this << d->m_process->program(); +#endif /* KGPG_DEBUG_TRANSACTIONS */ + d->m_process->start(); + emit infoProgress(0, 1); + } else { + emit done(d->m_success); + } +} + +void +KGpgTransaction::write(const QByteArray &a, const bool lf) +{ + if (lf) + d->write(a + '\n'); + else + d->write(a); +} + +void +KGpgTransaction::write(const int i) +{ + write(QByteArray::number(i)); +} + +void +KGpgTransaction::askNewPassphrase(const QString& text) +{ + qDebug() << "KGpgTransaction::askNewPassphrase called"; + + emit statusMessage(tr("Requesting Passphrase")); + + /*d->m_passwordDialog = new KNewPasswordDialog(qobject_cast(parent())); + d->m_passwordDialog->setPrompt(text); + d->m_passwordDialog->setAllowEmptyPasswords(false); + connect(d->m_passwordDialog, SIGNAL(newPassword(QString)), SLOT(slotPasswordEntered(QString))); + connect(d->m_passwordDialog, SIGNAL(rejected()), SLOT(slotPasswordAborted())); + connect(d->m_process, SIGNAL(processExited()), d->m_passwordDialog->button(KDialog::Cancel), SLOT(clicked())); + d->m_passwordDialog->show();*/ + + +} + +int +KGpgTransaction::getSuccess() const +{ + return d->m_success; +} + +void +KGpgTransaction::setSuccess(const int v) +{ +#ifdef KGPG_DEBUG_TRANSACTIONS + qDebug() << d->m_success << v; +#endif /* KGPG_DEBUG_TRANSACTIONS */ + d->m_success = v; +} + +KGpgTransaction::ts_boolanswer +KGpgTransaction::boolQuestion(const QString& line) +{ + Q_UNUSED(line); + + return BA_UNKNOWN; +} + +void +KGpgTransaction::finish() +{ +} + +void +KGpgTransaction::setDescription(const QString &description) +{ + d->m_description = description; +} + +void +KGpgTransaction::waitForInputTransaction() +{ + Q_ASSERT(d->m_inputTransaction != NULL); + + if (d->m_inputProcessDone) + return; + + d->m_inputTransaction->waitForFinished(); +} + +void +KGpgTransaction::unexpectedLine(const QString &line) +{ + qDebug() << this << "unexpected input line" << line << "for command" << d->m_process->program(); +} + +KGpgTransaction::ts_passphrase_actions +KGpgTransaction::passphraseRequested() +{ + qDebug() << "KGpgTransaction::passphraseRequested called"; + if (!askPassphrase()) + return PA_USER_ABORTED; + else + return PA_CLOSE_GOOD; +} + +bool +KGpgTransaction::preStart() +{ + return true; +} + +void +KGpgTransaction::postStart() +{ +} + +void +KGpgTransaction::addIdHint(QString txt) +{ + int cut = txt.indexOf(QLatin1Char( ' ' ), 22, Qt::CaseInsensitive); + txt.remove(0, cut); + + if (txt.contains(QLatin1Char( '(' ), Qt::CaseInsensitive)) + txt = txt.section(QLatin1Char( '(' ), 0, 0) + txt.section(QLatin1Char( ')' ), -1); + + txt.replace(QLatin1Char( '<' ), QLatin1String( "<" )); + + if (!d->m_idhints.contains(txt)) + d->m_idhints << txt; +} + +QString +KGpgTransaction::getIdHints() const +{ + return d->m_idhints.join( tr(" or " )); +} + +GPGProc * +KGpgTransaction::getProcess() +{ + return d->m_process; +} + +int +KGpgTransaction::addArgument(const QString &arg) +{ + int r = d->m_process->program().count(); + + *d->m_process << arg; + + return r; +} + +int +KGpgTransaction::addArguments(const QStringList &args) +{ + int r = d->m_process->program().count(); + + *d->m_process << args; + + return r; +} + +void +KGpgTransaction::replaceArgument(const int pos, const QString &arg) +{ + QStringList args(d->m_process->program()); + d->m_process->clearProgram(); + + args.replace(pos, arg); + + d->m_process->setProgram(args); +} + +void +KGpgTransaction::insertArgument(const int pos, const QString &arg) +{ + insertArguments(pos, QStringList(arg)); +} + +void +KGpgTransaction::insertArguments(const int pos, const QStringList &args) +{ + QStringList tmp(d->m_process->program()); + + int tmppos = pos; + foreach (const QString &s, args) { + tmp.insert(tmppos++, s); + } + d->m_process->setProgram(tmp); + + int move = args.count(); + foreach (int *ref, d->m_argRefs) { + if (*ref >= pos) + *ref += move; + } +} + +void +KGpgTransaction::addArgumentRef(int *ref) +{ + d->m_argRefs.append(ref); +} + +bool +KGpgTransaction::askPassphrase(const QString &message) +{ + qDebug() << "KGpgTransaction::askPassphrase called"; + + if (d->m_passphraseAction == PA_USER_ABORTED) + return false; + + QString passdlgmessage; + QString userIDs(getIdHints()); + if (userIDs.isEmpty()) + userIDs = tr("[No user id found]"); + else + userIDs.replace(QLatin1Char( '<' ), QLatin1String( "<" )); + + if (d->m_tries < 3) + passdlgmessage = tr("

Bad passphrase. You have 1 try left.

", "

Bad passphrase. You have %1 tries left.

", d->m_tries); + if (message.isEmpty()) { + passdlgmessage += tr("Enter passphrase for %1").arg(userIDs); + } else { + passdlgmessage += message; + } + + --d->m_tries; + + emit statusMessage(tr("Requesting Passphrase")); + return (KgpgInterface::sendPassphrase(passdlgmessage, d->m_process, qobject_cast(parent())) == 0); +} + +void +KGpgTransaction::setGnuPGHome(const QString &home) +{ + QStringList tmp(d->m_process->program()); + + Q_ASSERT(tmp.count() > 3); + int homepos = tmp.indexOf(QLatin1String("--options"), 1); + if (homepos == -1) + homepos = tmp.indexOf(QLatin1String("--homedir"), 1); + Q_ASSERT(homepos != -1); + Q_ASSERT(homepos + 1 < tmp.count()); + + tmp[homepos] = QLatin1String("--homedir"); + tmp[homepos + 1] = home; + + d->m_process->setProgram(tmp); +} + +int +KGpgTransaction::waitForFinished(const int msecs) +{ + int ret = TS_OK; + + if (d->m_inputTransaction != NULL) { + int ret = d->m_inputTransaction->waitForFinished(msecs); + if ((ret != TS_OK) && (msecs != -1)) + return ret; + } + + bool b = d->m_process->waitForFinished(msecs); + + if (ret != TS_OK) + return ret; + + if (!b) + return TS_USER_ABORTED; + else + return getSuccess(); +} + +const QString & +KGpgTransaction::getDescription() const +{ + return d->m_description; +} + +void +KGpgTransaction::setInputTransaction(KGpgTransaction *ta) +{ + Q_ASSERT(d->m_chainingAllowed); + + if (d->m_inputTransaction != NULL) + clearInputTransaction(); + d->m_inputTransaction = ta; + + GPGProc *proc = ta->getProcess(); + proc->setStandardOutputProcess(d->m_process); + connect(ta, SIGNAL(done(int)), SLOT(slotInputTransactionDone(int))); +} + +void +KGpgTransaction::clearInputTransaction() +{ + disconnect(d->m_inputTransaction, SIGNAL(done(int)), this, SLOT(slotInputTransactionDone(int))); + d->m_inputTransaction = NULL; +} + +bool +KGpgTransaction::hasInputTransaction() const +{ + return (d->m_inputTransaction != NULL); +} + +void +KGpgTransaction::kill() +{ + d->m_process->kill(); +} + +void +KGpgTransaction::newPasswordEntered() +{ +} + +//#include "moc_kgpgtransaction.cpp" diff --git a/kgpg/transactions/kgpgtransaction.h b/kgpg/transactions/kgpgtransaction.h new file mode 100644 index 0000000..8fc76a5 --- /dev/null +++ b/kgpg/transactions/kgpgtransaction.h @@ -0,0 +1,465 @@ +/* + * Copyright (C) 2008,2009 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGTRANSACTION_H +#define KGPGTRANSACTION_H + +#include +#include +#include + +class GPGProc; +class KGpgSignTransactionHelper; +class KGpgTransactionPrivate; +class QByteArray; +class QProcess; + +/** + * @brief Process one GnuPG operation + * + * This class encapsulates one GnuPG operation. It will care for all + * interaction with the gpg process. Everything you have to care about + * is to set up the object properly, call start() and catch the done signal. + * + * This is an abstract base class for specific operations that implements + * the basic I/O loop, the process setup and interaction and some convenience + * members to set extra arguments for the process. + * + * If you want to add a new operation create a child class that implements + * nextLine(). Ususally you also need a constructor that takes some information + * like the id of the key to modify. + * + * @author Rolf Eike Beer + */ +class KGpgTransaction: public QObject { + Q_OBJECT + + friend class KGpgTransactionPrivate; + friend class KGpgSignTransactionHelper; + + Q_DISABLE_COPY(KGpgTransaction) + +public: + /** + * @brief return codes common to many transactions + * + * Every transaction may define additional return codes, which + * should start at TS_COMMON_END + 1. + */ + enum ts_transaction { + TS_OK = 0, ///< everything went fine + TS_BAD_PASSPHRASE = 1, ///< the passphrase was not correct + TS_MSG_SEQUENCE = 2, ///< unexpected sequence of GnuPG messages + TS_USER_ABORTED = 3, ///< the user aborted the transaction + TS_INVALID_EMAIL = 4, ///< the given email address is invalid + TS_INPUT_PROCESS_ERROR = 5, ///< the connected input process returned an error + TS_COMMON_END = 100 ///< placeholder for return values of derived classes + }; + /** + * @brief result codes for GnuPG boolean questions + * + * These are the possible answers to a boolean question of a GnuPG process. + */ + enum ts_boolanswer { + BA_UNKNOWN = 0, ///< the question is not supported (this is an error) + BA_YES = 1, ///< answer "YES" + BA_NO = 2 ///< answer "NO" + }; + /** + * @brief actions to do after a passphrase was sent to GnuPG + */ + enum ts_passphrase_actions { + PA_NONE = 0, ///< do nothing special + PA_CLOSE_GOOD = 1, ///< close command channel if passphrase was accepted + PA_USER_ABORTED = 2 ///< the user has cancelled the dialog, abort the transaction + }; + + /** + * @brief KGpgTransaction constructor + */ + explicit KGpgTransaction(QObject *parent = 0, const bool allowChaining = false); + /** + * @brief KGpgTransaction destructor + */ + virtual ~KGpgTransaction(); + + /** + * @brief Start the operation. + */ + void start(); + + /** + * @brief sets the home directory of GnuPG called for this transaction + */ + void setGnuPGHome(const QString &home); + + /** + * @brief blocks until the transaction is complete + * @return the result of the transaction like done() would + * @retval TS_USER_ABORTED the timeout expired + * + * If this transaction has another transaction set as input then + * it would wait for those transaction to finish first. The msecs + * argument is used as limit for both transactions then so you + * can end up waiting twice the given time (or longer if you have + * more transactions chained). + */ + int waitForFinished(const int msecs = -1); + + /** + * @brief return description of this transaction + * @return string used to describe what's going on + * + * This is especially useful when using this transaction from a KJob. + */ + const QString &getDescription() const; + + /** + * @brief connect the standard input of this transaction to another process + * @param proc process to read data from + * + * Once the input process is connected this transaction will not emit + * the done signal until the input process sends the done signal. + * + * The basic idea is that when an input transaction is set you only need + * to care about this transaction. The other transaction is automatically + * started when this one is started and is destroyed when this one is. + */ + void setInputTransaction(KGpgTransaction *ta); + + /** + * @brief tell the process the standard input is no longer connected + * + * If you had connected an input process you need to tell the transaction + * once this input process is gone. Otherwise you will not get a done + * signal from this transaction as it will wait for the finished signal + * from the process that will never come. + */ + void clearInputTransaction(); + + /** + * @brief check if another transaction will sent input to this + */ + bool hasInputTransaction() const; + + /** + * @brief abort this operation as soon as possible + */ + void kill(); + +signals: + /** + * @brief Emitted when the operation was completed. + * @param result return status of the transaction + * + * @see ts_transaction for the common status codes. Each transaction + * may define additional status codes. + */ + void done(int result); + + /** + * @brief emits textual status information + * @param msg the status message + */ + void statusMessage(const QString &msg); + + /** + * @brief emits procentual status information + * @param processedAmount how much of the job is done + * @param totalAmount how much needs to be done to complete this job + */ + void infoProgress(qulonglong processedAmount, qulonglong totalAmount); + +protected: + /** + * @brief Called before the gpg process is started. + * @return true if the process should be started + * + * You may reimplement this member if you need to do some special + * operations before the process is started. The command line of the + * process may be modified for the last time here. + * + * When you notice that some values passed are invalid or the + * transaction does not need to be run for some other reason you should + * call setSuccess() to set the return value and return false. In this + * case the process is not started but the value is immediately + * returned. + */ + virtual bool preStart(); + /** + * @brief Called when the gpg process is up and running. + * + * This functions is connected to the started() signal of the gpg process. + */ + virtual void postStart(); + /** + * @brief Called for every line the gpg process writes. + * @param line the input from the process + * @return true if "quit" should be sent to process + * + * You need to implement this member to get a usable subclass. + * + * When this function returns true "quit" is written to the process. + */ + virtual bool nextLine(const QString &line) = 0; + /** + * @brief Called for every boolean question GnuPG answers + * @param line the question GnuPG asked + * @return what to answer GnuPG + * + * This is called instead of nextLine() if the line contains a boolean + * question. Returning BA_UNKNOWN will cancel the current transaction + * and will set the transaction result to TS_MSG_SEQUENCE. + * + * The default implementation will answer BA_UNKNOWN to every question. + */ + virtual ts_boolanswer boolQuestion(const QString &line); + /** + * @brief Called when the gpg process finishes. + * + * You may reimplement this member if you need to do some special + * operations after process completion. The provided one simply + * does nothing which should be enough for most cases. + */ + virtual void finish(); + /** + * @brief called when the user entered a new password + * + * This is called after askNewPassphrase() was called, the user has + * entered a new password and it was sent to the GnuPG process. + * + * The default implementation does nothing. + */ + virtual void newPasswordEntered(); + /** + * @brief set the description returned in getDescription() + * @param description the new description of this transaction + */ + void setDescription(const QString &description); + + /** + * @brief wait until the input transaction has finished + */ + void waitForInputTransaction(); + + /** + * @brief notify of an unexpected line + * + * This will print out the line to the console to ease debugging. + */ + void unexpectedLine(const QString &line); + + /** + * @brief called when GnuPG asks for a passphrase + * @return true if "quit" should be sent to process + * + * This allows a transaction to implement special handling for + * passphrases, e.g. when both old and new passphrase must be + * requested when changing it. The default implementation will just + * call askPassphrase(). + */ + virtual ts_passphrase_actions passphraseRequested(); + +private: + KGpgTransactionPrivate* const d; + + Q_PRIVATE_SLOT(d, void slotReadReady()) + Q_PRIVATE_SLOT(d, void slotProcessExited()) + Q_PRIVATE_SLOT(d, void slotProcessStarted()) + Q_PRIVATE_SLOT(d, void slotInputTransactionDone(int)) + Q_PRIVATE_SLOT(d, void slotPasswordEntered(const QString &)) + Q_PRIVATE_SLOT(d, void slotPasswordAborted()) + +protected: + /** + * @brief Ask user for passphrase and send it to gpg process. + * + * If the gpg process asks for a new passphrase this function will do + * all necessary steps for you: ask the user for the password and write + * it to the gpg process. If the password is wrong the user is prompted + * again for the correct password. If the user aborts the password + * entry the gpg process will be killed and the transaction result will + * be set to TS_USER_ABORTED. + * + * In contrast to sendPassphrase() this function will not block, but + * handle everything using signals and slots. + * + * @see KgpgInterface::sendPassphrase + * @see askPassphrase + */ + void askNewPassphrase(const QString &text); + + /** + * @brief get the success value that will be returned with the done signal + */ + int getSuccess() const; + /** + * @brief set the success value that will be returned with the done signal + * @param v the new success value + * + * You should use 0 as success value. Other values can be defined as needed. + */ + void setSuccess(const int v); + + /** + * @brief add a userid hint + * @param txt userid description + * + * Before GnuPG asks for a passphrase it usually sends out a hint message + * for which key the passphrase will be needed. There may be several hint + * messages, e.g. if a text was encrypted with multiple keys. + */ + void addIdHint(QString txt); + /** + * @brief get string of all userid hints + * @returns concatenation of all ids previously added with addIdHint(). + */ + QString getIdHints() const; + + /** + * @brief get a reference to the gpg process object + * @returns gpg process object + * + * This returns a reference to the gpg process object used internally. + * In case you need to do some special things (e.g. changing the output + * mode) you can modify this object. + * + * Usually you will not need this. + * + * @warning Never free this object! + */ + GPGProc *getProcess(); + /** + * @brief add a command line argument to gpg process + * @param arg new argument + * @returns the position of the new argument + * + * This is a convenience function that allows adding one additional + * argument to the command line of the process. This must be called + * before start() is called. Usually you will call this from your + * constructor. + */ + int addArgument(const QString &arg); + /** + * @brief add command line arguments to gpg process + * @param args new arguments + * @returns the position of the first argument added + * + * This is a convenience function that allows adding additional + * arguments to the command line of the process. This must be called + * before start() is called. + */ + int addArguments(const QStringList &args); + /** + * @brief replace the argument at the given position + * @param pos position of old argument + * @param arg new argument + */ + void replaceArgument(const int pos, const QString &arg); + /** + * @brief insert an argument at the given position + * @param pos position to insert at + * @param arg new argument + */ + void insertArgument(const int pos, const QString &arg); + /** + * @brief insert arguments at the given position + * @param pos position to insert at + * @param args new arguments + */ + void insertArguments(const int pos, const QStringList &args); + /** + * @brief make sure the reference to a specific argument is kept up to date + * @param ref the value where the position is stored + * + * You might want to keep the position of a specific argument to + * later be able to repace it easily. In that case put it into + * this function too so every time someone mofifies the argument + * list (especially by insertArgument() and insertArguments()) + * this reference will be kept up to date. + */ + void addArgumentRef(int *ref); + /** + * @brief write data to standard input of gpg process + * @param a data to write + * @param lf if line feed should be appended to message + * + * Use this function to interact with the gpg process. A carriage + * return is appended to the data automatically. Usually you will + * call this function from nextLine(). + */ + void write(const QByteArray &a, const bool lf = true); + /** + * @brief write data to standard input of gpg process + * @param i data to write + * + * @overload + */ + void write(const int i); + /** + * @brief ask user for password + * @param message message to display to the user. If message is empty + * "Enter password for [UID]" will be used. + * @return true if the authorization was successful + * + * This function handles user authorization for key changes. It will + * take care to display the message asking the user for the password + * and the number of tries left. + */ + bool askPassphrase(const QString &message = QString()); +}; + +class KGpgTransactionPrivate: QObject { +public: + KGpgTransactionPrivate(KGpgTransaction *parent, bool allowChaining); + ~KGpgTransactionPrivate(); + + KGpgTransaction *m_parent; + GPGProc *m_process; + KGpgTransaction *m_inputTransaction; + //KNewPasswordDialog *m_passwordDialog; + int m_success; + int m_tries; + QString m_description; + bool m_chainingAllowed; + KGpgTransaction::ts_passphrase_actions m_passphraseAction; ///< ignore further request for passphrase + + QStringList m_idhints; + + void slotReadReady(); + void slotProcessExited(); + void slotProcessStarted(); + void slotInputTransactionDone(int result); + void slotPasswordEntered(const QString &password); + void slotPasswordAborted(); + + QList m_argRefs; + bool m_inputProcessDone; + int m_inputProcessResult; + bool m_ownProcessFinished; + + /** + * terminate GnuPG session + */ + void sendQuit(void); + + void write(const QByteArray &a); + +private: + void processDone(); + + unsigned int m_quitTries; ///< how many times we tried to quit + QStringList m_quitLines; ///< what we received after we tried to quit +}; + +#endif // KGPGTRANSACTION_H diff --git a/kgpg/transactions/kgpgverify.cpp b/kgpg/transactions/kgpgverify.cpp new file mode 100644 index 0000000..e9dbb36 --- /dev/null +++ b/kgpg/transactions/kgpgverify.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgpgverify.h" + +#include "../gpgproc.h" +#include "../core/KGpgKeyNode.h" +//#include "../model/kgpgitemmodel.h" + +//#include +//#include + +KGpgVerify::KGpgVerify(QObject *parent, const QString &text) + : KGpgTextOrFileTransaction(parent, text), + m_fileIndex(-1) +{ +} + +KGpgVerify::KGpgVerify(QObject *parent, const QList &files) + : KGpgTextOrFileTransaction(parent, files), + m_fileIndex(0) +{ +} + +KGpgVerify::~KGpgVerify() +{ +} + +QStringList +KGpgVerify::command() const +{ + QStringList ret(QLatin1String("--verify")); + + return ret; +} + +bool +KGpgVerify::nextLine(const QString &line) +{ + if (line.startsWith(QLatin1String("[GNUPG:] NO_PUBKEY "))) { + setSuccess(TS_MISSING_KEY); + m_missingId = line.mid(19).simplified(); + return false; + } + + if (line.startsWith(QLatin1String("[GNUPG:] ")) && + line.contains(QLatin1String("SIG"))) { + if (line.startsWith(QLatin1String("[GNUPG:] BADSIG"))) + setSuccess(KGpgVerify::TS_BAD_SIGNATURE); + else + setSuccess(KGpgTransaction::TS_OK); + } + + return KGpgTextOrFileTransaction::nextLine(line); +} + +void +KGpgVerify::finish() +{ + // GnuPG will return error code 2 if it wasn't able to verify the file. + // If it complained about a missing signature before that is fine. + if (((getProcess()->exitCode() == 2) && (getSuccess() == TS_MISSING_KEY)) || + ((getProcess()->exitCode() == 1) && (getSuccess() == TS_BAD_SIGNATURE))) + return; + + KGpgTextOrFileTransaction::finish(); +} + +static QString +sigTimeMessage(const QString &sigtime) +{ + QDateTime stamp; + if (sigtime.contains(QLatin1Char('T'))) { + stamp = QDateTime::fromString(sigtime, Qt::ISODate); + } else { + bool ok; + qint64 secs = sigtime.toLongLong(&ok); + if (ok) + stamp = QDateTime::fromMSecsSinceEpoch(secs * 1000); + } + + if (!stamp.isValid()) + return QString(); + +/* return tr("first argument is formatted date, second argument is formatted time", + "The signature was created at %1 %2", + KGlobal::locale()->formatDate(stamp.date(), KLocale::LongDate), + KGlobal::locale()->formatTime(stamp.time(), KLocale::LongDate)) + + QLatin1String("
");*/ + return "todo"; +} + +/* +QString +KGpgVerify::getReport(const QStringList &log, const KGpgItemModel *model) +{ + QString result; + // newer versions of GnuPG emit both VALIDSIG and GOODSIG + // for a good signature. Since VALIDSIG has more information + // we use that. + const QRegExp validsig(QLatin1String("^\\[GNUPG:\\] VALIDSIG([ ]+[^ ]+){10,}.*$")); + const bool useGoodSig = (model != NULL) && (log.indexOf(validsig) == -1); + QString sigtime; // timestamp of signature creation + + foreach (const QString &line, log) { + if (!line.startsWith(QLatin1String("[GNUPG:] "))) + continue; + + const QString msg = line.mid(9); + + if (msg.startsWith(QLatin1String("VALIDSIG ")) && !useGoodSig) { + // from GnuPG source, doc/DETAILS: + // VALIDSIG + // + // + const QStringList vsig = msg.mid(9).split(QLatin1Char(' '), QString::SkipEmptyParts); + Q_ASSERT(vsig.count() >= 10); + + const KGpgKeyNode *node = model->findKeyNode(vsig[9]); + + if (node != NULL) { + // ignore for now if this is signed with the primary id (vsig[0] == vsig[9]) or not + if (node->getEmail().isEmpty()) + result += tr("Good signature from:
%1
Key ID: %2
") + .arg(node->getName()).arg(vsig[9]); + else + result += tr("Good signature from: NAME , Key ID: HEXID", + "Good signature from:
%1 <%2>
Key ID: %3
") + .arg(node->getName()).arg(node->getEmail()).arg(vsig[9]); + + result += sigTimeMessage(vsig[2]); + } else { + // this should normally never happen, but one could delete + // the key just after the verification. Brute force solution: + // do the whole report generation again, but this time make + // sure GOODSIG is used. + return getReport(log, NULL); + } + } else if (msg.startsWith(QLatin1String("UNEXPECTED")) || + msg.startsWith(QLatin1String("NODATA"))) { + result += tr("No signature found.") + QLatin1Char('\n'); + } else if (useGoodSig && msg.startsWith(QLatin1String("GOODSIG "))) { + int sigpos = msg.indexOf( ' ' , 8); + const QString keyid = msg.mid(8, sigpos - 8); + + // split the name/email pair to give translators more power to handle this + QString email; + QString name = msg.mid(sigpos + 1); + + int oPos = name.indexOf(QLatin1Char('<')); + int cPos = name.indexOf(QLatin1Char('>')); + if ((oPos >= 0) && (cPos >= 0)) { + email = name.mid(oPos + 1, cPos - oPos - 1); + name = name.left(oPos).simplified(); + } + + if (email.isEmpty()) + result += tr("Good signature from:
%1
Key ID: %2
") + .arg(name).arg(keyid); + else + result += tr("Good signature from: NAME , Key ID: HEXID", + "Good signature from:
%1 <%2>
Key ID: %3
") + .arg(name).arg(email).arg(keyid); + if (!sigtime.isEmpty()) { + result += sigTimeMessage(sigtime); + sigtime.clear(); + } + } else if (msg.startsWith(QLatin1String("SIG_ID "))) { + const QStringList parts = msg.simplified().split(QLatin1Char(' ')); + if (parts.count() > 2) + sigtime = parts[2]; + } else if (msg.startsWith(QLatin1String("BADSIG"))) { + int sigpos = msg.indexOf( ' ', 7); + result += tr("BAD signature from:
%1
Key id: %2

The file is corrupted
") + .arg(msg.mid(sigpos + 1).replace(QLatin1Char('<'), QLatin1String("<"))) + .arg(msg.mid(7, sigpos - 7)); + } else if (msg.startsWith(QLatin1String("TRUST_UNDEFINED"))) { + result += tr("The signature is valid, but the key is untrusted
"); + } else if (msg.startsWith(QLatin1String("TRUST_ULTIMATE"))) { + result += tr("The signature is valid, and the key is ultimately trusted
"); + } + } + + return result; +} +*/ + +QString +KGpgVerify::missingId() const +{ + return m_missingId; +} + +//#include "kgpgverify.moc" diff --git a/kgpg/transactions/kgpgverify.h b/kgpg/transactions/kgpgverify.h new file mode 100644 index 0000000..beba12f --- /dev/null +++ b/kgpg/transactions/kgpgverify.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012 Rolf Eike Beer + */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGVERIFY_H +#define KGPGVERIFY_H + +#include "kgpgtextorfiletransaction.h" + +#include +#include +#include + +#include + +//class KGpgItemModel; +class QProcess; + +/** + * @brief verify the signature of the given text or files + */ +class KGpgVerify: public KGpgTextOrFileTransaction { + Q_OBJECT + + Q_DISABLE_COPY(KGpgVerify) + KGpgVerify(); // = delete C++0x +public: + enum ts_verify { + TS_MISSING_KEY = KGpgTransaction::TS_COMMON_END + 1, ///< signing key not in keyring + TS_BAD_SIGNATURE = TS_MISSING_KEY + 1 ///< the file is signed, but the signature is invalid + }; + + /** + * @brief verify signature of given text + * @param parent parent object + * @param text text to verify + */ + explicit KGpgVerify(QObject *parent, const QString &text = QString()); + + /** + * @brief verify signatures of file(s) + * @param parent parent object + * @param files list of file locations to verify + */ + KGpgVerify(QObject *parent, const QList &files); + + /** + * @brief destructor + */ + virtual ~KGpgVerify(); + + /** + * @brief get verification report + * @param log the log lines to scan + * @param model key model to use for key lookups + * @return verification report of GnuPG + */ + //static QString getReport(const QStringList &log, const KGpgItemModel *model = NULL); + + /** + * @brief get the missing key id + * @return key id that signed the message + * + * This is only valid if the transaction returned with result + * TS_MISSING_KEY. + */ + QString missingId() const; + +protected: + virtual QStringList command() const; + virtual bool nextLine(const QString &line); + virtual void finish(); + +private: + int m_fileIndex; + QString m_currentFile; + QStringList m_report; + QString m_missingId; +}; + +#endif // KGPGVERIFY_H diff --git a/main.cpp b/main.cpp index 19f29cd..5afa441 100644 --- a/main.cpp +++ b/main.cpp @@ -56,8 +56,8 @@ int main(int argc, char *argv[]) putenv(QString("GNUPGHOME=" + appPath + "/keydb").toAscii().data()); // this may help with newer gpgme versions on windows - //putenv(QString("GPGME_GPGPATH=" + appPath.replace("/", "\\") + "\\bin\\gpg.exe").toAscii().data()); - + putenv(QString("GPGME_GPGPATH=" + appPath + "/gpg-mac").toAscii().data()); + qDebug() << appPath + "/gpg-mac"; // QSettings uses org-name for automatically setting path... app.setOrganizationName("conf"); diff --git a/mainwindow.cpp b/mainwindow.cpp index 2064b48..dd5b306 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -23,6 +23,7 @@ MainWindow::MainWindow() { + qDebug() << "hallo"; mCtx = new GpgME::GpgContext(); /* get path were app was started */ @@ -731,7 +732,78 @@ void MainWindow::importKeyFromEdit() return; } - keyMgmt->importKeys(edit->curTextPage()->toPlainText().toAscii()); + //keyMgmt->importKeys(edit->curTextPage()->toPlainText().toAscii()); + QString text = edit->curTextPage()->toPlainText(); + + if (text.isEmpty()) + return; + + KGpgImport *imp; + + if (!KGpgImport::isKey(text) && KGpgDecrypt::isEncryptedText(text)) { + /*if (KMessageBox::questionYesNo(this, + i18n("The text in the clipboard does not look like a key, but like encrypted text.
Do you want to decrypt it first and then try importing it?
"), + i18n("Import from Clipboard")) != KMessageBox::Yes) + return;*/ + + imp = new KGpgImport(this); + KGpgDecrypt *decr = new KGpgDecrypt(this, text); + imp->setInputTransaction(decr); + } else { + imp = new KGpgImport(this, text); + } + + startImport(imp); +} + +void MainWindow::startImport(KGpgImport *import) +{ + qDebug() << "start import"; + changeMessage(tr("Importing..."), true); + connect(import, SIGNAL(done(int)), SLOT(slotImportDone(int))); + import->start(); +} + +void MainWindow::slotImportDone(int result) +{ + KGpgImport *import = qobject_cast(sender()); + + Q_ASSERT(import != NULL); + const QStringList rawmsgs(import->getMessages()); + + if (result != 0) { + /*KMessageBox::detailedSorry(this, i18n("Key importing failed. Please see the detailed log for more information."), + rawmsgs.join( QLatin1String( "\n")) , i18n("Key Import" ));*/ + qDebug() << "Key importing failed. Please see the detailed log for more information." << rawmsgs.join( QLatin1String( "\n")); + } + + QStringList keys(import->getImportedIds(0x1f)); + const bool needsRefresh = !keys.isEmpty(); + keys << import->getImportedIds(0); +/* + if (!keys.isEmpty()) { + const QString msg(import->getImportMessage()); + const QStringList keynames(import->getImportedKeys()); + + new KgpgDetailedInfo(this, msg, rawmsgs.join( QLatin1String( "\n") ), keynames, i18n("Key Import" )); + if (needsRefresh) + imodel->refreshKeys(keys); + else + changeMessage(i18nc("Application ready for user input", "Ready")); + } else{ + changeMessage(i18nc("Application ready for user input", "Ready")); + } +*/ + changeMessage(tr("Application ready for user input", "Ready")); + mCtx->emitKeyDBChanged(); + import->deleteLater(); +} + +void MainWindow::changeMessage(const QString &msg, const bool keep) +{ + int timeout = keep ? 0 : 10000; + + statusBar()->showMessage(msg, timeout); } void MainWindow::openKeyManagement() @@ -749,11 +821,38 @@ void MainWindow::encrypt() QStringList *uidList = mKeyList->getChecked(); - QByteArray *tmp = new QByteArray(); - if (mCtx->encrypt(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) { - QString *tmp2 = new QString(*tmp); - edit->fillTextEditWithText(*tmp2); + if (uidList->count() == 0) { + QMessageBox::critical(0, tr("No Key Selected"), tr("No Key Selected")); + return; } + + QStringList options; + KGpgEncrypt::EncryptOptions opts = KGpgEncrypt::DefaultEncryption; + + opts |= KGpgEncrypt::AllowUntrustedEncryption; + opts |= KGpgEncrypt::AsciiArmored; + + KGpgEncrypt *encr = new KGpgEncrypt(this, *uidList, edit->curTextPage()->toPlainText(), opts, options); + encr->start(); + connect(encr, SIGNAL(done(int)), SLOT(slotEncryptDone(int))); +} + +void MainWindow::slotEncryptDone(int result) +{ + KGpgEncrypt *enc = qobject_cast(sender()); + Q_ASSERT(enc != NULL); + + if (result == KGpgTransaction::TS_OK) { + const QString lf = QLatin1String("\n"); + //setPlainText(enc->encryptedText().join(lf) + lf); + edit->fillTextEditWithText(enc->encryptedText().join(lf) + lf); + } else { + /*KMessageBox::sorry(this, i18n("The encryption failed with error code %1", result), + i18n("Encryption failed."));*/ + qDebug() << "The encryption failed with error code " << result; + } + + sender()->deleteLater(); } void MainWindow::sign() @@ -764,11 +863,41 @@ void MainWindow::sign() QStringList *uidList = mKeyList->getPrivateChecked(); - QByteArray *tmp = new QByteArray(); + if(uidList->isEmpty()) { + QMessageBox::critical(0, tr("Key Selection"), tr("No Private Key Selected")); + return; + } + + //QByteArray *tmp = new QByteArray(); - if (mCtx->sign(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) { + /*if (mCtx->sign(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) { edit->fillTextEditWithText(QString::fromUtf8(*tmp)); + }*/ + + // TODO: more than one signers + KGpgSignText *signt = new KGpgSignText(this, uidList->first(), edit->curTextPage()->toPlainText()); + connect(signt, SIGNAL(done(int)), SLOT(slotSignDone(int))); + signt->start(); + //KGpgTextInterface *interface = new KGpgTextInterface(message, signkeyid, options); + //connect(interface, SIGNAL(txtSigningFinished(QString)), SLOT(slotSignUpdate(QString))); + //interface->signText(message, signkeyid, options); +} + +void MainWindow::slotSignDone(int result) +{ + const KGpgSignText * const signt = qobject_cast(sender()); + sender()->deleteLater(); + Q_ASSERT(signt != NULL); + + if (result != KGpgTransaction::TS_OK) { + //KMessageBox::sorry(this, i18n("Signing not possible: bad passphrase or missing key")); + //return; + qDebug() << "Signing not possible: bad passphrase or missing key"; + return; } + + edit->fillTextEditWithText(signt->signedText().join(QLatin1String("\n")) + QLatin1String("\n")); + } void MainWindow::decrypt() @@ -777,21 +906,36 @@ void MainWindow::decrypt() return; } - QByteArray *decrypted = new QByteArray(); - QByteArray text = edit->curTextPage()->toPlainText().toAscii(); // TODO: toUtf8() here? - mCtx->preventNoDataErr(&text); + //QByteArray *decrypted = new QByteArray(); + //QByteArray text = edit->curTextPage()->toPlainText().toAscii(); // TODO: toUtf8() here? + + + const QString fullcontent = edit->curTextPage()->toPlainText(); + // TODO: do we still need this with kgpg? + //mCtx->preventNoDataErr(fullcontent.toAscii()); + + // TODO: whats the use of this? + int m_posstart = -1; + int m_posend = -1; + + if (!KGpgDecrypt::isEncryptedText(fullcontent, &m_posstart, &m_posend)) + return; + + KGpgDecrypt *decr = new KGpgDecrypt(this, fullcontent.mid(m_posstart, m_posend - m_posstart)); + connect(decr, SIGNAL(done(int)), SLOT(slotDecryptDone(int))); + decr->start(); // try decrypt, if fail do nothing, especially don't replace text - if(!mCtx->decrypt(text, decrypted)) { + /* if(!mCtx->decrypt(text, decrypted)) { return; - } + }*/ /* * 1) is it mime (content-type:) * 2) parse header * 2) choose action depending on content-type */ - if(Mime::isMime(decrypted)) { +/* if(Mime::isMime(decrypted)) { Header header = Mime::getHeader(decrypted); // is it multipart, is multipart-parsing enabled if(header.getValue("Content-Type") == "multipart/mixed" @@ -807,9 +951,32 @@ void MainWindow::decrypt() } } } - edit->fillTextEditWithText(QString::fromUtf8(*decrypted)); + edit->fillTextEditWithText(QString::fromUtf8(*decrypted));*/ } +void MainWindow::slotDecryptDone(int result) +{ + KGpgDecrypt *decr = qobject_cast(sender()); + Q_ASSERT(decr != NULL); + + /*if (!m_tempfile.isEmpty()) { + KIO::NetAccess::removeTempFile(m_tempfile); + m_tempfile.clear(); + }*/ + + if (result == KGpgTransaction::TS_OK) { + // FIXME choose codec + //setPlainText(decr->decryptedText().join(QLatin1String("\n")) + QLatin1Char('\n')); + edit->fillTextEditWithText(decr->decryptedText().join(QLatin1String("\n")) + QLatin1Char('\n')); + } else if (result != KGpgTransaction::TS_USER_ABORTED) { + //KMessageBox::detailedSorry(this, i18n("Decryption failed."), decr->getMessages().join( QLatin1String( "\n" ))); + qDebug() << "Decryption failed." << decr->getMessages().join( QLatin1String( "\n" )); + } + + decr->deleteLater(); +} + + void MainWindow::verify() { if (edit->tabCount()==0 || edit->curPage() == 0) { @@ -839,9 +1006,24 @@ void MainWindow::appendSelectedKeys() return; } - QByteArray *keyArray = new QByteArray(); - mCtx->exportKeys(mKeyList->getSelected(), keyArray); - edit->curTextPage()->append(*keyArray); + QStringList expopts; + KGpgExport *exp = new KGpgExport(this, *mKeyList->getSelected(), expopts); + connect(exp, SIGNAL(done(int)), SLOT(slotAppendSelectedKeysReady(int))); + exp->start(); +} + +void MainWindow::slotAppendSelectedKeysReady(int result) { + KGpgExport *exp = qobject_cast(sender()); + Q_ASSERT(exp != NULL); + + if (result == KGpgTransaction::TS_OK) { + edit->curTextPage()->append(QLatin1String( exp->getOutputData() )); + } else { + //KMessageBox::sorry(this, i18n("Your public key could not be exported\nCheck the key.")); + qDebug() << "Your public key could not be exported\nCheck the key."; + } + + exp->deleteLater(); } void MainWindow::copyMailAddressToClipboard() @@ -850,9 +1032,9 @@ void MainWindow::copyMailAddressToClipboard() return; } - gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getSelected()->first()); + KgpgCore::KgpgKey key = mCtx->getKeyDetails(mKeyList->getSelected()->first()); QClipboard *cb = QApplication::clipboard(); - QString mail = key->uids->email; + QString mail = key.email(); cb->setText(mail); } @@ -862,8 +1044,8 @@ void MainWindow::showKeyDetails() return; } - gpgme_key_t key = mCtx->getKeyDetails(mKeyList->getSelected()->first()); - if (key) { + KgpgCore::KgpgKey key = mCtx->getKeyDetails(mKeyList->getSelected()->first()); + if (key.id() != "") { new KeyDetailsDialog(mCtx, key, this); } } diff --git a/mainwindow.h b/mainwindow.h index 0097062..c17a71e 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -31,6 +31,13 @@ #include "aboutdialog.h" #include "verifynotification.h" #include "wizard.h" +//#include "kgpg/kgpgtextinterface.h" +#include "kgpg/core/kgpgkey.h" +#include "kgpg/transactions/kgpgencrypt.h" +#include "kgpg/transactions/kgpgdecrypt.h" +#include "kgpg/transactions/kgpgexport.h" +#include "kgpg/transactions/kgpgimport.h" +#include "kgpg/transactions/kgpgsigntext.h" QT_BEGIN_NAMESPACE class QMainWindow; @@ -87,16 +94,19 @@ private slots: * with the currently checked keys */ void encrypt(); + void slotEncryptDone(int result); /** * @details Show a passphrase dialog and decrypt the text of currently active tab. */ void decrypt(); + void slotDecryptDone(int result); /** * @details Sign the text of currently active tab with the checked private keys */ void sign(); + void slotSignDone(int result); /** * @details Verify the text of currently active tab and show verify information. @@ -129,11 +139,14 @@ private slots: * @details Import keys from currently active tab to keylist if possible. */ void importKeyFromEdit(); + void startImport(KGpgImport *import); + void slotImportDone(int result); /** * @details Append the selected keys to currently active textedit. */ void appendSelectedKeys(); + void slotAppendSelectedKeysReady(int result); /** * @details Copy the mailaddress of selected key to clipboard. @@ -277,6 +290,13 @@ private: */ void parseMime(QByteArray *message); + /** + * @brief show a message in the status bar + * @param msg the text to show + * @param keep if the text should stay visible or may be hidden after a while + */ + void changeMessage(const QString &msg, const bool keep = false); + TextEdit *edit; /** Tabwidget holding the edit-windows */ QMenu *fileMenu; /** Submenu for file operations*/ QMenu *editMenu; /** Submenu for text operations*/ diff --git a/release/bin/gpg-mac b/release/bin/gpg-mac new file mode 100755 index 0000000..fe9fe0e Binary files /dev/null and b/release/bin/gpg-mac differ diff --git a/release/ts/gpg4usb_ar.qm b/release/ts/gpg4usb_ar.qm index 3135f47..17627b8 100644 Binary files a/release/ts/gpg4usb_ar.qm and b/release/ts/gpg4usb_ar.qm differ diff --git a/release/ts/gpg4usb_ar.ts b/release/ts/gpg4usb_ar.ts index 7989865..97dcbc7 100644 --- a/release/ts/gpg4usb_ar.ts +++ b/release/ts/gpg4usb_ar.ts @@ -933,9 +933,9 @@ Alessandro (pt_br) و Kirill (ru) و Phol (es) و Viriato (es) و Serse (it) و You are about to export your private key. This is NOT your public key, so don't give it away. Make sure you keep it save.Do you really want to export your private key? - أنت بصدد تصدير مفتاح السريّ. -هذا ليس مفتاحك العلنيّ. -احرص على حفظه في أمان. أتريد حقا تصدير مفتاحك السريّ؟ + أنت بصدد تصدير مفتاحك السريّ الذي تُظهّر به و توقّع. +هذا ليس مفتاحك العلنيّ الذي.تشاركه مع الآخرين ليُراسلوك. +إن صدّرته فاحرص على حفظه في أمان. أتريد حقا تصدير مفتاحك السريّ؟ @@ -1113,7 +1113,7 @@ Weak -> Strong You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window): To be more informative, I phrased the second sentence as "Uses of tools ompatible with the GPG system can use your public key for you [...]" ينبغي عليك توليد زوج مفاتيح يتألف من مفتاح علنيّ و آخر سريّ.<br /> -يمكن لمن يستخدمون أدوات متوافقةمع نظام التعمية GPG استخدام مفتاحك العلنيّ لتعمية الرسائل لك و للتحقق من توقيعك على الرسائل التي وقّعتها. بينما تستخدم أنت مفتاحك السريّ لتظهير الرسائل المعماة لك و لتوقيع الرسائل.<br /> +يمكن لمن يستخدمون أدوات متوافقةمع نظام التعمية PGP استخدام مفتاحك العلنيّ لتعمية الرسائل لك و للتحقق من توقيعك على الرسائل التي وقّعتها. بينما تستخدم أنت مفتاحك السريّ لتظهير الرسائل المعماة لك و لتوقيع الرسائل.<br /> لمزيد من المعلومات طالع الشرح (الذي سيظهر في النافذة الرئيسية): @@ -2313,7 +2313,8 @@ Alessandro (pt_br) و Kirill (ru) و Phol (es) و Viriato (es) و Serse (it) و Error Validating signature - خطأ أثناء التحقق من توقيع + This should better be phrased as "Invalid signature by %1", as "error" imples that the verification process itself filed, instead of yielding a complete, yet undesired, result. + توقيع غير صحيح من @@ -2377,7 +2378,7 @@ Alessandro (pt_br) و Kirill (ru) و Phol (es) و Viriato (es) و Serse (it) و OK - حَسَنٌ + جيِّد @@ -2395,12 +2396,12 @@ Alessandro (pt_br) و Kirill (ru) و Phol (es) و Viriato (es) و Serse (it) و Show detailed verify information - أظهر بيانات تفصيلية للاستيثاق + أظهر تفاصيلَ بيانات الاستيثاق Details - بيانات + تفاصيل @@ -2415,12 +2416,12 @@ Alessandro (pt_br) و Kirill (ru) و Phol (es) و Viriato (es) و Serse (it) و Text was completely signed by: - النصُّ كُلُّه وقَّعه %1: + النصُّ كُلُّه وقَّعه: Text was partially signed by: - النصُّ بعضُه وقَّعه %1: + النصُّ بعضُه وقَّعه: diff --git a/release/ts/gpg4usb_de.ts b/release/ts/gpg4usb_de.ts index e3366ef..c59b3ed 100644 --- a/release/ts/gpg4usb_de.ts +++ b/release/ts/gpg4usb_de.ts @@ -82,34 +82,6 @@ Attachments - - Add File - Datei hinzufügen - - - Add a file - Füge eine Datei hinzu - - - Encrypt - Verschlüsseln - - - Encrypt marked File(s) - Verschlüssele die markierten Dateien - - - Decrypt - Entschlüsseln - - - Decrypt marked File(s) - Entschlüssele die markierten Dateien - - - couldn't open file: - Konnte Datei nicht öffnen: - @@ -281,23 +253,11 @@ File exists! Do you want to overwrite it? Die Datei existiert bereits! Möchten sie sie überschreiben? - - Files - Dateien - - - All Files (*) - Alle Dateien (*) - Save File Datei Speichern - - couldn't open file: - Konnte Datei nicht öffnen: - Cannot write file %1: @@ -342,49 +302,6 @@ Language Sprache - - Language change is applied after restarting program. - Die Änderung der Sprache wird beim nächsten Programmstart übernommen. - - - System Default - Systemstandard - - - - GpgME::Context - - No Key Selected - Kein Schlüssel ausgewählt - - - Unsupported algorithm - Nicht unterstützter Algorithmus - - - Error decrypting: - Fehler beim Entschlüsseln: - - - Wrong password - Falsches Passwort - - - Enter Password - Bitte Passwort eingeben - - - Key Selection - Schlüsselauswahl - - - No Private Key Selected - Kein privater Schlüssel ausgewählt - - - Error signing: - Fehler beim Signieren: - GpgME::GpgContext @@ -439,453 +356,6 @@ Fehler beim Signieren: - - GpgWin - - &Open... - Ö&ffnen... - - - Ctrl+O - Strg+O - - - Open an existing file - Öffen Datei - - - &Save - &Speichern - - - Ctrl+S - Strg+S - - - Save the current File - Speichere Datei - - - Save &As - Speichern &unter - - - Ctrl+A - Strg+A - - - Save the current File as... - Speichere aktuelle Datei als.... - - - &Print - &Drucken - - - Ctrl+P - Strg+P - - - Print Document - Drucken - - - &Quit - &Beenden - - - Ctrl+Q - Strg+Q - - - Quit Program - Beende das Programm - - - &Paste - E&infügen - - - Ctrl+V - Strg+V - - - Paste Text From Clipboard - Füge Text aus der Zwischenablage ein - - - Cu&t - &Ausschneiden - - - Ctrl+X - Strg+X - - - Cut the current selection's contents to the clipboard - aktuelle Auswahl ausschneiden und in Zwischenablage einfügen - - - &Copy - &Kopieren - - - Ctrl+C - Strg+C - - - Copy the current selection's contents to the clipboard - aktuelle Auswahl in Zwischenablage kopieren - - - Select &All - Alles &markieren - - - Select the whole text - Den ganzen Text markieren - - - Open settings dialog - Öffne den Einstellungsdialog - - - &Encrypt - &Verschlüsseln - - - Ctrl+E - Ctrl+E - - - Encrypt Message - Verschlüssele den Text - - - &Decrypt - &Entschlüsseln - - - Ctrl+D - Ctrl+D - - - Decrypt Message - Entschlüssele den Text - - - Import New Key From File - Importiere einen neuen Schlüssel aus Datei - - - Import New Key From Editor - Importiere einen neuen Schlüssel aus dem Textfeld - - - &About - &Info - - - Show the application's About box - Zeige die Information über die Anwendung - - - &File - &Datei - - - &Edit - &Bearbeiten - - - &Help - &Hilfe - - - File - Datei - - - Edit - Bearbeiten - - - &Undo - &Rückgängig - - - &New - &Neu - - - Open a new file - Öffne eine neue Datei - - - &Close - &Schliessen - - - Close file - Schliesse die Datei - - - Undo Last Edit Action - Mache die letzte Aktion rückgängig - - - &Redo - &Wiederherstellen - - - Redo Last Edit Action - Stelle die letzte Editieraktion wieder her - - - &Quote - &Kommentiere - - - Quote whole text - Kommentiere den gesamten Text - - - Remove double &Linebreaks - Entferne doppelte &Zeilenumbrüche - - - Remove double linebreaks, e.g. in pasted text from webmailer - Entferne doppelte Zeilenumbrüche, z.B. bei eingefügtem Text aus einem Webmailer - - - Se&ttings - Ei&nstellungen - - - &File Encryption - Datei Verschlüsselung - &Datei Verschlüsselung - - - Encrypt/Decrypt File - Ver-/Entschlüssele Datei - - - &Sign - &Signiere - - - Sign Message - Signiere die Nachricht - - - &Verify - &Verifiziere - - - Verify Message - Verifiziere die Nachricht - - - Key Management - Schlüsselverwaltung - - - Open Keymanagement - Öffne die Schlüsselverwaltung - - - Open Import New Key Dialog - Öffne den Schlüsselimport Dialog - - - Online &Tutorial - Online &Dokumentation - - - Open Online Tutorial - Öffne die Online Dokumentation - - - Translate gpg4usb - Übersetze gpg4usb - - - Translate gpg4usb yourself - Übersetze gpg4usb selbst - - - Append Selected Key(s) To Text - Hänge die ausgewählten Schlüssel an den Text an - - - Append The Selected Keys To Text in Editor - Hänge den gewählten Schhlüssel an den Text im Editor an - - - Copy EMail-address - Kopiere EMail-Adresse - - - Copy selected EMailaddress to clipboard - Kopiere die ausgewählten EMail-Adresse in die Zwischenablage - - - Show Keydetails - Eigenschaften anzeigen - - - Show Details for this Key - Details zu diesem Schlüssel anzeigen - - - &Keys - Sch&lüssel - - - &Import Key From... - &Importiere Schlüssel aus... - - - &View - &Ansicht - - - Key - Schlüssel - - - Ready - Fertig - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Diese Anwendung erlaubt es, auf einfache <br>Art Texte und Dateien zu ver- und entschlüsseln. <br>Sie steht unter der GPL v3.0<br><br><b>Entwickler:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Übersetzung:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>Falls sie Fragen und/oder Vorschläge haben,<br>kontaktieren sie uns unter<br>gpg4usb at cpunk.de</a><br><br>oder treffen Sie uns in unserem xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> oder senden Sie eine Email an unsere Mailingliste unter <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Keyserver - &Schlüsselserver - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Diese Anwendung erlaubt es, auf einfache <br>Art Texte und Dateien zu ver- und entschlüsseln. <br>Sie steht unter der GPL v2.0<br><br><b>Entwickler:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Übersetzung:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>Falls sie Fragen und/oder Vorschläge haben,<br>kontaktieren sie uns unter<br>gpg4usb at cpunk.de</a><br><br>oder treffen Sie uns in unserem xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Diese Anwendung erlaubt es, auf einfache <br>Art Texte und Dateien zu ver- und entschlüsseln. <br>Sie steht unter der GPL v2.0<br><br><b>Entwickler:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Übersetzung:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>Falls sie Fragen und/oder Vorschläge haben,<br>kontaktieren sie uns unter<br>gpg4usb at cpunk.de</a><br><br>oder treffen Sie uns in unserem xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - - - There is one unencrypted file in attachment folder - Es gibt unverschlüsselte Dateien im Attachment Ordner - - - There are - Es gibt - - - unencrypted files in attachment folder - unverschlüsselte Dateien im Attachment Ordner - - - Encrypt for: - Verschlüssele für: - - - Attached files: - Angehängte Dateien: - - - Application - Anwendung - - - Cannot read file %1: -%2. - Kann Datei nicht lesen %1: %2. - - - File loaded - Datei geladen - - - The document has been modified. -Do you want to save your changes? - Die Datei würde verändert. Möchten Sie die Änderung speichern? - - - Cannot write file %1: -%2. - Kann Datei nicht lesen %1: %2. - - - Saved '%1' - %1 gespeichert - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Diese Anwendung ermöglicht einfaches<br>Ver- und Entschlüsseln von Texten und Dateien.<br>Sie steht unter der GPL v2.0<br><br><b>Entwickler:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Übersetzung:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es)<br><br>Falls Sie irgendwelche Fragen und/oder <br>Vorschläge haben, kontaktieren Sie uns über<br>gpg4usb at cpunk.de</a><br><br>oder treffen sie uns einfach in unserem XMPP-Channel:<br>gpg4usb at conference.jabber.ccc.de</center> - - - Open Key - Öffne Datei - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Kirill (ru)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Diese Anwendung erlaubt das einfache<br> Ver-und Entschlüsseln von Texten und Dateien.<br>Die Anwendung ist lizensiert unter der GPL v2.0<br><br><b>Entwickler:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Übersetzung:</b><br>Kirill (ru), Alessandro (pt)<br><br>Falls sie Fragen oder Anregungen haben,<br> kontaktieren sie uns unter gpg4usb at cpunk.de</a><br><br>oder treffen sie uns in unserem XMPP-Channel:<br>gpg4usb at conference.jabber.ccc.de</center> - - - couldn't open file: - Konnte Datei nicht öffnen: - - - &Editor - &Editor - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Diese Anwendung erlaubt es, auf einfache <br>Art Texte und Dateien zu ver- und entschlüsseln. <br>Sie steht unter der GPL v3.0<br><br><b>Entwickler:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Übersetzung:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>Falls sie Fragen und/oder Vorschläge haben,<br>kontaktieren sie uns unter<br>gpg4usb at cpunk.de</a><br><br>oder treffen Sie uns in unserem xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> oder senden Sie eine Email an unsere Mailingliste unter <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Clipboard - &Zwischenablage - - - Import New Key From Clipboard - Importiere neuen Schlüssel aus der Zwischenablage - - - Import Key - Schlüsselimport - - - &Crypt - &Crypt - - - Crypt - Crypt - - - About - Über - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Diese Anwendung ermöglicht einfaches<br>Ver- und Entschlüsseln von Texten und Dateien.<br>Sie steht unter der GPL v2.0<br><br><b>Entwickler:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Übersetzung:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es)<br><br>Falls Sie irgendwelche Fragen und/oder <br>Vorschläge haben, kontaktieren Sie uns über<br>gpg4usb at cpunk.de</a><br><br>oder treffen sie uns einfach in unserem XMPP-Channel:<br>gpg4usb at conference.jabber.ccc.de</center> - - - Key Files - Schlüssel Dateien - - - All Files - Alle Dateien - - - Import Key From... - Impoertiere neuen Schlüssel aus... - - ImportFromGnupgPage @@ -966,10 +436,6 @@ Do you want to save your changes? Imported Configuration from old gpg4usb.<br>Will now restart to activate the configuration. Einstellungen wurden erfolgreich aus anderen gpg4usb importiert.<br> Starte neu, um die Einstellungen zu aktivieren. - - Imported Configuration from old gpg4usb.<br/>Will now restart to activate the configuration. - Einstellungen wurden erfolgreich aus anderen gpg4usb importiert.<br> Starte neu, um die Einstellungen zu aktivieren. - IntroPage @@ -1118,14 +584,6 @@ Make sure you keep it save.Do you really want to export your private key?Exporting private Key Privaten Schlüssel exportieren - - You are about to export your private key. -This is NOT your public key, so don't give it away. -Make sure you keep it save. - Sie sind dabei ihren privaten Schlüssel zu exportieren. -Das ist NICHT ihr öffentlicher Schlüssel, -also geben sie ihn nicht weiter. - Export Key To File @@ -1136,10 +594,6 @@ also geben sie ihn nicht weiter. Key Files Schlüssel Dateien - - Key Files - Schlüsseldateien - KeyGenDialog @@ -1431,19 +885,11 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) Close Key Management Beende die Schlüsselverwaltung - - Import From &File - &Import aus Datei - Import New Key From File Importiere einen neuen Schlüssel aus einer Datei - - Import From &Clipboard - Import aus &Zwischenablage - Import New Key From Clipboard @@ -1560,10 +1006,6 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) &Key Sch&lüssel - - Crypt - Crypt - Open Key @@ -1600,82 +1042,11 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) <br/>The action can not be undone. <br/>Diese Aktion kann nicht rückgängig gemacht werden. - - Are you sure that you want to delete the selected keys?. -The action can not be undone. - Sind Sie sicher, das sie die ausgewählten Schlüssel löschen wollen? -Die Aktion kann nicht rückgängig gemacht werden. - Export Key To File Schlüssel exportieren - - Name: - Name: - - - E-Mailaddress:: - E-Mailadresse: - - - Comment: - Kommentar: - - - KeySize (in Bit): - Schlüsselgröße (in Bit): - - - Expiration Date: - Ablaufdatum: - - - Password: - Passwort: - - - Repeat Password: - Passwort wiederholen: - - - Never Expire - läuft nie ab - - - Password: Strength -Weak -> Strong - Passwortstärke -Schwach -> Stark - - - Password Strength - Passwortstärke - - - Name must contain at least five characters. - - Name muss mindestens 5 Buchstaben lang sein. - - - Password and Repeat don't match. - Passwort und Wiederholung stimmen nicht überein. - - - Generating Key... - Erzeuge Schlüssel... - - - Collecting random data for key generation. - This may take a while. - To speed up the process use your computer - (e.g. browse the net, listen to music,...) - Sammle Zufallsdaten für Schlüsselerzeugung. -Das kann etwas dauern. -Benutze den Computer um den Vorgang zu -Beschleunugen(z.B. Internet-surfen, Musik hören, ...) - KeyServerImportDialog @@ -1730,62 +1101,58 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) Bemerkung - + Couldn't contact keyserver! Konnte Schlüsselserver nicht erreichen! - + Too many responses from keyserver! Zu viele Antworten vom Schlüsselserver! - + No keys found, input may be kexId, retrying search with 0x. Keine Schlüssel gefunden, der Suchbegriff könnte eine Schlüssel-ID sein. Wiederhole suche mit vorangestellten 0x. - + No keys found containing the search string! Keinen Schlüssel gefunden, der den Suchbegriff enthält! - + Insufficiently specific search string! Suchbegriff zu ungenau definiert! - + revoked abgelaufen - + disabled deaktiviert - + %1 keys found. Doubleclick a key to import it. %1 Schlüssel gefunden. Importiere durch Doppelklick. - + Error while contacting keyserver! Fehler bei der Verbindung zum Schlüsselserver! - + Key imported Schlüssel importiert KeyserverTab - - Deafult Keyserver for import: - Standard Schlüsselserver für den Import: - Default Keyserver for import: @@ -2349,99 +1716,6 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) Settings Einstellungen - - Iconsize - Optionen - - - small - klein - - - medium - mittel - - - large - gross - - - Iconstyle - Iconstil - - - just text - Nur Text - - - just icons - Nur Icons - - - text and icons - Text und Icons - - - Windowstate - Fenstereinstellungen - - - Save window size and position on exit. - Speichere Fenstergröße und -position beim Beenden. - - - Save checked private keys on exit and restore them on next start. - Speichere ausgewählte private Schlüssel beim Beenden und stelle diese beim nächsten Start wieder her. - - - MIME-parsing (Experimental) - MIME-Parsing (Experimentell) - - - Try to split attachments from PGP-MIME ecrypted messages. - Versuche, die Anhänge von PGP-MIME verschlüsselten Nachrichten zu extrahieren. - - - Try to recognize quoted printable. - Versuche Quoted Printable Text zu erkennen. - - - Enable open with external app, saves file in tmp folder. - Aktiviere das Öffnen mit externen Anwendungen (dieses speichert die Datei im Temp Verzeichnis). - - - Remember Password - Behalte das Passwort - - - Remember password till closing gpg4usb - Behalte das Passwort bis gpg4usb geschlossen wird - - - save window size and position on exit - Speichere Fenstergröße und -position beim Beenden - - - Save Checked Keys - Schlüsselspeicherung - - - Save checked private keys on exit and restore them on next start - Speichere ausgewählte private Schlüssel beim Beenden und stelle diese beim nächsten Start wieder her. - - - Language - Sprache - - - Language change is applied after restarting program. - DIe Änderung der Sprache wird beim nächsten Progrmmstart übernommen. - - - English - Insert local name of language here. This is used for the language menu of the settingsdialog - Deutsch - General @@ -2467,10 +1741,6 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) Advanced Erweitert - - English - Deutsch - System Default @@ -2560,16 +1830,6 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) Der Text wurde teilweise signiert am %1 von: - - Text was completly signed on %1 by: - - Der Text wurde vollständig signiert am %1 durch: - - - Text was partially signed on %1 by: - - Der Text wurde teilweise signiert am %1 durch: - VerifyKeyDetailBox @@ -2661,23 +1921,11 @@ Beschleunugen(z.B. Internet-surfen, Musik hören, ...) Text was partially signed by: Der Text wurde teilweise signiert von: - - Key not present with Fingerprint: - Schlüssel nicht vorhanden mit Fingerabdruck: - Error for key with fingerprint Fehler den den Schlüssel mit Fingerabdruck - - Text is completly signed by: - Text ist vollständig signiert durch: - - - Text is partially signed by: - Text ist teilweise signiert durch: - Wizard diff --git a/release/ts/gpg4usb_en.ts b/release/ts/gpg4usb_en.ts index c56be76..fa16e5b 100644 --- a/release/ts/gpg4usb_en.ts +++ b/release/ts/gpg4usb_en.ts @@ -1096,52 +1096,52 @@ Weak -> Strong - + Couldn't contact keyserver! - + Too many responses from keyserver! - + No keys found, input may be kexId, retrying search with 0x. - + No keys found containing the search string! - + Insufficiently specific search string! - + revoked - + disabled - + %1 keys found. Doubleclick a key to import it. - + Error while contacting keyserver! - + Key imported @@ -1706,11 +1706,6 @@ Weak -> Strong SettingsDialog - - English - Insert local name of language here. This is used for the language menu of the settingsdialog - English - General @@ -1746,10 +1741,6 @@ Weak -> Strong System Default - - English - English - TextEdit diff --git a/release/ts/gpg4usb_es.ts b/release/ts/gpg4usb_es.ts index 044003c..b580e2b 100644 --- a/release/ts/gpg4usb_es.ts +++ b/release/ts/gpg4usb_es.ts @@ -2,1778 +2,290 @@ - - - Iconsize - Tamaño Icono - - - small - pequeño - - - medium - mediano - - - large - grande - - - Iconstyle - Estilo Icono - - - just text - solo texto - - - just icons - solo iconos - - - text and icons - texto e iconos - - - Windowstate - Ventana de Estado - - - Save window size and position on exit. - Guardar tamaño y posicion ventana al salir. - - - Filename - Nombre de archivo - - - Contenttype - Tipo de contenido - - - couldn't open file: - no se pudo abrir el archivo: - - - Save File - Guardar Archivo - - - Save this file - Guardar este archivo - - - Open File - Abrir Archivo - - - Open this file - Abrir este archivo - - - File - Archivo - - - Cannot write file %1: -%2. - No puedo escribir archivo %1: -%2. - - - Encrypt / Decrypt File - Cifrar / Descifrar Archivo - - - Action - Accion - - - Input - Entrada - - - ... - ... - - - Output - Salida - - - &Encrypt - &Cifrar - - - &Decrypt - &Descifrar - - - File exists! Do you want to overwrite it? - El archivo existe! ¿Quiere sobreescribirlo? - - - Remember Password - Recordar Contraseña - - - Remember password until closing gpg4usb - Recordar contraseña hasta cerrar gpg4usb - - - Save Checked Keys - Guardar Llaves Verificadas - - - Save checked private keys on exit and restore them on next start. - Guardar llaves privadas verificadas al salir y restaurarlas en proximo arranque. - - - Confirm drag'n'drop key import - Confirmar importar llave arrastrar y soltar - - - Import files dropped on the keylist without confirmation. - Importar archivos soltados en la lista de llaves sin confirmacion. - - - Language - Idioma - - - Language change is applied after restarting program. - Cambio idioma se aplicara despues de reiniciar el programa. - - - System Default - Por Defecto - - - No Key Selected - Ninguna llave seleccionada - - - Unsupported algorithm - Algoritmo incompatible - - - Error decrypting: - Error al descifrar: - - - Wrong password - Contraseña incorrecta - - - Enter Password - Ingresar Contraseña - - - Key Selection - Seleccionar Llave - - - No Private Key Selected - No se Selecciono Llave Privada - - - Error signing: - Error al firmar: - - - &Open... - &Abrir... - - - Ctrl+O - Crtl+O - - - Open an existing file - Abrir archivo existente - - - &Save - &Guardar - - - Ctrl+S - Crtl+S - - - Save the current File - Guardar archivo actual - - - Save &As - Guardar &Como - - - Save the current File as... - Guardar Archivo actual como... - - - &Print - &Imprimir - - - Ctrl+P - Crtl+P - - - Print Document - Imprimir Documento - - - &Quit - &Salir - - - Ctrl+Q - Crtl+Q - - - Quit Program - Salir del Programa - - - &Undo - &Deshacer - - - Undo Last Edit Action - Deshacer Ultima Accion Editar - - - &Redo - &Rehacer - - - Redo Last Edit Action - Rehacer ultima accion editar - - - &Paste - &Pegar - - - Ctrl+V - Crtl+V - - - Paste Text From Clipboard - Pegar Texto desde Portapapeles - - - Cu&t - Corta&r - - - Ctrl+X - Crtl+X - - - Cut the current selection's contents to the clipboard - Cortar contenido de la seleccion actual al portapapeles - - - &Copy - &Copiar - - - Ctrl+C - Crtl+C - - - Copy the current selection's contents to the clipboard - Copiar contenido de la seleccion actual al portapapeles - - - Select &All - Seleccionar &Todo - - - Ctrl+A - Crtl+A - - - Select the whole text - Seleccionar todo el texto - - - Se&ttings - Con&figuracion - - - Open settings dialog - Abrir dialogo configuracion - - - Ctrl+E - Crtl+E - - - Encrypt Message - Cifrar Mensaje - - - Ctrl+D - Crtl+D - - - Decrypt Message - Descifrar Mensaje - - - &File Encryption - &Cifrado Archivo - - - Encrypt/Decrypt File - Cifrar / Descifrar Archivo - - - &Sign - &Firmar - - - Sign Message - Firmar Mensaje - - - &Verify - &Verificar - - - Verify Message - Verificar Mensaje - - - &File - &Archivo - - - Import New Key From File - Importar Nueva Llave Desde Archivo - - - &Editor - &Editor - - - Import New Key From Editor - Importar Nueva Llave Desde Editor - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - Try to determine if you use not complicated encryption (simple) or you use one taht is easy to use (facil) - <center>Este programa le permite hacer un facil<br/>cifrado/descifrado de sus mensajes de texto o archivos<br>Esta licenciado bajo el GPL v2.0<br><br><b>Programadores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Traduccion:</b><br>Alessandro (pt_br), Kirill (ru), Viriato13 (es), Serse (it) <br><br>Si usted tiene alguna pregunta y/o sugerencias, entre<br/>en nuestra <a href="http://gpg4usb.cpunk.de/contact.php">pagina de contacto</a> o envie un email a nuestra<br/> lista decorreo en <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Clipboard - &Portapapeles - - - Import New Key From Clipboard - Importar Nueva Llave Desde Portapapeles - - - Key Management - Administrador de Llaves - - - Open Keymanagement - Abrir Administrador de Llaves - - - Import Key - Importar Llave - - - Open Import New Key Dialog - Abrir Dialogo Importar Nueva Llave - - - &About - &Acerca de - - - Show the application's About box - Mostrar recuadro Acerca de del programa - - - Online &Tutorial - Tutorial &En linea - - - Open Online Tutorial - Abrir Tutorial En linea - - - Translate gpg4usb - Traducir gpg4usb - - - Translate gpg4usb yourself - Traduzca usted mismo gpg4usb - - - Append Selected Key(s) To Text - Adjuntar Llave(s) Seleccionada(s) Al Texto - - - Append The Selected Keys To Text in Editor - Adjuntar Llaves Seleccionadas Al Texto en Editor - - - Copy EMail-address - Copiar direcciones de Correo Electronico - - - Copy selected EMailaddress to clipboard - Copiar direcciones de Correo Electronico seleccionadas a portapapeles - - - Show Keydetails - Mostrar Detalles de Llave - - - Show Details for this Key - Mostrar Detalles para esta Llave - - - &Edit - &Editar - - - &Crypt - &Cifrar - - - &Keys - &Llaves - - - &Import Key From... - &Importar Llave Desde... - - - &View - &Ver - - - &Help - &Ayuda - - - Crypt - Cifrar - - - Key - Llave - - - Edit - Editar - - - Ready - Listo - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Este programa le permite hacer un facil<br/>cifrado/descifrado de sus mensajes de texto o archivos<br>Esta licenciado bajo el GPL v2.0<br><br><b>Programadores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Traduccion:</b><br>Alessandro (pt_br), Kirill (ru), Viriato13 (es), Serse (it) <br><br>Si usted tiene alguna pregunta y/o sugerencias, entre<br/>en nuestra <a href="http://gpg4usb.cpunk.de/contact.php">pagina de contacto</a> o envie un email a nuestra<br/> lista decorreo en <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Keyserver - &Servidor de llaves - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Este programa le permite hacer un facil<br>cifrado/descifrado de sus mensajes de texto o archivos<br>Esta licenciado bajo el GPL v2.0<br><br><b>Programadores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Traduccion:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato13 (es), Serse (it) <br><br>Si usted tiene alguna pregunta y/o<br>sugerencias, contactenos en<br>gpg4usb en cpunk.de</a><br><br>o puede encontrarnos en nuestro xmpp-channel:<br>gpg4usb en conference.jabber.ccc.de</center> - - - There is one unencrypted file in attachment folder - Hay un archivo sin cifrar en carpeta adjuntos - - - There are - Hay - - - unencrypted files in attachment folder - archivos sin cifrar en carpeta adjuntos - - - Encrypt for: - Cifrar para: - - - &New - &Nuevo - - - Open a new file - Abrir nuevo archivo - - - &Close - &Cerrar - - - Close file - Cerrar archivo - - - &Quote - &Poner comillas - - - Quote whole text - Poner comillas a todo el texto - - - Remove double &Linebreaks - Quitar doble &Fin de linea - - - Remove double linebreaks, e.g. in pasted text from webmailer - Quitar dobel fin de linea, p.ej. en texto pegado desde webmailer - - - Attached files: - Archivos Adjuntos: - - - Application - Programa - - - Cannot read file %1: -%2. - No puedo leer archivo %1: -%2. - - - File loaded - Archivo cargado - - - %1[*] - %2 - %1[*] - %2 - - - The document has been modified. -Do you want to save your changes? - El documento ha sido modificado. -¿Quiere usted guardar los cambios? - - - Saved '%1' - Guardado '%1' - - - About - Acerca de' - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Este Programa le permite hacer un facil<br>cifrado/descifrado de sus mensajes de texto o archivos.<br>Esta licenciado bajo el GPL v2.0<br><br><b>Programadores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Traduccion:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato13 (es)<br><br>Si usted tiene alguna pregunta y/ o <br>sugerencia, contacte con nosotros en<br>gpg4usb en cpunk.de</a><br><br>o puede encontrarnos en nuestro xmpp-channel:<br>gpg4usb en conference.jabber.ccc.de</center> - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Este Programa le permite hacer un facil<br>cifrado/descifrado de sus mensajes de texto o archivos.<br>Esta licenciado bajo el GPL v2.0<br><br><b>Programadores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Traduccion:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato13 (es)<br><br>Si usted tiene alguna pregunta y/ o <br>sugerencia, contacte con nosotros en<br>gpg4usb en cpunk.de</a><br><br>o puede encontrarnos en nuestro xmpp-channel:<br>gpg4usb en conference.jabber.ccc.de</center> - - - Open Key - Abrir Llave - - - Key Files - Archivos de Llaves - - - All Files - Todos los Archivos - - - Import Key From... - Importar Llave Desde... - - - Owner details - Detalles del Propietario - - - Key details - Detalles de la Llave - - - Fingerprint - Huella Digital - - - Name: - Nombre: - - - E-Mailaddress: - Direccion de Correo Electronico: - - - Comment: - Comentario: - - - Key size: - Tamaño de Llave: - - - Expires on: - Expira en: - - - Created on: - Creado en: - - - Algorithm: - Algoritmo: - - - Key ID: - ID de Llave: - - - Never - Nunca - - - / Never - / Nunca - - - Private Key - Llave Privada - - - Export Private Key - Exportar llave Privada - - - Warning: Key expired - Advertencia: Llave expirada - - - Keydetails - Detalles de Llave - - - Exporting private Key - Exportando Llave privada - - - You are about to export your private key. -This is NOT your public key, so don't give it away. -Make sure you keep it save. - Esta a punto de exportar su llave privada. -Esta NO es su llave publica, asi que no la revele. -Guardela de forma segura. - - - Export Key To File - Exportar Llave a Archivo - - - Key Files - Archivos Llaves - - - Name - Nombre - - - EMail - Correo Electrónico - - - Import Keys - Importar Llaves - - - You've dropped something on the keylist. - gpg4usb will now try to import key(s). - Usted ha soltado algo en la lista de llaves -gpg4usb intentara ahora importar la(s) llave(s). - - - Always import without bothering. - Siempre importar sin molestias. - - - Couldn't Open File: - No se pudo Abrir el Archivo: - - - Keymanagement - Administrador der Llaves - - - &Close Key Management - &Cerrar Administrador de Llaves - - - Close Key Management - Cerrar Administrador de Llaves - - - Import From &File - Importar Desde &Archivo - - - Import From &Clipboard - Importar Desde &Portapapeles - - - Import New Key From Keyserver - Importar Nueva Llave desde Servidor de Llaves - - - Export To &Clipboard - Exportar A &Portapapeles - - - Export Selected Key(s) To Clipboard - Exportar Llave(s) Seleccionada(s) A Portapapeles - - - Export To &File - Exportar A &Archivo - - - Export Selected Key(s) To File - Exportar Llave(s) Seleccionada(s) A Archivo - - - Delete Selected Key(s) - Borrar Llave(s) Seleccionada(s) - - - Delete the Selected keys - Borrar las Llaves Seleccionadas - - - Delete Checked Key(s) - Borrar Llave(s) Verificadas - - - Delete the Checked keys - Borrar las Llaves Verificadas - - - Generate Key - Crear Llave - - - Generate New Key - Crear Nueva Llave - - - &Key - &Llave - - - Deleting Keys - Borrando Llaves - - - <b>Are you sure that you want to delete the following keys?.</b><br/><br/> - ¿Esta usted seguro de querer borrar las siguientes llaves?.</b><br/><br/> - - - <br/>The action can not be undone. - <br/> La accion no puede deshacerse. - - - Are you sure that you want to delete the selected keys?. -The action can not be undone. - ¿Esta seguro de querer borrar las llaves seleccionadas?. -Esta accion no se puede deshacer. - - - E-Mailaddress:: - Direccion de Correo Electronico: - - - KeySize (in Bit): - Tamaño Llave (en Bit): - - - Expiration Date: - Fecha Expiracion: - - - Password: - Contraseña: - - - Repeat Password: - Repetir Contraseña: - - - Never Expire - Nunca Expira - - - Password: Strength -Weak -> Strong - Contraseña: Fortaleza -Debil -> Fuerte - - - Password Strength - Fortaleza de la Contraseña - - - Name must contain at least five characters. - - El nombre debe contener al menos cinco caracteres. - - - - Password and Repeat don't match. - Contraseña y Repetir no coinciden. - - - Generating Key... - Creando Llave... - - - Collecting random data for key generation. - This may take a while. - To speed up the process use your computer - (e.g. browse the net, listen to music,...) - Recogiendo datos aleatorios para crear llave. -Puede tardar un rato. -Para acelerar el proceso use su computadora -(ejemplo, navegar por la Red, oir musica,...) - - - &Import - &Importar - - - &Search - &Buscar - - - Search string: - Buscar cadena de caracteres: - - - Keyserver: - Servidor de llaves: - - - Import Keys from Keyserver - Importar Llaves desde el Servidor de Llaves - - - UID - Tu ID - - - Creation date - Fecha de creacion - - - KeyID - ID de Llave - - - Couldn't contact keyserver! - ¡No se puede contactar la servidor de llaves! - - - Too many responses from keyserver! - ¡Demasiadas respuestas desde el servidor de llaves! - - - No keys found, input may be kexId, retrying search with 0x. - No se encontraron llaves, el ingreso puede estar kexId, intentar buscar con 0x. - - - No keys found containing the search string! - ¿No existen llaves con esa cadena de caracteres! - - - Insufficiently specific search string! - ¡Cadena de caracteres insuficiente para busqueda! - - - %1 keys found. Doubleclick a key to import it. - %1 llaves encontradas. Pulse dos veces una llave para importarla. - - - Error while contacting keyserver! - ¡Error mientras contactaba al servidor de llaves! - - - Key imported - Llave importada - - - Default Keyserver for import: - Servidor de llaves por defecto para importar: - - - Decode quoted printable - Descifrar quoted printable - - - Try to recognize quoted printable. - Intentar reconocer quoted printable. - - - Parse PGP/MIME (Experimental) - Analizar PGP/MIME (Experimental) - - - Try to split attachments from PGP-MIME ecrypted messages. - Intenta separar los archivos adjuntos de los mensajes cifrados PGP-MIME. - - - Open with external application (Experimental) - Abrir con programa externo (Experimental) - - - Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol> - Abrir adjuntos con programa por defecto para el tipo de archivo <br>Hay al menos dos posibles problemas con esta opcion:<ol><li>Se necesita guardar el archivo sin cifrar en la carpeta adjuntos <br>Es tarea suya limpiar esta carpeta </li><li>El programa externo puede tener sus propios archivos temporales </li></ol> - - - Enable opening with external applications. - Permitir abrir con programas externos. - - - Unsaved files - Archivos No guardados - - - <h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3> - <h3>%1 archivos contienen informacion sin guardar.<br/>¿Guardar los cambios antes de cerrar?</h3> - - - Check the files you want to save: - Verificar los archivos que usted quiere guardar: - - - <b>Note:</b> If you don't save these files, all changes are lost.<br/> - <b>Nota:</b>Si usted no guarda estos archivos, se perderan todos los cambios.<br/> - - - Settings - Configuracion - - - save window size and position on exit - guardar tamaño y posicion de ventana al salir - - - MIME-parsing (Experimental) - MIME-analisis (Experimental) - - - General - General - - - Appearance - Aspecto - - - PGP/Mime - PGP/Mime - - - Keyserver - Servidor de llaves - - - Tab Dialog - Pestaña Dialogo - - - English - Español - - - untitled - sin nombre - - - Open file - Abrir archivo - - - Save file - Guardar archivo - - - Unsaved document - Documento sin guardar - - - <h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3> - <h3>El documento "%1" ha sido modificado.<br/>¿Quiere guardar sus cambios? </h3> - - - Signaturedetails - Detalles de firma - - - Error Validating signature - Error al Validar firma - - - Text was completely signed on - %1 by: - - El texto se registro completamente - %1 por: - - - Text was partially signed on - %1 by: - - El texto se registro parcialmente - %1 por: - - - Import from keyserver - Importar desde servidor de llaves - - - Status: - Estado: - - - Fingerprint: - Huella Digital: - - - Key not present in keylist - Llave ausente en la lista de llaves - - - Key not present with id 0x - Llave ausente con id 0x - - - EMail: - Correo electronico: - - - OK - OK - - - Error for key with id 0x - Error para llave con id 0x - - - Import missing key from Keyserver - Importar llave faltante desde Servidor de llaves - - - Show detailed verify information - Mostrar informacion de verificacion detallada - - - Error validating signature by: - Error al validar firma de: - - - Text was completely signed by: - El texto fue completamente firmado por: - - - Text was partially signed by: - El texto fue parcialmente firmado por: - - - Error for key with fingerprint - Error para la llave con huella digital - - - - AdvancedTab - - Show Steganography Options [Advanced] - Mostrar las Opciones de Esteganografía [Avanzado] - - - Show Steganographic Options. - Mostrar Opciones de Esteganografía. - - - - AppearanceTab - - Iconsize - Tamaño Icono - - - small - pequeño - - - medium - mediano - - - large - grande - - - Iconstyle - Estilo Icono - - - just text - solo texto - - - just icons - solo iconos - - - text and icons - texto e iconos - - - Windowstate - Ventana de Estado - - - Save window size and position on exit. - Guardar tamaño y posicion de ventana al salir. - - - - AttachmentTableModel - - Filename - Nombre de archivo - - - Contenttype - Tipo de contenido - - - - Attachments - - Save File - Guardar Archivo - - - Save this file - Guardar este archivo - - - Open File - Abrir Archivo - - - Open this file - Abrir este archivo - - - File - Archivo - - - Cannot write file %1: -%2. - No se puede escribir archivo %1: -%2. - - - - ChoosePage - - Choose your action... - Elija su acción... - - - ...by clicking on the apropriate link. - ....pulsando sobre el enlace pertinente. - - - If you have never used gpg4usb before and also don't own a gpg key yet you may possibly want to - Si nunca antes ha utilizado gpg4usb y tampoco cuenta todavia con una llave gpg podría desear - - - create a new keypair - crear un nuevo par de llaves - - - If you upgrade from an older version of gpg4usb you may want to - Si esta actualizando una versión anterior de gpg4usb podría querer - - - import settings and/or keys from gpg4usb - importar opciones y/o llaves de gpg4usb - - - If you are already using GnuPG you may want to - Si ya está utilizando GnuPG podría desear - - - import keys from GnuPG - importar llaves desde GnuPG - - - - ConclusionPage - - Ready. - Listo. - - - Have fun with gpg4usb! - ¡Diviértase con el gpg4usb! - - - You are ready to use gpg4usb now.<br><br>The offline help will get you started with gpg4usb. It will open in the main window.<br> - Ahora está listo para usar gpg4usb.<br><br>La ayuda sin conexión le ayudará a iniciarse con el gpg4usb. Esto abrirá la ventana principal.<br> - - - Open offline help. - Abrir la Ayuda sin conexión. - - - Dont show the wizard again. - No mostrar nuevamente al asistente. - - - - FileEncryptionDialog - - Encrypt / Decrypt File - Cifrar / Descifrar Archivo - - - File - Archivo - - - Action - Accion - - - Input - Entrada - - - ... - ... - - - Output - Salida - - - &Encrypt - &Cifrar - - - &Decrypt - &Descifrar - - - Open File - Abrir Archivo - - - Save File - Guardar Archivo - - - couldn't open file: - no se pudo abrir el archivo: - - - File exists! Do you want to overwrite it? - El archivo ya existe! ¿Quiere sobreescribirlo? - - - Cannot write file %1: -%2. - No puedo escribir archivo %1: -%2. - - - Decrypt File - Descifrar Archivo - - - Encrypt File - Cifrar Archivo - - - Couldn't Open file: - No se pudo abrir el archivo: - - - - GeneralTab - - Remember Password - Recordar Contraseña - - - Remember password until closing gpg4usb - Recordar contraseña hasta cerrar gpg4usb - - - Save Checked Keys - Guardar Llaves Verificadas - - - Save checked private keys on exit and restore them on next start. - Guardar llaves privadas verificadas al salir y restaurarlas en proximo arranque. - - - Confirm drag'n'drop key import - Confirmar importar llave arrastrar y soltar - - - Import files dropped on the keylist without confirmation. - Importar archivos soltados en la lista de llaves sin confirmacion. - - - Language - Idioma - - - Language change is applied after restarting program. - Cambio de idioma se aplicara despues de reiniciar el programa. - - - System Default - Por Defecto - - - - GpgME::Context - - No Key Selected - Ninguna llave seleccionada - - - Unsupported algorithm - Algoritmo incompatible - - - Error decrypting: - Error al descifrar: - - - Wrong password - Contraseña incorrecta - - - Enter Password - Ingresar Contraseña - - - Key Selection - Seleccionar Llave - - - No Private Key Selected - No se Selecciono Llave Privada - - - Error signing: - Error al firmar: - - - - GpgME::GpgContext - - No Key Selected - Ninguna llave seleccionada - - - <br>No private key with id %1 present in keyring - <br>No hay llave privada con id %1 en el llavero - - - Unsupported algorithm - Algoritmo incompatible - - - Error decrypting: - Error al descifrar: - - - Wrong password - Contraseña incorrecta - - - Enter Password - Ingresar Contraseña - - - Key Selection - Seleccionar Llave - - - No Private Key Selected - No se Selecciono Llave Privada - + AdvancedTab - Error signing: - Error al firmar: + Show Steganography Options [Advanced] + Mostrar las Opciones de Esteganografía [Avanzado] - Enter Password for - Ingresar Contraseña para + Show Steganographic Options. + Mostrar Opciones de Esteganografía. - GpgWin - - &New - &Nuevo - - - Open a new file - Abrir nuevo archivo - - - &Open... - &Abrir... - - - Open an existing file - Abrir archivo existente - - - &Save - &Guardar - - - Save the current File - Guardar archivo actual - - - Save &As - Guardar &Como - - - Save the current File as... - Guardar Archivo actual como... - - - &Print - &Imprimir - - - Print Document - Imprimir Documento - - - &Close - &Cerrar - - - Close file - Cerrar archivo - - - &Quit - &Salir - - - Quit Program - Salir del Programa - - - &Undo - &Deshacer - - - Undo Last Edit Action - Deshacer Ultima Accion Editar - - - &Redo - &Rehacer - - - Redo Last Edit Action - Rehacer ultima accion editar - - - &Paste - &Pegar - - - Paste Text From Clipboard - Pegar Texto desde Portapapeles - + AppearanceTab - Cu&t - Corta&r + Iconsize + Tamaño Icono - Cut the current selection's contents to the clipboard - Cortar contenido de la seleccion actual al portapapeles + small + pequeño - &Copy - &Copiar + medium + mediano - Copy the current selection's contents to the clipboard - Copiar contenido de la seleccion actual al portapapeles + large + grande - &Quote - &Poner comillas + Iconstyle + Estilo Icono - Quote whole text - Poner comillas a todo el texto + just text + solo texto - Select &All - Seleccionar &Todo + just icons + solo iconos - Select the whole text - Seleccionar todo el texto + text and icons + texto e iconos - Remove double &Linebreaks - Quitar doble &Fin de linea + Windowstate + Ventana de Estado - Remove double linebreaks, e.g. in pasted text from webmailer - Quitar doble fin de linea, p.ej. en texto pegado desde webmailer + Save window size and position on exit. + Guardar tamaño y posicion de ventana al salir. + + + AttachmentTableModel - Se&ttings - Con&figuracion + Filename + Nombre de archivo - Open settings dialog - Abrir dialogo configuracion + Contenttype + Tipo de contenido + + + Attachments - &Encrypt - &Cifrar + Save File + Guardar Archivo - Encrypt Message - Cifrar Mensaje + Save this file + Guardar este archivo - &Decrypt - &Descifrar + Open File + Abrir Archivo - Decrypt Message - Descifrar Mensaje + Open this file + Abrir este archivo - &File Encryption - &Cifrado Archivo + File + Archivo - Encrypt/Decrypt File - Cifrar / Descifrar Archivo + Cannot write file %1: +%2. + No se puede escribir archivo %1: +%2. + + + ChoosePage - &Sign - &Firmar + Choose your action... + Elija su acción... - Sign Message - Firmar Mensaje + ...by clicking on the apropriate link. + ....pulsando sobre el enlace pertinente. - &Verify - &Verificar + If you have never used gpg4usb before and also don't own a gpg key yet you may possibly want to + Si nunca antes ha utilizado gpg4usb y tampoco cuenta todavia con una llave gpg podría desear - Verify Message - Verificar Mensaje + create a new keypair + crear un nuevo par de llaves - &Editor - &Editor + If you upgrade from an older version of gpg4usb you may want to + Si esta actualizando una versión anterior de gpg4usb podría querer - Import New Key From Editor - Importar Nueva Llave Desde Editor + import settings and/or keys from gpg4usb + importar opciones y/o llaves de gpg4usb - Key Management - Administrador de Llaves + If you are already using GnuPG you may want to + Si ya está utilizando GnuPG podría desear - Open Keymanagement - Abrir Administrador de Llaves + import keys from GnuPG + importar llaves desde GnuPG + + + ConclusionPage - Import Key - Importar Llave + Ready. + Listo. - Open Import New Key Dialog - Abrir Dialogo Importar Nueva Llave + Have fun with gpg4usb! + ¡Diviértase con el gpg4usb! - &About - &Acerca de + You are ready to use gpg4usb now.<br><br>The offline help will get you started with gpg4usb. It will open in the main window.<br> + Ahora está listo para usar gpg4usb.<br><br>La ayuda sin conexión le ayudará a iniciarse con el gpg4usb. Esto abrirá la ventana principal.<br> - Show the application's About box - Mostrar recuadro Acerca de del programa + Open offline help. + Abrir la Ayuda sin conexión. - Online &Tutorial - Tutorial &En linea + Dont show the wizard again. + No mostrar nuevamente al asistente. + + + FileEncryptionDialog - Open Online Tutorial - Abrir Tutorial En linea + Encrypt / Decrypt File + Cifrar / Descifrar Archivo - Translate gpg4usb - Traducir gpg4usb + File + Archivo - Translate gpg4usb yourself - Traduzca usted mismo gpg4usb + Action + Accion - Append Selected Key(s) To Text - Adjuntar Llave(s) Seleccionada(s) Al Texto + Input + Entrada - Append The Selected Keys To Text in Editor - Adjuntar Llaves Seleccionadas Al Texto en Editor + Output + Salida - Copy EMail-address - Copiar direcciones de Correo Electronico + &Encrypt + &Cifrar - Copy selected EMailaddress to clipboard - Copiar direcciones de Correo Electronico seleccionadas a portapapeles + &Decrypt + &Descifrar - Show Keydetails - Mostrar Detalles de Llave + Open File + Abrir Archivo - Show Details for this Key - Mostrar Detalles para esta Llave + Save File + Guardar Archivo - &File - &Archivo + File exists! Do you want to overwrite it? + El archivo ya existe! ¿Quiere sobreescribirlo? - &Edit - &Editar + Cannot write file %1: +%2. + No puedo escribir archivo %1: +%2. - &Crypt - &Cifrar + Decrypt File + Descifrar Archivo - &Keys - &Llaves + Encrypt File + Cifrar Archivo - &Import Key From... - &Importar Llave Desde... + Couldn't Open file: + No se pudo abrir el archivo: + + + GeneralTab - &View - &Ver + Remember Password + Recordar Contraseña - &Help - &Ayuda + Remember password until closing gpg4usb + Recordar contraseña hasta cerrar gpg4usb - Crypt - Cifrar + Save Checked Keys + Guardar Llaves Verificadas - Key - Llave + Save checked private keys on exit and restore them on next start. + Guardar llaves privadas verificadas al salir y restaurarlas en proximo arranque. - Edit - Editar + Confirm drag'n'drop key import + Confirmar importar llave arrastrar y soltar - Ready - Listo + Import files dropped on the keylist without confirmation. + Importar archivos soltados en la lista de llaves sin confirmacion. - Encrypt for: - Cifrar para: + Language + Idioma + + + GpgME::GpgContext - Attached files: - Archivos Adjuntos: + No Key Selected + Ninguna llave seleccionada - About - Acerca de' + <br>No private key with id %1 present in keyring + <br>No hay llave privada con id %1 en el llavero - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Este programa le permite hacer un facil<br/>cifrado/descifrado de sus mensajes de texto o archivos<br>Esta licenciado bajo el GPL v3.0<br><br><b>Programadores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Traduccion:</b><br>Alessandro (pt_br), Kirill (ru), Viriato13 (es), Serse (it) <br><br>Si usted tiene alguna pregunta y/o sugerencias, entre<br/>en nuestra <a href="http://gpg4usb.cpunk.de/contact.php">pagina de contacto</a> o envie un email a nuestra<br/> lista decorreo en <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. + Unsupported algorithm + Algoritmo incompatible - There is one unencrypted file in attachment folder - Hay un archivo sin cifrar en carpeta adjuntos + Error decrypting: + Error al descifrar: - There are - Hay + Wrong password + Contraseña incorrecta - unencrypted files in attachment folder - archivos sin cifrar en carpeta adjuntos + Enter Password + Ingresar Contraseña - Import Key From... - Importar Llave Desde... + Key Selection + Seleccionar Llave - &Clipboard - &Portapapeles + No Private Key Selected + No se Selecciono Llave Privada - &Keyserver - &Servidor de llaves + Error signing: + Error al firmar: - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Este programa permite un fácil cifrado <br/>y descifrado de mensajes de texto o de archivos.<br>Esta autorizado en virtud al GPL v3<br><br><b>Programadores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Traduccion:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>Si tiene preguntas o sugerencias diríjase a <br/>nuestra <a href="http://gpg4usb.cpunk.de/contact.php">pagina de contacto</a> o envie un correo electrónico a nuestra<br/> lista de correos a <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. + Enter Password for + Ingresar Contraseña para @@ -1935,14 +447,6 @@ Para acelerar el proceso use su computadora Exporting private Key Exportando Llave privada - - You are about to export your private key. -This is NOT your public key, so don't give it away. -Make sure you keep it save. - Esta a punto de exportar su llave privada. -Esta NO es su llave publica, asi que no la revele. -Guardela de forma segura. - Export Key To File Exportar Llave a Archivo @@ -2325,72 +829,6 @@ gpg4usb intentara ahora importar la(s) llave(s). Export Key To File Exportar Llave a Archivo - - Name: - Nombre: - - - E-Mailaddress:: - Direccion de Correo Electronico: - - - Comment: - Comentario: - - - KeySize (in Bit): - Tamaño Llave (en Bit): - - - Expiration Date: - Fecha Expiracion: - - - Password: - Contraseña: - - - Repeat Password: - Repetir Contraseña: - - - Never Expire - Nunca Expira - - - Password: Strength -Weak -> Strong - Contraseña: Fortaleza -Debil -> Fuerte - - - Password Strength - Fortaleza de la Contraseña - - - Name must contain at least five characters. - - El nombre debe contener al menos cinco caracteres. - - - - Password and Repeat don't match. - Contraseña y Repetir no coinciden. - - - Generating Key... - Creando Llave... - - - Collecting random data for key generation. - This may take a while. - To speed up the process use your computer - (e.g. browse the net, listen to music,...) - Recogiendo datos aleatorios para crear llave. -Puede tardar un rato. -Para acelerar el proceso no use en su computadora -(ejemplo, navegar por la Red, oir musica,...) - Keyring files Carpetas Llavero @@ -2969,10 +1407,6 @@ Para acelerar el proceso no use en su computadora Settings Configuracion - - English - Español - Advanced Avanzado diff --git a/release/ts/gpg4usb_he.qm b/release/ts/gpg4usb_he.qm new file mode 100644 index 0000000..626d6cf Binary files /dev/null and b/release/ts/gpg4usb_he.qm differ diff --git a/release/ts/gpg4usb_he.ts b/release/ts/gpg4usb_he.ts new file mode 100644 index 0000000..9287a3a --- /dev/null +++ b/release/ts/gpg4usb_he.ts @@ -0,0 +1,1973 @@ + + + + + AdvancedTab + + + Show Steganography Options [Advanced] + להציג אפשרויות סטגנוגרפיה [מתקדם] + + + + Show Steganographic Options. + להציג אפשרויות סטגנוגרפיה. + + + + AppearanceTab + + + Iconsize + אייקונים + + + + small + קטנים + + + + medium + בינוניים + + + + large + גדולים + + + + Iconstyle + סגנון אייקונים + + + + just text + טקסט בלבד + + + + just icons + איקונים בלבד + + + + text and icons + טקסט ואיקונים + + + + Windowstate + מצב החלון + + + + Save window size and position on exit. + לשמור את גודל החלון ומיקומו ביציאה. + + + + AttachmentTableModel + + + Filename + שם קובץ + + + + Contenttype + סוג תוכן + + + + Attachments + + + + Save File + שמירה + + + + Save this file + לשמור קובץ + + + + Open File + פתיחה + + + + Open this file + לפתוח קובץ + + + + + File + קובץ + + + + + Cannot write file %1: +%2. + לא ניתן לכתוב לקובץ %1: +%2. + + + + ChoosePage + + + Choose your action... + בחר פעולה... + + + + ...by clicking on the apropriate link. + ...על-ידי לחיצה על הקישור המתאים. + + + + If you have never used gpg4usb before and also don't own a gpg key yet you may possibly want to + במידה וטרם השתמשת ב- gpg4usb וגם אין ברשותך מפתח gpg עדיין אולי תרצה + + + + create a new keypair + ליצור זוג מפתחות חדש + + + + If you upgrade from an older version of gpg4usb you may want to + במידה ואתה משדרג מגרסה קודמת של gpg4usb אולי תרצה + + + + import settings and/or keys from gpg4usb + ליבא הגדרות ו/או מפתחות מ- gpg4usb + + + + If you are already using GnuPG you may want to + במידה ואתה כבר נשתמש ב- GnuPG אולי תרצה + + + + import keys from GnuPG + ליבא מפתחות מ- GnuPG + + + + ConclusionPage + + + Ready. + מוכן. + + + + Have fun with gpg4usb! + תהנו עם gpg4usb! + + + + You are ready to use gpg4usb now.<br><br>The offline help will get you started with gpg4usb. It will open in the main window.<br> + אתה מוכן להתחיל להשתמש ב- gpg4usb.<br><br>קבצי העזרה יעזרו לך להתחיל לעבוד. הם יפתחו בחלון הראשי.<br> + + + + Open offline help. + לפתוח את קבצי העזרה. + + + + Dont show the wizard again. + אל תראה את האשף פעם נוספת. + + + + FileEncryptionDialog + + + Encrypt / Decrypt File + להצפין/לפענח קובץ + + + + + + File + קובץ + + + + Action + פעולה + + + + Decrypt File + לפענח קובץ + + + + Encrypt File + להצפין קובץ + + + + Input + קלט + + + + Output + פלט + + + + &Encrypt + &הצפנה + + + + &Decrypt + &פענוח + + + + Open File + פתיחה + + + + Save File + שמירה + + + + Couldn't Open file: + לא הצלחתי לפתוח קובץ: + + + + Cannot write file %1: +%2. + לא ניתן לכתוב לקובץ %1: +%2. + + + + File exists! Do you want to overwrite it? + הקובץ קיים! האם להחליפו? + + + + GeneralTab + + + Remember Password + לזכור סיסמה + + + + Remember password until closing gpg4usb + לזכור סיסמה עד לסגירת gpg4usb + + + + Save Checked Keys + לשמור מפתחות מסומנים + + + + Save checked private keys on exit and restore them on next start. + לשמור את המפתחות הפרטיים ביציאה ולשחזר אותם בהפעלה הבאה. + + + + Confirm drag'n'drop key import + לאשר יבוא מפתח בגרור-וזרוק + + + + Import files dropped on the keylist without confirmation. + ליבא מפתחות הזרקים ברשימת המפתחות ללא בקשת אישור. + + + + Language + שפה + + + + GpgME::GpgContext + + + No Key Selected + לא נבחר מפתח + + + + <br>No private key with id %1 present in keyring + <br>לא נמצא מפתח פרטי בטבעת עם המזהה %1 + + + + Unsupported algorithm + אלגוריתם לא נתמך + + + + Error decrypting: + שגיאת פענוח: + + + + Wrong password + סיסמה שגויה + + + + Enter Password for + הכנס סיסמה עבור + + + + Enter Password + הכנס סיסמה + + + + Key Selection + בחירת מפתח + + + + No Private Key Selected + לא נבחר מפתח פרטי + + + + Error signing: + שגיאת חתימה: + + + + ImportFromGnupgPage + + + Import keys... + יבוא מפתחות... + + + + ...from existing GnuPG installation + ...מהתקנה קיימת של GnuPG + + + + You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br> + ניתן ליבא מפתחות מ- GnuPG המותקן מקומית.<br><br> המיקום נקרא מהרגיסטרי של חלונות או מספריית .gnupg בתיקיית הבית של לינוקס.<br> + + + + Import keys from GnuPG + יבוא מפתחות מ- GnuPG + + + + Import Error + שגיאת יבוא + + + + Couldn't locate GnuPG home directory + לא הצלחתי לאתר את ספריית הבית של GnuPG + + + + ImportFromGpg4usbPage + + + Import from... + יבוא מ... + + + + ...existing gpg4usb + ...גרסה אחרת של gpg4usb + + + + You can import keys and/or settings from existing gpg4usb. <br><br>Just check what you want to import, click the import button and choose the directory of your other gpg4usb in the appearing file dialog. + באפשרותך ליבא מפתחות או הגדרות מגרסה אחרת של gpg4usb. <br><br>יש לסמן את האפשרויות ליבוא, ללחוץ על כפתור היבוא ולבחור את התיקיה של הגרסה האחרת של gpg4usb. + + + + Keys + מפתחות + + + + Configuration + הגדרות + + + + Import from gpg4usb + ליבא מ- gpg4usb + + + + Other gpg4usb directory + תיקיית gpg4usb + + + + Configuration Imported + הגדרות יובאו + + + + Imported Configuration from old gpg4usb.<br>Will now restart to activate the configuration. + יבאתי את ההגדרות מהגרסה הקודמת של gpg4usb. <br>מאתחל את התוכנה בכדי להפעיל ההגדרות החדשות. + + + + IntroPage + + + Getting started... + מתחילים... + + + + ... with gpg4usb + ...עם gpg4usb + + + + To use gpg4usb for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br> + בכדי להשתמש ב- gpg4usb לפענוח וחתימה של הודעות, יש צורך במפתח פרטי. הדף הבא יסייע לך ביצירת מפתח או יבוא של אחד.<br><br>למידע נוסף יש ללחוץ על הקישור לדף <a href='docu_concepts.html'>העקרונות</a> (לחיצה על הקישור תפתח את הדף בחלון המרכזי). <br> + + + + Choose a Language + בחירת שפה + + + + KeyDetailsDialog + + + Owner details + פרטי הבעלים + + + + Key details + פרטי המפתח + + + + Fingerprint + טביעת אצבע + + + + Additional Uids + מזהים נוספים + + + + Name: + שם: + + + + E-Mailaddress: + כתובת דוא"ל: + + + + Comment: + הערות: + + + + Expires on: + תקף עד: + + + + Created on: + נוצר ב: + + + + Key ID: + מזהה מפתח: + + + + copy fingerprint to clipboard + להעתיק טביעת אצבע ללוח ההדבקה + + + + Warning: Key expired + זהירות: פג תוקף המפתח + + + + Warning: Key revoked + זהירות: המפתח בוטל + + + + Keydetails + פרטי מפתח + + + + You are about to export your private key. +This is NOT your public key, so don't give it away. +Make sure you keep it save.Do you really want to export your private key? + הנך עומד ליצא את המפתח הפרטי שלך +זה *לא* המפתח הציבורי, אז אל תפיץ אותו. +חשוב לשמור עליו. האם ליצא את המפתח הפרטי? + + + + Key Files + קבצי מפתחות + + + + Export error + שגיאת יצוא + + + + Couldn't open %1 for writing + לא ניתן לפתוח את %1 לכתיבה + + + + Key size: + גודל המפתח: + + + + Algorithm: + אלגוריתם: + + + + Never + לעולם לא + + + + / Never + / לעולם לא + + + + Private Key + מפתח פרטי + + + + Export Private Key + ליצא את המפתח הפרטי + + + + Exporting private Key + מייצא את הפתח הפרטי + + + + Export Key To File + ליצא מפתח לקובץ + + + + KeyGenDialog + + + Generate Key + יצירת מפתח + + + + Password Strength + חוזק סיסמה + + + + Name: + שם: + + + + E-Mailaddress: + כתובת דוא"ל: + + + + Comment: + הערה: + + + + Expiration Date: + בתוקף עד: + + + + Never Expire + תקף לעד + + + + KeySize (in Bit): + גודל מפתח (בביטים): + + + + Password: + סיסמה: + + + + Password: Strength +Weak -> Strong + סיסמה: חוזק חלשה -> חזקה + + + + Repeat Password: + סיסמה בשנית: + + + + Name must contain at least five characters. + + השם חייב להכיל לפחות חמשה תווים. + + + + Password and Repeat don't match. + שתי הסיסמאות לא תואמות. + + + + Generating Key... + מייצר מפתח... + + + + Collecting random data for key generation. + This may take a while. + To speed up the process use your computer + (e.g. browse the net, listen to music,...) + אוסף נתונים אקראיים ליצירת המפתח. +הפעולה עשויה להתארך. +בכדי להאיץ את התהליך אפשר להשתמש במחשב +(לדוגמה: לגלוש ברשת, להאזין למוזיקה,...) + + + + Success + הצלחה + + + + New key created + מפתח חדש נוצר + + + + KeyGenPage + + + Create a keypair... + ליצור זוג מפתחות... + + + + ...for decrypting and signing messages + ...לפענוח וחתימה על הודעות + + + + You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window): + עליך ליצור זוג מפתחות חדש. הזוג כולל מפתח ציבורי ומפתח פרטי.<br>משתמשים אחרים יכולים להשתמש במפתח הציבורי שלך בכדי להצפין הודעות עבורך ולודא הודעות שנחתמו על ידך. באפשרותך לפענח ולחתום על הודעות בעזרת המפתח הפרטי.<br>למידע נוסף יש לפנות למדריכים הלא מקוונים (יוצג בחלון הראשי): + + + + Offline tutorial + מדריך לא מקוון + + + + Create New Key + יצירת מפתח חדש + + + + KeyImportDetailDialog + + + + Key import details + נתוני יבוא מפתח + + + + No keys found to import + לא נמצאו מפתחות ליבוא + + + + Genral key import info + נתונים כלליים + + + + Considered: + נמצאו: + + + + Public unchanged: + ציבוריים ללא שינוי: + + + + Imported: + יובאו: + + + + Not imported: + לא יובאו: + + + + Private read: + פרטיים: + + + + Private imported: + מפתחות פרטיים שיובאו: + + + + Private unchanged: + פרטיים ללא שינוי: + + + + Name + שם + + + + Email + דוא"ל + + + + Status + מצב + + + + Fingerprint + טביעת אצבע + + + + private + פרטי + + + + public + ציבורי + + + + unchanged + ללא שינוי + + + + new key + מפתח חדש + + + + new subkey + תת מפתח חדש + + + + new signature + חתימה חדשה + + + + new uid + מזהה חדש + + + + KeyList + + + Name + שם + + + + EMail + דוא"ל + + + + Import Keys + יבוא מפתחות + + + + You've dropped something on the keylist. + gpg4usb will now try to import key(s). + זרקת משהו על רשימת המפתחות +התוכנה תנסה ליבא את המפתח/ות. + + + + Always import without bothering. + תמיד יבא ללא שאלות. + + + + Couldn't Open File: + לא הצלחתי לפתוח את הקובץ: + + + + KeyMgmt + + + Keymanagement + מנהל מפתחות + + + + &Close Key Management + &לסגור את מנהל המפתחות + + + + Ctrl+Q + Ctrl+Q + + + + Close Key Management + לסגור את מנהל המפתחות + + + + Import New Key From File + יבוא מפתח חדש מקובץ + + + + Import New Key From Clipboard + יבוא מפתח חדש מלוח ההדבקה + + + + &Keyserver + &שרת מפתחות + + + + Import New Key From Keyserver + יבוא מפתח חדש משרת מפתחות + + + + Export To &Clipboard + יצוא &ללוח ההדבקה + + + + Export Selected Key(s) To Clipboard + יצוא המפתח/ות שנבחרו ללוח ההדבקה + + + + Export To &File + יצוא &לקובץ + + + + Export Selected Key(s) To File + לייצא מפתחות שנבחרו לקובץ + + + + Delete Selected Key(s) + למחוק מפתחות שנבחרו + + + + Delete the Selected keys + למחוק מפתחות שנבחרו + + + + Delete Checked Key(s) + למחוק מפתחות שסומנו + + + + Delete the Checked keys + למחוק מפתחות שסומנו + + + + Generate Key + יצירת מפתח + + + + Generate New Key + יצירת מפתח חדש + + + + Show Keydetails + להציג נתוני מפתח + + + + Show Details for this Key + להציג נתונים עבור מפתח זה + + + + Import key + ליבא מפתח + + + + Import key from + ליבא מפתח ממקור + + + + key(s) exported + מפתחות יוצאו + + + + + &File + &קובץ + + + + &Clipboard + &לוח הדבקה + + + + &Key + &מפתח + + + + &Import Key From... + &ליבא מפתח מ... + + + + Key + מפתח + + + + Open Key + לפתוח מפתח + + + + + Key Files + קבצי מפתח + + + + Keyring files + קבצי טבעת מפתחות + + + + Couldn't Open File: + לא הצלחתי לפתוח קובץ: + + + + Deleting Keys + מוחק מפתחות + + + + <b>Are you sure that you want to delete the following keys?.</b><br/><br/> + <b>האם למחוק את המפתחות הבאים?.</b><br/><br/> + + + + <br/>The action can not be undone. + <br/>The לא ניתן לשחזר פעולה זו. + + + + Export Key To File + ליצא מפתח לקובץ + + + + KeyServerImportDialog + + + &Close + &סגירה + + + + &Import + &יבוא + + + + &Search + &חיפוש + + + + Search string: + מחרוזת חיפוש: + + + + Keyserver: + שרת מפתחות: + + + + Import Keys from Keyserver + ליבא מפתחות משרת מפתחות + + + + UID + מזהה + + + + Creation date + תאריך יצירה + + + + KeyID + מזהה מפתח + + + + Tag + תג + + + + Couldn't contact keyserver! + לא הצלחתי להתחבר לשרת המפתחות! + + + + Too many responses from keyserver! + תשובות רבות מדי משרת המפתחות! + + + + No keys found, input may be kexId, retrying search with 0x. + לא נמצאו מפתחות, הקלט יכול להיות keyId, מנסה לחפש עם 0x. + + + + No keys found containing the search string! + לא נמצאו מפתחות המכילים את מחרוזת החיפוש! + + + + Insufficiently specific search string! + מחרוזת החיפוש אינה מוגדרת! + + + + revoked + נשלל + + + + disabled + נוטרל + + + + %1 keys found. Doubleclick a key to import it. + %1 מפתח/ות נמצאו. הקלקה כפולה בכדי לייבא. + + + + Error while contacting keyserver! + שגיאה בהתחברות לשרת המפתחות! + + + + Key imported + מפתח יובא + + + + KeyserverTab + + + Default Keyserver for import: + ברירת מחדל לשרת מפתחות ליבוא: + + + + MainWindow + + + &New + &חדש + + + + Open a new file + לפתוח קובץ חדש + + + + &Open... + &לפתוח... + + + + Open an existing file + לפתוח קובץ חדש + + + + &Save + &שמירה + + + + Save the current File + לשמור את הקובץ הנוכחי + + + + Save &As + &לשמור בשם + + + + Save the current File as... + לשמור את הקובץ הנוכחי בשם... + + + + &Print + &הדפסה + + + + Print Document + להדפיס + + + + + &Close + &סגירה + + + + Close file + לסגור את הקובץ + + + + &Quit + &יציאה + + + + Quit Program + לצאת מהתוכנית + + + + &Undo + &ביטול + + + + Undo Last Edit Action + ביטול פעולת עריכה אחרונה + + + + &Redo + &שחזור פעולה + + + + Redo Last Edit Action + לשחזר את פעולת העריכה האחרנה + + + + Zoom In + הגדלה + + + + Zoom Out + הקטנה + + + + &Paste + &הדבקה + + + + Paste Text From Clipboard + הדבקת טקסט מלוח ההדבקה + + + + Cu&t + &גזירה + + + + Cut the current selection's contents to the clipboard + גזריה ללוח ההדבקה + + + + &Copy + &העתקה + + + + Copy the current selection's contents to the clipboard + העתקה ללוח ההדבקה + + + + &Quote + &ציטוט + + + + Quote whole text + ציטוט כל הטקסט + + + + Select &All + בחירת &הכול + + + + Select the whole text + בחירת כל הטקסט + + + + Remove &spacing + להסיר &רווחים + + + + Remove double linebreaks, e.g. in pasted text from webmailer + הסרת מעברי שורות כפולים כגון בטקסט מעותק + + + + Se&ttings + &הגדרות + + + + Open settings dialog + פתיחת חלון ההגדרות + + + + &Encrypt + &הצפנה + + + + Encrypt Message + להצפין הודעה + + + + &Decrypt + &פענוח + + + + Decrypt Message + לפענח הודעה + + + + &File Encryption + &הצפנת קובץ + + + + Encrypt/Decrypt File + להצפין/לפענח קובץ + + + + &Encrypt File + &הצפנת קובץ + + + + Encrypt File + להצפין קובץ + + + + &Decrypt File + &פענח קובץ + + + + Decrypt File + לפענח קובץ + + + + &Sign + &חתימה + + + + Sign Message + לחתום הודעה + + + + &Verify + &אימות + + + + Verify Message + לאמת הודעה + + + + &Editor + &עורך + + + + Import New Key From Editor + יבוא מפתח חדש מהעורך + + + + Manage &keys + ניהול &מפתחות + + + + Open Keymanagement + פתיחת מנהל המפתחות + + + + &About + &אודות + + + + Show the application's About box + להציג את חלון האודות של היישום + + + + Integrated Help + עזרה מובנית + + + + Open integrated Help + לפתוח את העזרה המובנת + + + + Online &Tutorials + מדריכים &מקוונים + + + + Open Online Tutorials + לפתוח את המדריכין המקוונים + + + + Translate gpg4usb + תרגום gpg4usb + + + + Translate gpg4usb yourself + תרגם את gpg4usb + + + + Open &Wizard + פתיחת &אשף + + + + Open the wizard + לפתוח את האשף + + + + Append Selected Key(s) To Text + לצרף את המפתח/ות שנבחרו לטקסט + + + + Append The Selected Keys To Text in Editor + לצרף את המפתחות שנבחרו לטקסט שבעורך + + + + Copy EMail-address + להעתיק כתובת דוא"ל + + + + Copy selected EMailaddress to clipboard + העתקת כתובות דוא"ל שנבחרו ללוח ההדבקה + + + + Show Keydetails + הצגת נתוני מפתח + + + + Show Details for this Key + להציג פרטים אודות מפתח זה + + + + &File + &קובץ + + + + &Edit + &עריכה + + + + &Crypt + &הצפנה + + + + &Keys + &מפתחות + + + + &Import Key From... + &יבוא מפתח מ... + + + + &Steganography + &סטגנוגרפיה + + + + Remove PGP Header + הסרת כותרת PGP + + + + Add PGP Header + הוספת כותרת PGP + + + + &View + &צפייה + + + + &Help + &עזרה + + + + File + קובץ + + + + Crypt + הצפנה + + + + Key + מפתח + + + + Edit + עריכה + + + + Special edit + עריכה מיוחדת + + + + Import key from... + יבוא מפתח מ... + + + + Import key + יבוא מפתח + + + + Encrypt or decrypt File + הצפנת או פענוח קובץ + + + + File.. + קובץ.. + + + + Ready + מוכן + + + + Encrypt for: + להצפין עבור: + + + + Attached files: + קבצים מצורפים: + + + + About + אודות + + + + <center>This application allows simple encryption <br>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Viriato/Phol (es), <br>Serse (it), Russell (my),<br>Alessandro (pt_br), Kirill (ru), Tom (vi)<br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. + <center>תוכנה זו מאפשרת הצפנה ופענוח <br>פשוטים של הודעות טקסט וקבצים.<br>היא מופצת תחת רישיון GPL v3<br><br><b>מפתחים:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>תרגום:</b><br>Viriato/Phol (es), <br>Serse (it), Russell (my),<br>Alessandro (pt_br), Kirill (ru),<br>Tom (vi), Elad (he) <br><br>אם יש לך הצעות או שאלות ממולץ להציץ<br/>בדף <a href="http://gpg4usb.cpunk.de/contact.php">יצירת הקשר</a> שלנו או לשלוח מייל <br/> לרשימת התפוצה שלנו <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. + + + + <br><br> Built with Qt + <br><br>נבנה בעזרת Qt + + + + and GPGME + ו- GPGME + + + + There is one unencrypted file in attachment folder + יש קובץ לא מוצפן בספריית הקבצים המצורפים + + + + There are + יש + + + + unencrypted files in attachment folder + קבצים לא מוצפנים בספריית הקבצים המצורפים + + + + MimeTab + + + Decode quoted printable + פענוח ציטוטים + + + + Try to recognize quoted printable. + נסה לזהות ציטוטים. + + + + Parse PGP/MIME (Experimental) + פרוק PGP/MIME (ניסויני) + + + + Try to split attachments from PGP-MIME ecrypted messages. + נסה לחלץ מידע מצורף מהודעות מוצפנות מסוג PGP-MIME. + + + + Open with external application (Experimental) + לפתוח בעזרת יישום חיצוני (ניסיוני) + + + + Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol> + לפתוח קבצים מצורפים בעזרת יישום ברירת המחדל לסוג זה של קובץ.<br> ישנן לפחות שתי בעיות אפשריות בהתנהגות זו:<ol><li>יש לשמור את הקובץ המפוענח לספריית הקבצים המצורפים.<br> זו העבודה שלך לנקות ספרייה זו.</li><li>ליישום החיצוני עשויים להיות קבצים זמניים.</li></ol> + + + + Enable opening with external applications. + לפתוח בעזרת יישומים חיצוניים. + + + + QuitDialog + + + Unsaved files + קבצים שלא נשמרו + + + + <h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3> + <h3>%1 קבצים מכילים מידע שלא נשמר.<br/>לשמור לפני הסגירה?</h3> + + + + Check the files you want to save: + יש לסמן את הקבצים שברצונך לשמור: + + + + <b>Note:</b> If you don't save these files, all changes are lost.<br/> + <b>זהירות:</b> אי שמירה של קבצים אלו תביא לאובדן המידע.<br/> + + + + SettingsDialog + + + General + כללי + + + + Appearance + תצוגה + + + + PGP/Mime + PGP/MIME + + + + Keyserver + שרת מפתחות + + + + Advanced + מתקדם + + + + Settings + הגדות + + + + System Default + ברירת המחדל של המערכת + + + + TextEdit + + + untitled + untitled + + + + Open file + פתיחת קובץ + + + + + Application + יישום + + + + + Cannot read file %1: +%2. + לא ניתן לקרוא את הקובץ %1: +%2. + + + + File + קובץ + + + + Cannot write file %1: +%2. + לא ניתן לכתוב את הקובץ %1: +%2. + + + + Save file + שמירת קובץ + + + + Unsaved document + קובץ לא שמור + + + + <h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3> + <h3>המסמך "%1" שונה.<br/>האם ברצונך לשמור את השינויים?</h3> + + + + <b>Note:</b> If you don't save these files, all changes are lost.<br/> + <b>זהירות:</b> במידה והקובץ לא יישמר, כל השינויים יאבדו.<br/> + + + + VerifyDetailsDialog + + + Signaturedetails + נתוני חתימה + + + + Error Validating signature + שגיאה באימות החתימה + + + + Text was completely signed on + %1 by: + + כל הטקסט נחתם ב- + %1 על-ידי: + + + + + Text was partially signed on + %1 by: + + חלק מהטקסט נחתם ב- + %1 על-ידי: + + + + + VerifyKeyDetailBox + + + Import from keyserver + ליבא משרת מפתחות + + + + + + Status: + מצב: + + + + + Fingerprint: + טביעת אצבע: + + + + Key not present in keylist + המפתח לא נמצא ברשימת המפתחות + + + + Key not present with id 0x + המפתח לא נמצא עם מזהה 0x + + + + + Name: + שם: + + + + + EMail: + דוא"ל: + + + + OK + בסדר + + + + Error for key with id 0x + שגיאה עבור מפתח עם מזהה 0x + + + + VerifyNotification + + + Import missing key from Keyserver + ליבא מפתח חסר משרת מפתחות + + + + Show detailed verify information + להציג מידע מפורט לאימות + + + + Details + נתונים + + + + Key not present with id 0x + מפתח לא נמצא עם מזהה 0x + + + + Error validating signature by: + שגיאה באימות חתימה על-ידי: + + + + Text was completely signed by: + כל הטקסט נחתם על-ידי: + + + + Text was partially signed by: + חלק מהתקסט נחתם על-ידי: + + + + Error for key with fingerprint + שגיאה עבור מפתח עם טביעת האצבע + + + + Wizard + + + First Start Wizard + באיתחול הפעל את האשף + + + + Import Error + שגיאת יבוא + + + + Couldn't locate any keyring file in %1 + לא מצאתי את קובץ טבעת המפתחות ב- %1 + + + + + Import error + שגיאת יבוא + + + + Couldn't open private keyringfile: %1 + לא ניתן לפתוח את קובץ טבעת המפתחות הפרטיים: %1 + + + + Couldn't open public keyringfile: %1 + לא ניתן לפתוח את קובץ טבעת המפתחות הציבוריים: %1 + + + diff --git a/release/ts/gpg4usb_my.ts b/release/ts/gpg4usb_my.ts index 1f29646..1ff72c0 100644 --- a/release/ts/gpg4usb_my.ts +++ b/release/ts/gpg4usb_my.ts @@ -116,10 +116,6 @@ %2. - - Cannot write file %1: %2. - ဖိုင် %1: %2 ကို ရေးလို့မရပါ။ - ChoosePage @@ -211,10 +207,6 @@ Action လုပ်ဆောင်ချက် - - ... - ... - Decrypt File @@ -266,14 +258,6 @@ %2. - - couldn't open file: - ဖိုင်ကို ဖွင့်လို့ မရပါ - - - - Cannot write file %1: %2. - ဖိုင် %1: %2 ကို ရေးလို့ မရပါ။ - File exists! Do you want to overwrite it? @@ -317,49 +301,6 @@ Language ဘာသာစကား - - Language change is applied after restarting program. - ဘာသာစကား အ​ပြောင်းအလဲကို ပရိုဂရမ် ပြန်ဖွင့်တဲ့အခါ အတည်ပြုသွားမှာ ဖြစ်တယ်။ - - - System Default - နည်းစနစ် သတ်မှတ်ချက် - - - - GpgME::Context - - No Key Selected - ကီး ရွေးချယ်မထားပါ - - - Unsupported algorithm - ပံ့ပိုးမထားတဲ့ အယ်လဂိုရီသမ် - - - Error decrypting: - စာဝှက်ဖြည်နေစဉ် အမှားအယွင်း ဖြစ်ပေါ်နေတယ် - - - - Wrong password - စကားဝှက် မှားနေတယ် - - - Enter Password - စကားဝှက်ကို ရေးထည့်ရန် - - - Key Selection - ကီး ရွေးချယ်မှု - - - No Private Key Selected - Private ကီး ရွေးချယ်မထားပါ - - - Error signing: - လက်မှတ်ရေးထိုးနေစဉ် အမှားအယွင်း ဖြစ်ပေါ်နေတယ် - - GpgME::GpgContext @@ -414,333 +355,6 @@ လက်မှတ်ရေးထိုးနေစဉ် အမှားအယွင်း ဖြစ်ပေါ်နေတယ် - - - GpgWin - - &Open... - ဖွင့်ရန်... - - - Open an existing file - ရှိပြီးသား ဖိုင်ကို ဖွင့်ရန် - - - &Save - သိမ်းဆည်းရန် - - - Save the current File - လက်ရှိ ဖိုင်ကို သိမ်းဆည်းရန် - - - Save &As - သိမ်းဆည်းမဲ့ ပုံစံ - - - Save the current File as... - လက်ရှိ ဖိုင်ကို သိမ်းဆည်းမဲ့ ပုံစံ... - - - &Print - ပရင့်ထုတ်ရန် - - - Print Document - မှတ်တမ်းမှတ်ရာကို ပရင့်ထုတ်ရန် - - - &Close - ပိတ်ရန် - - - Close file - ဖိုင်ကို ပိတ်ရန် - - - &Quit - ပိတ်ရန် - - - Quit Program - ပရိုဂရမ်ကို ပိတ်ရန် - - - &Undo - ပြန်ပြင်ရန် - - - Undo Last Edit Action - နောက်ဆုံး တည်းဖြတ်မှုကို ပြန်ပြင်ရန် - - - &Redo - ပြန်​ဖြည်ရန် - - - Redo Last Edit Action - နောက်ဆုံး လုပ်ဆောင်ချက်ကို ပြန်ဖြည်ရန် - - - &Paste - ပွားရန် - - - Paste Text From Clipboard - Clipboard ထဲက စာသားကို ပွားရန် - - - Cu&t - ဖြတ်ထုတ်ရန် - - - Cut the current selection's contents to the clipboard - လက်ရှိ ရွေးချယ်ထားတဲ့ အကြောင်းအရာကို clipboard ထဲကို ဖြတ်ယူရန် - - - &Copy - ကော်ပီကူးရန် - - - Copy the current selection's contents to the clipboard - လက်ရှိ ရွေးချယ်ထားတဲ့ အကြောင်းအရာများကို clipboard ထဲ ကော်ပီကူးရန် - - - &Quote - ကိုးကားရန် - - - Quote whole text - စာသား တခုလုံးကို ကိုးကားရန် - - - Select &All - အားလုံးကို ရွေးချယ်ရန် - - - Select the whole text - စာသား တခုလုံးကို ရွေးချယ်ရန် - - - Remove double &Linebreaks - နှစ်ထပ် မျဉ်းကြောင်းကို ဖယ်ရှားရန် - - - Remove double linebreaks, e.g. in pasted text from webmailer - နှစ်ထပ် မျဉ်းကြောင်းကို ဖယ်ရှားရန်၊ ဥပမာ - webmailer ကနေ ပွားယူလိုက်တဲ့ စာသားထဲမှ - - - Open settings dialog - settings dialog ကို ဖွင့်ရန် - - - &Encrypt - စာဝှက်ရန် - - - Encrypt Message - ပေးစာကို စာဝှက်ရန် - - - &Decrypt - စာဝှက်ဖြည်ရန် - - - Decrypt Message - ပေးစာကို စာဝှက်ဖြည်ရန် - - - &File Encryption - ဖိုင်ကို စာဝှက်ခြင်း - - - Encrypt/Decrypt File - ဖိုင်ကို စာဝှက်ရန်/စာဝှက်ဖြည်ရန် - - - &Sign - လက်မှတ်ရေးထိုးရန် - - - Sign Message - ပေးစာကို လက်မှတ်ရေးထိုးရန် - - - &Verify - အတည်ပြုရန် - - - Verify Message - ပေးစာကို အတည်ပြုရန် - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>ဒီလုပ်ငန်းသုံး ဆော့ဗ်ဝဲကို အသုံးပြုပြီး ပေးစာများ (သို့) ဖိုင်များကို <br/>ရိုးရိုး စာဝှက်ပေးခြင်းနဲ့၊ စာဝှက်​ဖြည်ခြင်း ပြုလုပ်နိုင်တယ်။<br>၄င်းကို GPL v3 အောက်မှာ လိုင်စင် ပြုလုပ်ထားတယ်။<br><br><b>ဖန်တီး လုပ်ဆောင်သူများ -</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>ဘာသာပြန်ဆိုခြင်း -</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>အကယ်လို့ သင့်မှာ မေးစရာ မေးခွန်များ (သို့) အကြံပြုချက်များ ရှိရင်<br/>ကျွန်ုပ်တို့ရဲ့ <a href="http://gpg4usb.cpunk.de/contact.php">ဆက်သွယ်ရန် စာမျက်နှာ</a> ကို သွားရောက်နိုင်တယ် <br/> (သို့) ကျွန်ုပ်တို့ရဲ့ အီးမေးလ် အုပ်စု<a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>ကို ​စာ​ ရေးသားပေးပို့နိုင်တယ်။ - - - &Keyserver - ကီးဆာဗာ - - - Import New Key From Editor - ကီး အသစ်ကို အယ်ဒီတာကနေ တင်သွင်းရန် - - - Key Management - ကီး စီမံခန့်ခွဲရေး - - - Open Keymanagement - Keymanagement ကို ဖွင့်ရန် - - - Open Import New Key Dialog - Import New Key Dialog ကို ဖွင့်ရန် - - - &About - အကြောင်းအရာ - - - Show the application's About box - ဒီလုပ်ငန်းသုံး ဆော့ဗ်ဝဲရဲ့ အကြောင်းအရာ ဇယားကို ဖေါ်ပြရန် - - - &File - ဖိုင် - - - &Edit - တည်းဖြတ်ရန် - - - &Help - အကူအညီ - - - Append Selected Key(s) To Text - ရွေးချယ်ထားတဲ့ ကီး(များ)ကို စာသားနဲ့ ပူးတွဲပေးရန် - - - Se&ttings - ချိန်ညှိချက်များ - - - &New - အသစ် - - - Open a new file - ဖိုင်အသစ် ဖွင့်ရန် - - - Online &Tutorial - အွန်လိုင်း သင်တန်းလမ်းညွှန် - - - Open Online Tutorial - အွန်လိုင်း သင်တန်းလမ်းညွှန်ကို ဖွင့်ရန် - - - Translate gpg4usb - gpg4usb ကို ဘာသာပြန်ဆိုရန် - - - Translate gpg4usb yourself - gpg4usb ကို ကိုယ်တိုင် ဘာသာပြန်ဆိုရန် - - - Append The Selected Keys To Text in Editor - ရွေးချယ်ထားတဲ့ ကီးများကို အယ်ဒီတာထဲမှာ စာသားနဲ့ ပူးတွဲပေးရန် - - - Copy EMail-address - အီးမေးလ် လိပ်စာကို ကော်ပီကူးရန် - - - Copy selected EMailaddress to clipboard - အီးမေးလ် လိပ်စာကို clipboard မှာ ကော်ပီကူးရန် - - - Show Keydetails - ကီးအကြောင်း အသေးစိတ်ကို ဖေါ်ပြရန် - - - Show Details for this Key - ဒီကီးအကြောင်း အသေးစိတ်ကို ဖေါ်ပြရန် - - - &Keys - ကီး - - - &Import Key From... - ကီးကို တင်သွင်းရမဲ့ နေရာ... - - - &View - ကြည့်ရှုရန် - - - Ready - အဆင်သင့် - - - Encrypt for: - စာဝှက်မဲ့အချက် - - - - Attached files: - ပူးတွဲထားတဲ့ ဖိုင်များ - - - - There is one unencrypted file in attachment folder - ပူးတွဲထားတဲ့ ဖိုင်ထဲမှာ စာဝှက်မထားတဲ့ ဖိုင်တခု ရှိတယ် - - - There are - ပါ၀င်တဲ့အချက် - - - unencrypted files in attachment folder - ပူးတွဲထားတဲ့ ဖိုင်တွဲထဲက စာဝှက်မထားတဲ့ ဖိုင်များ - - - &Editor - အယ်ဒီတာ - - - &Clipboard - &Clipboard - - - Import Key - ကီးကို တင်သွင်းရန် - - - &Crypt - စာဝှက်ရန် - - - Crypt - စာဝှက်ရန် - - - Key - ကီး - - - Edit - တည်းဖြတ်ရန် - - - About - အကြောင်းအရာ - - - Import Key From... - ကီးကို တင်သွင်းရမဲ့ နေရာ... - - ImportFromGnupgPage @@ -922,18 +536,6 @@ Couldn't open %1 for writing - - Expires on: - သက်တမ်း ကုန်ဆုံးချိန် - - - - Created on: - ဖန်တီးတဲ့ နေ့စွဲ - - - - Key ID: - ကီး ID - - Warning: Key expired @@ -966,19 +568,11 @@ Make sure you keep it save.Do you really want to export your private key?Key size: ကီး အရွယ်အစား - - - Algorithm: - ဘယ်လဂိုရီသမ် - - Never လုံး၀ - - / Never - / လုံး၀ - Private Key @@ -994,10 +588,6 @@ Make sure you keep it save.Do you really want to export your private key?Exporting private Key Private ကီးကို တင်ပို့နေတယ် - - You are about to export your private key. This is NOT your public key, so don't give it away. Make sure you keep it save. - သင်ဟာ သင့်ရဲ့ private ကီးကို တင်ပို့ဖို့ လုပ်ဆောင်နေတယ်။ ဒါဟာ သင့်ရဲ့ public ကီးမဟုတ်တဲ့အတွက်၊ ဒီတိုင်း ပစ်မထားပဲ၊ လုံလုံခြုံခြုံ သိမ်းဆည်းထားပါ။ - Export Key To File @@ -1262,19 +852,11 @@ Weak -> Strong Couldn't Open File: - - You've dropped something on the keylist. gpg4usb will now try to import key(s). - ကီးစာရင်းထဲမှာ သင် တစုံတခု ထည့်သွင်းထားတယ်။ အခု gpg4usb က ကီးတွေကို တင်သွင်းလာလိမ့်မယ်။ - Always import without bothering. အနှောင့်အယှက် မရှိပဲ အမြဲတမ်း တင်သွင်းရန်။ - - Couldn't Open File: - ဖိုင်ကို ဖွင့်လို့ မရပါ - - KeyMgmt @@ -1440,10 +1022,6 @@ Weak -> Strong Key Files ကီးဖိုင်များ - - Couldn't Open File: - ဖိုင်ကို ဖွင့်မရပါ - - Deleting Keys @@ -1464,62 +1042,6 @@ Weak -> Strong Export Key To File ကီးကို ဖိုင်အဖြစ် တင်ပို့ရန် - - Name: - နာမည် - - - - E-Mailaddress:: - အီးမေးလ် လိပ်စာ - - - - Comment: - မှတ်ချက် - - - - KeySize (in Bit): - ကီး အ​ရွယ်အစား (Bit) - - - - Expiration Date: - သက်တမ်း ကုန်ဆုံးချိန် - - - - Password: - စကားဝှက် - - - - Repeat Password: - စကားဝှက်ကို ထပ်ရေးရန် - - - - Never Expire - သက်တမ်း ကုန်ဆုံးချိန် မရှိ - - - Password: Strength Weak -> Strong - စကားဝှက် - ကြံ့ခိုင်မှု အားနည်း -> အားကောင်း - - - Password Strength - စကားဝှက်ရဲ့ ကြံ့ခိုင်မှု - - - Name must contain at least five characters. - နာမည်ထဲမှာ အနည်းဆုံး အက္ခရာစာလုံး ငါးလုံး ပါဝင်ရမယ်။ - - - Password and Repeat don't match. - စကားဝှက်နဲ့ ထပ်မံ ရေးသားချက် မကိုက်ညီပါ။ - - - Generating Key... - ကီး ထုတ်လုပ်ရန်... - - - Collecting random data for key generation. This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...) - ကီး ထုတ်လုပ်ဖို့ ကျပန်း ဒေတာများကို စုဆောင်းနေတယ်။ အချိန်အတော်ကြာ ယူနိုင်တယ်။ လုပ်ငန်းကို အရှိန်မြှင့်ဖို့ ကွန်ပျူတာ အသုံးပြုပါ (ဥပမာ - အင်တာနက်ကို သုံးပါ၊ တေးသီချင်းများ နား​ဆင်ပါ၊...) - KeyServerImportDialog @@ -1574,52 +1096,52 @@ Weak -> Strong - + Couldn't contact keyserver! ကီးဆာဗာကို ဆက်သွယ်လို့ မရပါ။ - + Too many responses from keyserver! ကီးဆာဗာဆီရဲ့ တုံ့ပြန်ချက် အလွန်များပြားနေတယ်။ - + No keys found, input may be kexId, retrying search with 0x. ကီး မတွေ့ရှိပါ၊ ဖြည့်သွင်းချက်ဟာ kexId ဖြစ်နေနိုင်တယ်၊ 0x ကို အသုံးပြုပြီး ထပ်မံရှာဖွေပါ။ - + No keys found containing the search string! ရှာဖွေနေတဲ့ အက္ခရာစာလုံး ပါတဲ့ ကီးကို မတွေ့ရှိပါ။ - + Insufficiently specific search string! ပြည့်စုံမှု မရှိတဲ့ ရှာဖွေရေး အက္ခရာစာလုံး။ - + revoked - + disabled - + %1 keys found. Doubleclick a key to import it. ကီး %1 ခုကို တွေ့ရှိရတယ်။ သူ့ကို တင်သွင်းဖို့ ကီးတခုကို နှစ်ချက် နှိပ်ပါ။ - + Error while contacting keyserver! ကီး​ဆာဗာကို ဆက်သွယ်နေစဉ် အမှားအယွင်း ဖြစ်ပေါ်နေတယ်။ - + Key imported တင်သွင်းလိုက်တဲ့ ကီး @@ -2184,11 +1706,6 @@ Weak -> Strong SettingsDialog - - English - Insert local name of language here. This is used for the language menu of the settingsdialog - English - General @@ -2224,10 +1741,6 @@ Weak -> Strong System Default နည်းစနစ် သတ်မှတ်ချက် - - English - အင်္ဂလိပ် (My) - TextEdit @@ -2265,23 +1778,11 @@ Weak -> Strong Save file - - Cannot read file %1: %2. - ဖိုင် %1: %2 ကို ဖတ်လို့ မရဘူး။ - File ဖုိင် - - Cannot write file %1: %2. - ဖိုင် %1: %2 ကို ရေးလို့ မရဘူး။ - - - Save file - ဖိုင်ကို သိမ်းဆည်းရန် - Unsaved document @@ -2324,14 +1825,6 @@ Weak -> Strong - - Text was completely signed on %1 by: - စသားကို %1 မှာ အပြည့်အစုံ လက်မှတ်ရေးထိုးပေးတဲ့သူ - - - - Text was partially signed on %1 by: - စာသားကို %1 တပိုင်းတစနဲ့ လက်မှတ်ရေးထိုးပေးသူ - - VerifyKeyDetailBox @@ -2428,22 +1921,6 @@ Weak -> Strong Text was partially signed by: - - Error validating signature by: - လက်မှတ် အတည်ပြုမှု အမှားအယွင်းကို ဖန်တီးသူ - - - - Text was completely signed by: - စာသားကို အပြည့်အစုံ လက်မှတ်ရေးထိုးသူ - - - - Text was partially signed by: - စာသားကို တပိုင်းတစနဲ့ လက်မှတ်ရေးထိုးသူ - - - - Error for key with fingerprint - လက်ဗွေပါတဲ့ ကီးရဲ့ မှားယွင်းချက် - Wizard diff --git a/release/ts/gpg4usb_pt_BR.ts b/release/ts/gpg4usb_pt_BR.ts index 565a208..dad2783 100644 --- a/release/ts/gpg4usb_pt_BR.ts +++ b/release/ts/gpg4usb_pt_BR.ts @@ -163,14 +163,6 @@ ConclusionPage - - Finish Start Wizard - Terminar o Auxiliar de Primeiro Uso - - - You're ready to encrypt and decrpt now. - Agora você está preparado para encriptar e decriptar. - Ready. @@ -216,10 +208,6 @@ Action Ação - - ... - ... - Decrypt File @@ -265,23 +253,11 @@ File exists! Do you want to overwrite it? O arquivo existe! Deseja sobreescrever? - - Files - Arquivos - - - All Files (*) - Todos os Arquivos (*) - Save File Salvar Arquivo - - couldn't open file: - não pode abrir o arquivo: - Cannot write file %1: @@ -327,49 +303,6 @@ Language Idioma - - Language change is applied after restarting program. - A alteração de idioma será aplicada após reiniciar o programa. - - - System Default - Padrão do Sistema - - - - GpgME::Context - - No Key Selected - Chave Não Selecionada - - - Unsupported algorithm - Algorítmo não suportado - - - Error decrypting: - Erro ao decriptar: - - - Wrong password - Senha errada - - - Enter Password - Insira a Senha - - - Key Selection - Seleção de chave - - - No Private Key Selected - Chave privada não selecionada - - - Error signing: - Erro durante assinatura: - GpgME::GpgContext @@ -424,462 +357,6 @@ Erro ao assinar: - - GpgWin - - &Open... - &Abrir... - - - Ctrl+O - Ctrl+A - - - Open an existing file - Abrir um arquivo existente - - - &Save - &Salvar - - - Ctrl+S - Ctrl+S - - - Save the current File - Salvar o arquivo atual - - - Save &As - Salvar Co&mo - - - Ctrl+A - Ctrl+M - - - Save the current File as... - Salvar o arquivo atual como... - - - &Print - &Imprimir - - - Ctrl+P - Ctrl+I - - - Print Document - Imprimir Documento - - - &Quit - Sai&r - - - Ctrl+Q - Ctrl+R - - - Quit Program - Sair - - - &Paste - i used this without accelerator & to avoid confusion with windows native paste (ctrl+v) - &Colar - - - Ctrl+V - Ctrl+V - - - Paste Text From Clipboard - Colar Texto da Área de Transferência - - - Cu&t - i used this without accelerator & to avoid confusion with native windows cut ctrl+x - &Recortar - - - Ctrl+X - Ctrl+X - - - Cut the current selection's contents to the clipboard - Recortar a seleção atual para a Área de Transferência - - - &Copy - &Copiar - - - Ctrl+C - Ctrl+C - - - Copy the current selection's contents to the clipboard - Copiar a seleção para a área de transferência - - - Select &All - Selecionar &Tudo - - - Select the whole text - Selecionar todo texto - - - Se&ttings - Con&figurações - - - Open settings dialog - Abrir janela de configurações - - - &Encrypt - &Encriptar - - - Ctrl+E - Ctrl+E - - - Encrypt Message - Encriptar Mensagem - - - &Decrypt - &Decriptar - - - Ctrl+D - Ctrl+D - - - Decrypt Message - Decriptar Mensagem - - - &File Encryption - Encriptar &Arquivo - - - Encrypt/Decrypt File - Encriptar/Decriptar Arquivo - - - Import New Key From File - Importar Nova Chave do Arquivo - - - Import New Key From Editor - Importar Nova Chave do Editor - - - Key Management - Gerenciador de Chaves - - - Open Keymanagement - Abrir Gerenciador de Chaves - - - Open Import New Key Dialog - Abrir Diálogo de Importação de Nova Chave - - - &About - &Sobre - - - Show the application's About box - Exibe a janela 'sobre' - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Esse programa serve para encriptar e<br>decriptar mensagens de texto ou arquivos.<br>E é liberado sob a licença GPL v2.0<br><br><b>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru)<br><br>Caso tenha dúvidas e/ou sugestões,<br>envie uma mensagem para<br>gpg4usb at cpunk.de</a><br><br>ou nos encontre no nosso canal xmpp:<br>gpg4usb at conference.jabber.ccc.de</center> - - - &File - &Arquivo - - - &Edit - E&ditar - - - &Help - A&juda - - - File - Arquivo - - - Edit - Editar - - - &Undo - &Desfazer - - - &New - &Novo - - - Open a new file - Abrir um novo arquivo - - - &Close - &Fechar - - - Close file - Fechar o arquivo - - - Undo Last Edit Action - Desfazer Última Edição - - - &Redo - &Repetir - - - Redo Last Edit Action - Repete a última ação de edição - - - &Quote - &Destacar - - - Quote whole text - Destacar todo o texto - - - Remove double &Linebreaks - Remover quebras de linha &duplicadas - - - Remove double linebreaks, e.g. in pasted text from webmailer - Remover quebras de linha duplicadas, como ocorre quando colamos o texto do webmail - - - &Sign - &Assinar - - - Sign Message - Assinar Mensagem - - - &Verify - &Verificar - - - Verify Message - Verificar a Mensagem - - - Online &Tutorial - &Tutorial Online - - - Open Online Tutorial - Abrir Tutorial Online - - - Translate gpg4usb - Traduzir gpg4usb - - - Translate gpg4usb yourself - Traduza o gpg4usb você mesmo - - - Append Selected Key(s) To Text - Anexar Chaves Marcadas no Texto - - - Append The Selected Keys To Text in Editor - Anexar Chaves Marcadas ao Texto do Editor - - - Copy EMail-address - Copiar o endereço de EMail - - - Copy selected EMailaddress to clipboard - Copiar o endereço de EMail selecionado para a área de transferência - - - Show Keydetails - Exibir detalhes da chave - - - Show Details for this Key - Exibir Detalhes da Chave - - - &Keys - &Chaves - - - &Import Key From... - &Importar Chave de... - - - &View - E&xibir - - - Key - Chave - - - Ready - Pronto - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Esse programa permite a encriptação e decriptação<br>simplificada de mensagens de texto ou arquivos.<br>E é liberado sob a licença GPL v3<br><br><b>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom(vi) <br><br>Caso tenha alguma dúvida ou sugestão dê uma olhada <br/>na nossa <a href="http://gpg4usb.cpunk.de/contact.php">página de contato</a> ou envie um email<br/> para <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Keyserver - &Servidor de Chaves - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Esse programa permite a encriptação e decriptação<br>simplificada de mensagens de texto ou arquivos.<br>E é liberado sob a licença GPL v2.0<br><br><b>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it)<br><br>Caso tenha alguma dúvida ou sugestão dê uma olhada <br/>na nossa <a href="http://gpg4usb.cpunk.de/contact.php">página de contato</a> ou envie um email<br/> para <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Esse programa serve para encriptar e<br>decriptar mensagens de texto ou arquivos.<br>E é liberado sob a licença GPL v2.0<br><br><b>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es), Serse (it)<br><br>Caso tenha dúvidas e/ou sugestões,<br>envie uma mensagem para<br>gpg4usb at cpunk.de</a><br><br>ou nos encontre no nosso canal xmpp:<br>gpg4usb at conference.jabber.ccc.de</center> - - - There is one unencrypted file in attachment folder - Há um arquivo não decriptado na pasta de anexos - - - There are - Existem - - - unencrypted files in attachment folder - arquivos não decriptados na pasta de anexos - - - Encrypt for: - Encriptar para: - - - Attached files: - Arquivos anexos: - - - Application - Aplicação - - - Cannot read file %1: -%2. - Não leu o arquivo %1: -%2. - - - File loaded - Arquivo carregado - - - %1[*] - %2 - %1[*] - %2 - - - The document has been modified. -Do you want to save your changes? - O documento foi alterado. -Deseja salvar as alterações? - - - Cannot write file %1: -%2. - Não escreveu o arquivo %1: -%2. - - - Saved '%1' - i used inverse order because its more natural speak in this way - '%1' salvo - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Kirill (ru)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center> Este aplicativo permite a encriptação/decriptação<br>simplificada das suas mensagens de texto ou arquivos.<br>E é liberado sob licença GPL-V2.0<br><br>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Krill(ru)<br>Alessandro Benevenuto (pt-br)<br><br>Caso tenha dúvidas e/ou sugestões, entre em<br>contatoatravés de gpg4usb at cpunk.de</a><br><br>ou no canal xmpp<br>gpg4usb at conference.jabber.ccc.de</center> - - - Open Key - Abrir a Chave - - - Key Files - Arquivos de Chaves - - - All Files - Todos os Arquivos - - - couldn't open file: - Não pode abrir o arquivo: - - - &Editor - &Editor - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Esse programa permite a encriptação e decriptação<br>simplificada de mensagens de texto ou arquivos.<br>E é liberado sob a licença GPL v2.0<br><br><b>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it)<br><br>Caso tenha alguma dúvida ou sugestão dê uma olhada <br/>na nossa <a href="http://gpg4usb.cpunk.de/contact.php">página de contato</a> ou envie um email<br/> para <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. {3<?} {4u?} {4u?} {4u?} - - - &Clipboard - Área de &Transferência - - - Import New Key From Clipboard - Importar Nova Chave da Área de Transferência - - - Import Key - Importar Chave - - - &Crypt - &Encriptar - - - Crypt - Encriptar - - - About - Sobre - - - <center>This Application allows you to do simple<br>encryption/decryption of your text-message or file.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es)<br><br>If you have any questions and/or<br>suggestions, contact us at<br>gpg4usb at cpunk.de</a><br><br>or feel free to meet us in our xmpp-channel:<br>gpg4usb at conference.jabber.ccc.de</center> - <center>Esse programa serve para encriptar e<br>decriptar mensagens de texto ou arquivos.<br>E é liberado sob a licença GPL V2.0<br><br><b>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Alessandro (pt_br), Alex (fr), Kirill (ru), Viriato (es)<br><br>Caso tenha duvidas e/ou sugestões,<br>envie uma mensagem para<br>gpg4usb at cpunk.de</a><br><br>ou nos encontre no nosso canal xmppl:<br>gpg4usb at conference.jabber.ccc.de</center> - - - Import Key From... - Importar Chave de... - - ImportFromGnupgPage @@ -963,14 +440,6 @@ Deseja salvar as alterações? IntroPage - - Introduction - Introdução - - - This wizard will help you getting started with encrypting and decrypting. - Esse auxiliar ajudará você a começar a encriptar e decriptar. - Getting started... @@ -1088,10 +557,6 @@ Tenha certeza de mantê-la segura. Você realmente deseja exportar sua chave pri Couldn't open %1 for writing Não pode abrir %1 para escrita - - Key Files - Arquivos de Chaves - Key size: @@ -1127,14 +592,6 @@ Tenha certeza de mantê-la segura. Você realmente deseja exportar sua chave pri Exporting private Key Exportando Chave Privada - - You are about to export your private key. -This is NOT your public key, so don't give it away. -Make sure you keep it save. - Você está prestes a exportar sua chave privada. -Essa NÃO é sua chave pública, portanto NÃO a distribua. -Guarde-a em segurança. - Export Key To File @@ -1153,10 +610,6 @@ Guarde-a em segurança. Name: Nome: - - E-Mailaddress:: - E-mail: - Comment: @@ -1245,14 +698,6 @@ Fraca -> Forte KeyGenPage - - Key-Generating - Gerando a Chave - - - First you've got to create an own key. - Primeiro você precisa criar sua própria chave. - Create a keypair... @@ -1278,10 +723,6 @@ Fraca -> Forte Create New Key Criar Nova Chave - - key generated. Now you can crypt and sign texts. - Chave gerada. Agora você pode encriptar e assinar textos. - KeyImportDetailDialog @@ -1450,19 +891,11 @@ gpg4usb tentará importar a(s) chave(s). Close Key Management Fechar Gerenciador de Chaves - - Import From &File - Importar do &Arquivo - Import New Key From File Importar Nova Chave do Arquivo - - Import From &Clipboard - Importar da Área de &Transferência - Import New Key From Clipboard @@ -1579,10 +1012,6 @@ gpg4usb tentará importar a(s) chave(s). &Key &Chave - - Crypt - Encriptar - Open Key @@ -1619,83 +1048,11 @@ gpg4usb tentará importar a(s) chave(s). <br/>The action can not be undone. <br/>Essa ação não poderá ser desfeita. - - Are you sure that you want to delete the selected keys?. -The action can not be undone. - Tem certeza que deseja excluir as chaves marcadas? -A ação não poderá ser desfeita. - Export Key To File Exportar Chave para Arquivo - - Name: - Nome: - - - E-Mailaddress:: - E-mail: - - - Comment: - Comentários: - - - KeySize (in Bit): - Tamanho da Chave (bits): - - - Expiration Date: - Data de expiração: - - - Password: - Senha: - - - Repeat Password: - Repetir a Senha: - - - Never Expire - Nunca Expira - - - Password: Strength -Weak -> Strong - Senha: Resistência: -Fraca -> Forte - - - Password Strength - Resistência da Senha - - - Name must contain at least five characters. - - O nome deve conter pelo menos cinco caracteres. - - - - Password and Repeat don't match. - As senhas não conferem. - - - Generating Key... - Gerando as Chaves... - - - Collecting random data for key generation. - This may take a while. - To speed up the process use your computer - (e.g. browse the net, listen to music,...) - Coletando dados aleatórios para a geração da chave. - Isso pode demorar um pouco. - Para agilizar o processo use seu computador - (ex: navegue na internet, ouça música,...) - KeyServerImportDialog @@ -1750,52 +1107,52 @@ Fraca -> Forte Tag - + Couldn't contact keyserver! Não foi possivel acessar o servidor de chaves! - + Too many responses from keyserver! Muitas respostas do Servidor de Chaves! - + No keys found, input may be kexId, retrying search with 0x. Não foram localizadas chaves, a entrada deve ser kexID, tente uma nova pesquisa com 0x. - + No keys found containing the search string! Não foram encontradas chaves com o texto da pesquisa! - + Insufficiently specific search string! Texto da pesquisa insuficiente! - + revoked revogado - + disabled desabilitado - + %1 keys found. Doubleclick a key to import it. %1 chaves encontradas. Dê um duplo clique na chave para importá-la. - + Error while contacting keyserver! Erro durante a conexão com o servidor de chaves! - + Key imported Chave importada @@ -2026,10 +1383,6 @@ Fraca -> Forte and GPGME e GPGME - - Remove double &Linebreaks - Remover quebras de linha &duplicadas - Remove double linebreaks, e.g. in pasted text from webmailer @@ -2125,23 +1478,11 @@ Fraca -> Forte Import New Key From Editor Importar Nova Chave do Editor - - Key Management - Gerenciador de Chaves - Open Keymanagement Abrir Gerenciador de Chaves - - Import Key - Importar Chave - - - Open Import New Key Dialog - Abrir Diálogo de Importação de Nova Chave - &About @@ -2152,14 +1493,6 @@ Fraca -> Forte Show the application's About box Exibe a janela 'sobre' - - Online &Tutorial - &Tutorial Online - - - Open Online Tutorial - Abrir Tutorial Online - Translate gpg4usb @@ -2305,10 +1638,6 @@ Fraca -> Forte About Sobre - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Esse programa permite a encriptação e decriptação<br>simplificada de mensagens de texto ou arquivos.<br>E é liberado sob a licença GPL v3<br><br><b>Desenvolvedores:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Tradução:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it)<br><br>Caso tenha alguma dúvida ou sugestão dê uma olhada <br/>na nossa <a href="http://gpg4usb.cpunk.de/contact.php">página de contato</a> ou envie um email<br/> para <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - There is one unencrypted file in attachment folder @@ -2324,18 +1653,6 @@ Fraca -> Forte unencrypted files in attachment folder arquivos não decriptados na pasta de anexos - - Import Key From... - Importar Chave de... - - - &Clipboard - Área de &Transferência - - - &Keyserver - &Servidor de Chaves - MimeTab @@ -2405,79 +1722,6 @@ Fraca -> Forte Settings Configurações - - Iconsize - Tamanho do ícone - - - small - pequeno - - - medium - médio - - - large - grande - - - Iconstyle - Estilo do ícone - - - just text - somente texto - - - just icons - somente ícones - - - text and icons - texto e ícones - - - Windowstate - Status da Janela - - - Save window size and position on exit. - Salvar tamanho e posição da janela na saída. - - - Save checked private keys on exit and restore them on next start. - Salvar chaves privadas selecionadas na saída e restaurá-las na proxima execução. - - - MIME-parsing (Experimental) - Análise-MIME (Experimental) - - - Try to split attachments from PGP-MIME ecrypted messages. - Tentar dividir os anexos das mensagens PGP-MIME encriptadas. - - - save window size and position on exit - Salvar posição e tamanho da janela ao sair - - - Save Checked Keys - Salvar chaves marcadas - - - Language - Idioma - - - Language change is applied after restarting program. - A alteração de idioma será aplicada após reiniciar o programa. - - - English - Insert local name of language here. This is used for the language menu of the settingsdialog - Português do Brasil - General @@ -2503,14 +1747,6 @@ Fraca -> Forte Advanced Avançado - - Tab Dialog - Configurações - - - English - Português do Brasil - System Default diff --git a/release/ts/gpg4usb_ru.qm b/release/ts/gpg4usb_ru.qm index 852ac46..37e916d 100644 Binary files a/release/ts/gpg4usb_ru.qm and b/release/ts/gpg4usb_ru.qm differ diff --git a/release/ts/gpg4usb_ru.ts b/release/ts/gpg4usb_ru.ts index a593b40..70d46b9 100644 --- a/release/ts/gpg4usb_ru.ts +++ b/release/ts/gpg4usb_ru.ts @@ -82,10 +82,6 @@ Attachments - - couldn't open file: - Не удалось открыть файл: - @@ -212,10 +208,6 @@ Action Действие - - ... - ... - Decrypt File @@ -261,23 +253,11 @@ File exists! Do you want to overwrite it? Такой файл уже существует. Перезаписать его? - - Files - Файлы - - - All Files (*) - Все файлы - Save File Сохранить файл - - couldn't open file: - Не удалось открыть файл: - Cannot write file %1: @@ -323,49 +303,6 @@ Language Язык - - Language change is applied after restarting program. - Изменение языка вступит в силу после перезапуска программы. - - - System Default - Стандартнай язык системы - - - - GpgME::Context - - No Key Selected - Не выбран Ключ - - - Unsupported algorithm - Неподдерживаемый алгоритмм - - - Error decrypting: - Ошибка расшифровки: - - - Wrong password - Неверный Пароль - - - Enter Password - Введите Пароль - - - Key Selection - Выбор Ключа - - - No Private Key Selected - Не выбран Секретный Ключ - - - Error signing: - Ошибка подписания: - GpgME::GpgContext @@ -394,6 +331,11 @@ Wrong password Неверный Пароль + + + Enter Password for + Ввести пароль для + Enter Password @@ -415,391 +357,6 @@ Ошибка подписания: - - GpgWin - - &Open... - &Открыть... - - - Open an existing file - Открать существующий файл - - - &Save - &Сохранить - - - Save the current File - Сохранить файл - - - Save &As - Сохранить &как - - - Save the current File as... - Сохранить файл как... - - - &Print - &Печать - - - Print Document - Печать - - - &Close - &Закрыть - - - Close file - Закрыть файл - - - &Quit - Вы&йти - - - Quit Program - Завершить программу - - - &Undo - &Отменить - - - Undo Last Edit Action - Отменить последнее действие - - - &Redo - &Вернуть отмену - - - Redo Last Edit Action - Вернуть последнее изменение - - - &Paste - &Вставить - - - Paste Text From Clipboard - Вставить текст из Буфера Обмена - - - Cu&t - &Вырезать - - - Cut the current selection's contents to the clipboard - Вырезать выделенные элементы в Буфер Обмена - - - &Copy - &Копировать - - - Copy the current selection's contents to the clipboard - Копировать выделенные элементы в Буфер Обмена - - - &Quote - &Цитировать - - - Quote whole text - Цитировать весь текст - - - Select &All - В&ыделить всё - - - Select the whole text - Выделить весь текст - - - Remove double &Linebreaks - Удалить двойной &перенос строк - - - Remove double linebreaks, e.g. in pasted text from webmailer - Удалить двойной перенос строк, например в тексте, вставленном из браузера - - - Open settings dialog - Открыть окно настроек - - - &Encrypt - З&ашифровать - - - Encrypt Message - Зашифровать текст - - - &Decrypt - Расшифро&вать - - - Decrypt Message - Расшифровать текст - - - &Sign - &Подписать - - - Sign Message - Подписать сообщение - - - &Verify - &Проверить - - - Verify Message - Проверить сообщение - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Keyserver - Сервера &ключей - - - Import New Key From File - Импорт нового ключа из файла - - - Import New Key From Editor - Импорт нового ключа из редактора - - - &About - &О программе - - - Show the application's About box - Показать инфо о программе - - - &File - Ф&айл - - - &Edit - &Правка - - - &Help - &Справка - - - File - Файл - - - Edit - Правка - - - Se&ttings - &Настройки - - - &New - &Создать - - - Open a new file - Открыть новый файл - - - &File Encryption - Шифрование &файлов - - - Encrypt/Decrypt File - Зашифровать/Расшифровать файл - - - Key Management - Менеджер ключей - - - Open Keymanagement - Открыть Менеджер ключей - - - Open Import New Key Dialog - Открыть окно импорта ключей - - - Online &Tutorial - Онлайн-&руководство - - - Open Online Tutorial - Открыть онлайн-руководство - - - Translate gpg4usb - Перевести gpg4usb - - - Translate gpg4usb yourself - Самостоятельно перевести gpg4usb - - - Append Selected Key(s) To Text - Добавить выбранн. ключ(и) к тексту - - - Append The Selected Keys To Text in Editor - Добавить выбранный ключ к тексту в редакторе - - - Copy EMail-address - Копировать адрес eMail - - - Copy selected EMailaddress to clipboard - Копировать выбранный адрес eMail в Буфер Обмена - - - Show Keydetails - Показать свойства ключа - - - Show Details for this Key - Показать детали для этого ключа - - - &Keys - &Ключи - - - &Import Key From... - &Импорт ключа из... - - - &View - &Вид - - - Key - Ключ - - - Ready - Готово - - - Encrypt for: - Зашифровать для: - - - Attached files: - Прикреплённые файлы: - - - Application - Приложение - - - Cannot read file %1: -%2. - Не удалось прочесть файл %1: -%2. - - - File loaded - Файл загружен - - - The document has been modified. -Do you want to save your changes? - Документ был редактирован. -Сохранить изменения? - - - Cannot write file %1: -%2. - Не удалось записать файл %1: -%2. - - - Saved '%1' - "%1" сохранён - - - Open Key - Открыть ключ - - - couldn't open file: - Не удалось открыть файл: - - - &Editor - Окна &редактора - - - &Clipboard - &Буфера Обмена - - - Import New Key From Clipboard - Импорт нового ключа из Буфера Обмена - - - Import Key - Импорт ключа - - - &Crypt - &Шифрование - - - Crypt - Шифрование - - - About - О программе - - - There is one unencrypted file in attachment folder - Имеется один незашифрованный файл в папке вложений - - - There are - Имеются - - - unencrypted files in attachment folder - незашифрованные файлы в папке вложений - - - Key Files - Файлы ключей - - - All Files - Все файлы - - - Import Key From... - Импорт ключа из... - - ImportFromGnupgPage @@ -1001,10 +558,6 @@ Make sure you keep it save.Do you really want to export your private key?Couldn't open %1 for writing Не удалось открыть %1 для записи - - Key Files - Файлы ключей - Key size: @@ -1040,14 +593,6 @@ Make sure you keep it save.Do you really want to export your private key?Exporting private Key Экспорт Секретного Ключа - - You are about to export your private key. -This is NOT your public key, so don't give it away. -Make sure you keep it save. - Вы собираетесь экспортировать свой Секретный ключ. -Это НЕ открытый ключ, так что не давайте его никому. -Убедитесь, что он хранится в Надёжном Месте. - Export Key To File @@ -1346,19 +891,11 @@ gpg4usb попробует импортировать ключ(и).Close Key Management Закрыть Менеджер ключей - - Import From &File - Импорт из ф&айла - Import New Key From File Импорт нового ключа из файла - - Import From &Clipboard - Импорт из &Буфера Обмена - Import New Key From Clipboard @@ -1475,10 +1012,6 @@ gpg4usb попробует импортировать ключ(и).&Key &Ключ - - Crypt - Шифрование - Open Key @@ -1515,83 +1048,11 @@ gpg4usb попробует импортировать ключ(и).<br/>The action can not be undone. <br/>Это действие нельзя будет отменить. - - Are you sure that you want to delete the selected keys?. -The action can not be undone. - Вы уверены, что хотите стереть выбранные ключи? -Это действие будет необратимым. - Export Key To File Экспорт ключа в файл - - Name: - Имя: - - - E-Mailaddress:: - Адрес eMail: - - - Comment: - Комментарий: - - - KeySize (in Bit): - Длина ключа (бит): - - - Expiration Date: - Истекает: - - - Password: - Пароль: - - - Repeat Password: - Повторите Пароль: - - - Never Expire - без срока годности - - - Password: Strength -Weak -> Strong - Надёжность Пароля -Слабый -> Стойкий - - - Password Strength - Надёжность Пароля - - - Name must contain at least five characters. - - Имя должно быть длиной не менее 5 букв. - - - - Password and Repeat don't match. - Повторно введённый Пароль не совпал. - - - Generating Key... - Генерация ключа... - - - Collecting random data for key generation. - This may take a while. - To speed up the process use your computer - (e.g. browse the net, listen to music,...) - Сбор случайных данных для генерации ключа. -Это займёт некоторое время. Можно ускорить -процесс, активно используя компьютер (листая -страницы интернета, слушая музыку и т.д.) - KeyServerImportDialog @@ -1646,52 +1107,52 @@ Weak -> Strong Тег - + Couldn't contact keyserver! Не удалось связаться с сервером ключей! - + Too many responses from keyserver! Слишком много ответов от сервера ключей! - + No keys found, input may be kexId, retrying search with 0x. Не найдено ключа, запрос может быть идентификатором ключа, повторяю поиск, подставив 0x. - + No keys found containing the search string! Не найдено Ключей, содержащих поисковый запрос! - + Insufficiently specific search string! Поисковый запрос сформулирован слишком неопределённо! - + revoked отозван - + disabled деактивирован - + %1 keys found. Doubleclick a key to import it. Найдено %1 ключей. Для импорта двойной клик по ключу. - + Error while contacting keyserver! Ошибка соединения с сервером ключей! - + Key imported Ключ импортирован @@ -2261,80 +1722,6 @@ Weak -> Strong Settings Настройки - - Iconsize - Размер значков - - - small - Маленький - - - medium - Средний - - - large - Большой - - - Iconstyle - Стиль панелей инструментов - - - just text - Только текст - - - just icons - Только значки - - - text and icons - Значки и текст - - - Windowstate - Настройки окна - - - Save window size and position on exit. - Запоминать размер и положение окна при выходе. - - - Save checked private keys on exit and restore them on next start. - Запоминать отмеченные ключи при выходе и выделять их при следующем запуске. - - - MIME-parsing (Experimental) - MIME-parsing (экспериментально) - - - Try to split attachments from PGP-MIME ecrypted messages. - Пробовать отделять вложения писем, зашифрованных PGP-MIME. - - - save window size and position on exit - Сохранять размер окна при выходе - - - Save Checked Keys - Сохранение выбора ключей - - - Language - Язык - - - Language change is applied after restarting program. - Изменение языка вступит в силу после перезапуска программы. - - - English - Insert local name of language here. This is used for the language menu of the settingsdialog - Local language here is russian - Русский - General @@ -2360,15 +1747,6 @@ Weak -> Strong Advanced Дополнительные - - Tab Dialog - Настройки - - - English - Also local language here? - Русский - System Default @@ -2460,16 +1838,6 @@ Weak -> Strong Текст был %1 частично подписан: - - Text was completly signed on %1 by: - - Текст был %1 полностью подписан: - - - Text was partially signed on %1 by: - - Текст был %1 частично подписан: - VerifyKeyDetailBox @@ -2537,42 +1905,35 @@ Weak -> Strong Показать детали проверки подписи - + + Details + Детали + + + Key not present with id 0x Отсутствует ключ с идентификатором 0x - + Error validating signature by: Ошибка проверки подписи от: - + Text was completely signed by: Текст был полностью подписан: - + Text was partially signed by: Текст был частично подписан: - Key not present with Fingerprint: - Отсутствует ключ с отпечатком: - - - + Error for key with fingerprint Ошибка ключа с отпечатком - - Text is completly signed by: - Текст полностью подписан: - - - Text is partially signed by: - Текст частично подписан: - Wizard diff --git a/release/ts/gpg4usb_sv.qm b/release/ts/gpg4usb_sv.qm new file mode 100644 index 0000000..12e9c02 Binary files /dev/null and b/release/ts/gpg4usb_sv.qm differ diff --git a/release/ts/gpg4usb_sv.ts b/release/ts/gpg4usb_sv.ts new file mode 100644 index 0000000..5dc57d2 --- /dev/null +++ b/release/ts/gpg4usb_sv.ts @@ -0,0 +1,1975 @@ + + + + + AdvancedTab + + + Show Steganography Options [Advanced] + Visa Steganography-alternativ [Avancerat] + + + + Show Steganographic Options. + Visa Steganographiska alternativ. + + + + AppearanceTab + + + Iconsize + Ikonstorlek + + + + small + Liten + + + + medium + Medium + + + + large + Stor + + + + Iconstyle + Ikonstil + + + + just text + Endast text + + + + just icons + Endast ikoner + + + + text and icons + Text och ikoner + + + + Windowstate + Fönsterstatus + + + + Save window size and position on exit. + Spara fönsterstorlek och position vid avslut. + + + + AttachmentTableModel + + + Filename + Filnamn + + + + Contenttype + Innehållstyp + + + + Attachments + + + + Save File + Spara filen + + + + Save this file + Spara den här filen + + + + Open File + Öppna filen + + + + Open this file + Öppna den här filen + + + + + File + Fil + + + + + Cannot write file %1: +%2. + Kan inte skriva filen %1 +%2. + + + + ChoosePage + + + Choose your action... + Välj åtgärd... + + + + ...by clicking on the apropriate link. + ...genom att klicka på lämplig länk. + + + + If you have never used gpg4usb before and also don't own a gpg key yet you may possibly want to + Har du aldrig använt gpg4usb tidigare och inte har någon gpg-nyckel ännu, kanske du vill + + + + create a new keypair + skapa ett nytt nyckelpar + + + + If you upgrade from an older version of gpg4usb you may want to + Om du uppgraderat från en äldre version av gpg4usb. kanske du vill + + + + import settings and/or keys from gpg4usb + importera inställningar och/eller nycklar från gpg4usb + + + + If you are already using GnuPG you may want to + Om du redan använder GnuPG, vill du kanske + + + + import keys from GnuPG + importera nycklar från GnuPG + + + + ConclusionPage + + + Ready. + Klar. + + + + Have fun with gpg4usb! + Ha det så kul med gpg4usb! + + + + You are ready to use gpg4usb now.<br><br>The offline help will get you started with gpg4usb. It will open in the main window.<br> + Du är nu redo att börja använda gpg4usb.<br><br>Hjälpfilen kommer att hjälpa dig igång med gpg4usb. Den öppnas i programfönstret.<br> + + + + Open offline help. + Öppna hjälpfilen. + + + + Dont show the wizard again. + Visa inte denna guide igen. + + + + FileEncryptionDialog + + + Encrypt / Decrypt File + Kryptera/Dekryptera fil + + + + + + File + Fil + + + + Action + Åtgärd + + + + Decrypt File + Dekryptera fil + + + + Encrypt File + Kryptera fil + + + + Input + Indata + + + + Output + Utdata + + + + &Encrypt + &Kryptera + + + + &Decrypt + &Dekryptera + + + + Open File + Öppna fil + + + + Save File + Spara fil + + + + Couldn't Open file: + Kan inte öppna filen: + + + + Cannot write file %1: +%2. + Kan inte skriva filen %1: +%2. + + + + File exists! Do you want to overwrite it? + Filen finns redan! Vill du skriva över den? + + + + GeneralTab + + + Remember Password + Kom ihåg lösenord + + + + Remember password until closing gpg4usb + Kom ihåg lösenord tills gpg4usb avslutas + + + + Save Checked Keys + Spara förbockade nycklar + + + + Save checked private keys on exit and restore them on next start. + Spara förbockade nycklar vid avslut, och återställ dem vid nästa start. + + + + Confirm drag'n'drop key import + 'Dra och släpp' nyckelimport + + + + Import files dropped on the keylist without confirmation. + Importera filer som släpps i nyckellistan utan bekräftelse. + + + + Language + Språk + + + + GpgME::GpgContext + + + No Key Selected + Ingen nyckel vald + + + + <br>No private key with id %1 present in keyring + <br>Det finns ingen nyckel med ID %1, i din nyckelring + + + + Unsupported algorithm + Algoritmen saknar stöd + + + + Error decrypting: + Fel vid dekryptering: + + + + Wrong password + Fel lösenord + + + + Enter Password for + Ange lösenord för + + + + Enter Password + Ange lösenord + + + + Key Selection + Nyckelsamling + + + + No Private Key Selected + Ingen privat nyckel vald + + + + Error signing: + Fel vid signering: + + + + ImportFromGnupgPage + + + Import keys... + Importera nycklar... + + + + ...from existing GnuPG installation + ...från befintlig GnuPG-installation + + + + You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br> + Du kan importera nycklar från en lokalt installerad GnuPG.<br><br>Lagringsplatsen läses in från Windows register, eller antas vara .gnupg-katalogen i din home-katalog i Linux.<br> + + + + Import keys from GnuPG + Importera nycklar från GnuPG + + + + Import Error + Importfel + + + + Couldn't locate GnuPG home directory + Kunde inte hitta GnuPGs programmapp + + + + ImportFromGpg4usbPage + + + Import from... + Importera från... + + + + ...existing gpg4usb + ...befinlig gpg4usb + + + + You can import keys and/or settings from existing gpg4usb. <br><br>Just check what you want to import, click the import button and choose the directory of your other gpg4usb in the appearing file dialog. + Du kan importera nycklar och/eller inställningarfrån befintlig gpg4usb.<br><br>Bocka för det du vill importera, klicka på import-knappen och välj katalog för din andra gpg4usb i påföljande dialog. + + + + Keys + Nycklar + + + + Configuration + Inställningar + + + + Import from gpg4usb + Importera från gpg4usb + + + + Other gpg4usb directory + Annan gbg4usb-katalog + + + + Configuration Imported + Inställningar importerade + + + + Imported Configuration from old gpg4usb.<br>Will now restart to activate the configuration. + Inställningar importerade från gammal gpg4usb.<br>gpg4usb kommer nu att startas omför att aktivera inställningarna. + + + + IntroPage + + + Getting started... + Kom igång... + + + + ... with gpg4usb + ...med gpg4usb + + + + To use gpg4usb for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br> + För att kunna använda gpg4usb till att kryptera och signera meddelanden, behöver du en privat nyckel. Nästa sida hjälper dig att skapa eller importera en sådan nyckel.<br><br>För mer information, se <a href='docu_concepts.html'>konceptet</a> (klicka på länken för att öppna sidan i programfönstret). <br> + + + + Choose a Language + Väl ett språk + + + + KeyDetailsDialog + + + Owner details + Ägaruppgifter + + + + Key details + Nyckeluppgifter + + + + Fingerprint + Fingeravtryck + + + + Additional Uids + Ytterligare uid + + + + Name: + Namn: + + + + E-Mailaddress: + E-postadress: + + + + Comment: + Kommentar: + + + + Expires on: + Upphör att gälla: + + + + Created on: + Skapad: + + + + Key ID: + Nyckel-ID: + + + + copy fingerprint to clipboard + kopiera fingeravtryck till Urklipp + + + + Warning: Key expired + Varning! Nyckeln har upphört att gälla + + + + Warning: Key revoked + Varning! Nyckeln har dragits tillbaka + + + + Keydetails + Nyckeldetaljer + + + + You are about to export your private key. +This is NOT your public key, so don't give it away. +Make sure you keep it save.Do you really want to export your private key? + Du är på väg att exportera din privata nyckel. +Detta är INTE din publika nyckel, så lämna inte ut den! +Se till att förvara den säkert. Vill du exportera din privata nyckel? + + + + Key Files + Nyckelfiler + + + + Export error + Exportfel + + + + Couldn't open %1 for writing + Kunde inte öppna %1 för skrivning + + + + Key size: + Nyckelstorlek: + + + + Algorithm: + Algoritm: + + + + Never + Aldrig + + + + / Never + / Aldrig + + + + Private Key + Privat nyckel + + + + Export Private Key + Exportera privat nyckel + + + + Exporting private Key + Exporterar privat nyckel + + + + Export Key To File + Exportera nyckel till fil + + + + KeyGenDialog + + + Generate Key + Skapa nyckel + + + + Password Strength + Lösenordsstyrka + + + + Name: + Namn: + + + + E-Mailaddress: + E-postadress: + + + + Comment: + Kommentar: + + + + Expiration Date: + Upphör att gälla: + + + + Never Expire + Upphör aldrig + + + + KeySize (in Bit): + Nyckelstorlek (i bitar): + + + + Password: + Lösenord: + + + + Password: Strength +Weak -> Strong + Lösenordsstyrka +Svag -> Stark + + + + Repeat Password: + Upprepa lösenord: + + + + Name must contain at least five characters. + + Namnet måste innehålla minst 5 tecken. + + + + + Password and Repeat don't match. + Lösenorden matchar inte varandra. + + + + Generating Key... + Genererar nyckel... + + + + Collecting random data for key generation. + This may take a while. + To speed up the process use your computer + (e.g. browse the net, listen to music,...) + Samlar in slumpmässig data för nyckelgenerering. + Det här kan ta en stund. + Använd din dator för att snabba på processen + (Exempel: Surfa på nätet, lyssna på musik,...) + + + + Success + Åtgärden slutförd + + + + New key created + Ny nyckel skapad + + + + KeyGenPage + + + Create a keypair... + Skapa ett nyckelpar... + + + + ...for decrypting and signing messages + ...för dekryptering och signering av meddelanden + + + + You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window): + Du skall skapa ett nytt nyckelpar. Paret består av en publik och en privat nyckel.<br>Andra användare kan använda din publika nyckel för att kryptera meddelanden till dig, och för att verifiera mededelanden signerade av dig. Du kan använda din privata nyckel för att dekryptera och signera meddelanden.<br>Se hjälpfilen för ytterligare informationl (finns i hjälpmenyn): + + + + Offline tutorial + Hjälpdokument + + + + Create New Key + Skapa ny nyckel + + + + KeyImportDetailDialog + + + + Key import details + Importdetaljer + + + + No keys found to import + Hittade ingen nyckel att importera + + + + Genral key import info + Generell importinformation + + + + Considered: + Ansedd: + + + + Public unchanged: + Publik oförändrad: + + + + Imported: + Importerad: + + + + Not imported: + Inte importerad: + + + + Private read: + Privat inläst: + + + + Private imported: + Privat importerad: + + + + Private unchanged: + Privat oförändrad: + + + + Name + Namn + + + + Email + E-postadress + + + + Status + Status + + + + Fingerprint + Fingeravtryck + + + + private + privat + + + + public + publik + + + + unchanged + oförändrad + + + + new key + ny nyckel + + + + new subkey + ny undernyckel + + + + new signature + ny signatur + + + + new uid + nytt uid + + + + KeyList + + + Name + Namn + + + + EMail + E-postadress + + + + Import Keys + Importera nycklar + + + + You've dropped something on the keylist. + gpg4usb will now try to import key(s). + Du har släppt något på nyckellistan. gpg4usb kommer att försöka importera nycklar. + + + + Always import without bothering. + Importera alltid utan att fråga. + + + + Couldn't Open File: + Kunde inte öppna filen: + + + + KeyMgmt + + + Keymanagement + Nyckelhantering + + + + &Close Key Management + &Stäng nyckelhanteraren + + + + Ctrl+Q + Ctrl+Q + + + + Close Key Management + Stäng nyckelhanteraren + + + + Import New Key From File + Importera ny nyckel från fil + + + + Import New Key From Clipboard + Importera ny nyckel från Urklipp + + + + &Keyserver + &Nyckelserver + + + + Import New Key From Keyserver + Importera ny nyckel från nyckelserver + + + + Export To &Clipboard + Exportera till &Urklipp + + + + Export Selected Key(s) To Clipboard + Exportera markerade nycklar till Urklipp + + + + Export To &File + Exportera till &fil + + + + Export Selected Key(s) To File + Exportera markerade nycklar till fil + + + + Delete Selected Key(s) + Ta bort markerade nycklar + + + + Delete the Selected keys + Ta bort markerade nycklar + + + + Delete Checked Key(s) + Ta bort förbockade nycklar + + + + Delete the Checked keys + Ta bort förbockade nycklar + + + + Generate Key + Skapa nyckel + + + + Generate New Key + Skapa ny nyckel + + + + Show Keydetails + Visa nyckeldetaljer + + + + Show Details for this Key + Visa uppgifter om denna nyckel + + + + Import key + Importera nyckel + + + + Import key from + Importera nyckel från + + + + key(s) exported + exporterade nycklar + + + + + &File + &Arkiv + + + + &Clipboard + &Urklipp + + + + &Key + &Nyckel + + + + &Import Key From... + &Importera nyckel från... + + + + Key + Nyckel + + + + Open Key + Öppna nyckel + + + + + Key Files + Nyckelfiler + + + + Keyring files + Nyckelringsfiler + + + + Couldn't Open File: + Kan inte öppna filen: + + + + Deleting Keys + Tar bort nycklar + + + + <b>Are you sure that you want to delete the following keys?.</b><br/><br/> + <b>Vill du verkligen ta bort följande nycklar?</b><br/><br/> + + + + <br/>The action can not be undone. + <br/>Åtgärden kan inte ångras. + + + + Export Key To File + Exportera nyckel till fil + + + + KeyServerImportDialog + + + &Close + &Stäng + + + + &Import + &Importera + + + + &Search + &Sök + + + + Search string: + Söksträng: + + + + Keyserver: + Nyckelserver: + + + + Import Keys from Keyserver + Importera nycklar från nyckelserver + + + + UID + UID + + + + Creation date + Skapad + + + + KeyID + Nyckel-ID + + + + Tag + Tagg + + + + Couldn't contact keyserver! + Kunde inte ansluta till nyckelserver! + + + + Too many responses from keyserver! + För många svar från nyckelservern! + + + + No keys found, input may be kexId, retrying search with 0x. + Inga nycklar hittades, försöker söka på nytt med 0x. + + + + No keys found containing the search string! + Inga nycklar som innehåller söksträngen kan hittas! + + + + Insufficiently specific search string! + Otillräckligt specificerad söksträng! + + + + revoked + återkallad + + + + disabled + inaktiverad + + + + %1 keys found. Doubleclick a key to import it. + %1 nyckel/nycklar hittades. Dubbelklicka på en nyckel för att importera den. + + + + Error while contacting keyserver! + Ett fel upstod när nyckelservern kontaktades! + + + + Key imported + Nyckel importerad + + + + KeyserverTab + + + Default Keyserver for import: + Ordinarie nyckelserver för import: + + + + MainWindow + + + &New + &Nytt + + + + Open a new file + Öppna ny fil + + + + &Open... + &Öppna... + + + + Open an existing file + Öppna befintlig fil + + + + &Save + &Spara + + + + Save the current File + Spara aktuell fil + + + + Save &As + S&para som + + + + Save the current File as... + Spara aktuell fil som... + + + + &Print + S&kriv ut + + + + Print Document + Skriv ut dokument + + + + + &Close + S&täng + + + + Close file + Stäng fil + + + + &Quit + &Avsluta + + + + Quit Program + Avsluta programmet + + + + &Undo + &Ångra + + + + Undo Last Edit Action + Ångra senaste åtgärd + + + + &Redo + &Upprepa + + + + Redo Last Edit Action + Upprepa föregående åtgärd + + + + Zoom In + Zooma in + + + + Zoom Out + Zooma ut + + + + &Paste + &Klistra in + + + + Paste Text From Clipboard + Klistra in text från Urklipp + + + + Cu&t + K&lipp ut + + + + Cut the current selection's contents to the clipboard + Klipp ut markerat innehåll till Urklipp + + + + &Copy + Ko&piera + + + + Copy the current selection's contents to the clipboard + Kopiera markerat innehåll till Urklipp + + + + &Quote + &Citera + + + + Quote whole text + Citera text + + + + Select &All + &Markera allt + + + + Select the whole text + Markera hela texten + + + + Remove &spacing + Ta bort &tomma rader + + + + Remove double linebreaks, e.g. in pasted text from webmailer + Ta bort dubbla radbrytningar. (Ex: Inklistrad text från e-post) + + + + Se&ttings + &Inställningar + + + + Open settings dialog + Öppna inställningsdialogen + + + + &Encrypt + &Kryptera + + + + Encrypt Message + Kryptera meddelande + + + + &Decrypt + &Dekryptera + + + + Decrypt Message + Dekryptera meddelande + + + + &File Encryption + &Filkryptering + + + + Encrypt/Decrypt File + Kryptera/Dekryptera fil + + + + &Encrypt File + &Kryptera fil + + + + Encrypt File + Kryptera fil + + + + &Decrypt File + &Dekryptera fil + + + + Decrypt File + Dekryptera fil + + + + &Sign + &Signera + + + + Sign Message + Signera meddelande + + + + &Verify + &Verifiera + + + + Verify Message + Verifiera meddelande + + + + &Editor + &Redigerare + + + + Import New Key From Editor + Importera ny nyckel från redigerare + + + + Manage &keys + Hantera &nycklar + + + + Open Keymanagement + Öppna nyckelhanteringen + + + + &About + &Om + + + + Show the application's About box + Visa programmets Om-fönster + + + + Integrated Help + Hjälp + + + + Open integrated Help + Öppna hjälpfilen + + + + Online &Tutorials + Online-&hjälp + + + + Open Online Tutorials + Öppna hjälp i webbläsaren + + + + Translate gpg4usb + Översätt gpg4usb + + + + Translate gpg4usb yourself + Översätt gpg4usb själv + + + + Open &Wizard + Öppna &startguiden + + + + Open the wizard + Öppna startguiden + + + + Append Selected Key(s) To Text + Bifoga markerade nycklar till text + + + + Append The Selected Keys To Text in Editor + Bifoga de markerade nycklarna till texten + + + + Copy EMail-address + Kopiera e-postadress + + + + Copy selected EMailaddress to clipboard + Kopiera markerad e-postadress till Urklipp + + + + Show Keydetails + Visa nyckeldetaljer + + + + Show Details for this Key + Visa detaljerad info för denna nyckel + + + + &File + &Arkiv + + + + &Edit + &Redigera + + + + &Crypt + &Kryptering + + + + &Keys + &Nycklar + + + + &Import Key From... + &Importera nyckel från... + + + + &Steganography + &Steganografi + + + + Remove PGP Header + Ta bort PGP-huvud + + + + Add PGP Header + Lägg till PGP-huvud + + + + &View + &Visa + + + + &Help + &Hjälp + + + + File + Arkiv + + + + Crypt + Kryptering + + + + Key + Nycklar + + + + Edit + Redigera + + + + Special edit + Specialredigering + + + + Import key from... + Importera nyckel från... + + + + Import key + Importera nyckel + + + + Encrypt or decrypt File + Kryptera eller dekryptera fil + + + + File.. + Fil + + + + Ready + Klar + + + + Encrypt for: + Nyckellista + + + + Attached files: + Bifogade filer: + + + + About + Om + + + + <center>This application allows simple encryption <br>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Viriato/Phol (es), <br>Serse (it), Russell (my),<br>Alessandro (pt_br), Kirill (ru), Tom (vi)<br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. + <center>Detta program tillhandahåller enkel kryptering <br>och dekryptering av textmeddelanden och filer.<br>Det är licencierat under GPL v3<br><br><b>Utvecklarer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Översättning:</b><br>Viriato/Phol (es), <br>Serse (it), Russell (my),<br>Alessandro (pt_br), Kirill (ru), Tom (vi) Åke (sv)<br><br>Har du några frågor eller förslag, kan du använda vår<br/><a href="http://gpg4usb.cpunk.de/contact.php">kontaktsida</a> eller skicka e-post till vår<br/> e-postlista. <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. + + + + <br><br> Built with Qt + <br><br> Byggd med Qt + + + + and GPGME + och GPGME + + + + There is one unencrypted file in attachment folder + Det finns en okrypterad fil i bilagemappen + + + + There are + Det finns + + + + unencrypted files in attachment folder + okrypterade filer i bilagemappen + + + + MimeTab + + + Decode quoted printable + Avkoda citerade utskrivbara + + + + Try to recognize quoted printable. + Försök att identifiera citerade utskrivbara. + + + + Parse PGP/MIME (Experimental) + Tolka PGP/MIME (Experimentellt) + + + + Try to split attachments from PGP-MIME ecrypted messages. + Försök dela upp bifogade filer från PGP/MIME-krypterade meddelanden. + + + + Open with external application (Experimental) + Öppna med externt program (Experimentellt) + + + + Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol> + Öppna bilagor med standardprogrammet för filtypen.<br> Det finns minst två möjliga problem med detta uppförande:<ol><li>Filen måste sparas okrypterat i bilage-mappen.<br> Det blir ditt jobb att rensa den mappen.</li><li>Det externa programmet kanske har sina egna temporära filer.</li></ol> + + + + Enable opening with external applications. + Aktivera öppning med externa program + + + + + QuitDialog + + + Unsaved files + Osparade filer + + + + <h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3> + <h3>%1 filer innehåller osparad information.<br/>Vill du spara dessa ändringar före avslut?</h3> + + + + Check the files you want to save: + Markera de filer du vill spara: + + + + <b>Note:</b> If you don't save these files, all changes are lost.<br/> + <b>OBS!</b> Om du inte sparar dessa filer kommer alla ändringar att förloras.<br/> + + + + SettingsDialog + + + General + Allmänt + + + + Appearance + Utseende + + + + PGP/Mime + PGP/Mime + + + + Keyserver + Nyckelserver + + + + Advanced + Avancerat + + + + Settings + Inställningar + + + + System Default + Systemstandard + + + + TextEdit + + + untitled + ingenamn + + + + Open file + Öppna fil + + + + + Application + Program + + + + + Cannot read file %1: +%2. + Kan inte läsa filen %1: +%2. + + + + File + Fil + + + + Cannot write file %1: +%2. + Kan inte skriva filen %1: +%2. + + + + Save file + Spara fil + + + + Unsaved document + Osparat dokument + + + + <h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3> + <h3>Dokumentet "%1" har ändrats.<br/>Vill du spara ändringarna?</h3> + + + + <b>Note:</b> If you don't save these files, all changes are lost.<br/> + <b>OBS!</b> Om du inte sparar dessa filer kommer ändringarna att förloras.<br/> + + + + VerifyDetailsDialog + + + Signaturedetails + Signaturuppgifter + + + + Error Validating signature + Kunde inte validera signaturen + + + + Text was completely signed on + %1 by: + + Texten är signerad den + %1 av: + + + + + Text was partially signed on + %1 by: + + Texten är delvis signerad den + %1 av: + + + + + VerifyKeyDetailBox + + + Import from keyserver + Importera från nyckelserver + + + + + + Status: + Status: + + + + + Fingerprint: + Fingeravtryck: + + + + Key not present in keylist + Nyckel finns inte i nyckellistan + + + + Key not present with id 0x + Ingen befintlig nyckel med ID 0x + + + + + Name: + Namn: + + + + + EMail: + E-postadress: + + + + OK + OK + + + + Error for key with id 0x + Fel på nyckel med ID 0x + + + + VerifyNotification + + + Import missing key from Keyserver + Importera saknad nyckel från nyckelserver + + + + Show detailed verify information + Visa detaljerad verifieringsinformation + + + + Details + Detaljer + + + + Key not present with id 0x + Ingen nyckel med ID 0x + + + + Error validating signature by: + Kunde inte validera signatur av: + + + + Text was completely signed by: + Texten är signerad av: + + + + Text was partially signed by: + Texten är delvis signerad av: + + + + Error for key with fingerprint + Fel på nyckel med fingeravtrycket + + + + Wizard + + + First Start Wizard + Startguide + + + + Import Error + Importfel + + + + Couldn't locate any keyring file in %1 + Kunde inte hitta någon nyckelringsfil i %1 + + + + + Import error + Importfel + + + + Couldn't open private keyringfile: %1 + Kunde inte öppna den private nyckelringsfilen: %1 + + + + Couldn't open public keyringfile: %1 + Kunde inte öppna den publika nyckelringsfilen: %1 + + + diff --git a/release/ts/gpg4usb_vi.ts b/release/ts/gpg4usb_vi.ts index ba8a72a..4f7b9d7 100644 --- a/release/ts/gpg4usb_vi.ts +++ b/release/ts/gpg4usb_vi.ts @@ -207,10 +207,6 @@ Action Thực hiện - - ... - ... - Decrypt File @@ -256,10 +252,6 @@ Couldn't Open file: - - couldn't open file: - Không mở được tệp: - Cannot write file %1: @@ -310,49 +302,6 @@ Language Ngôn ngữ - - Language change is applied after restarting program. - Thay đổi Ngôn ngữ được áp dụng sau khi khởi động lại chương trình. - - - System Default - Mặc định Hệ thống - - - - GpgME::Context - - No Key Selected - Không có Khóa được chọn - - - Unsupported algorithm - Thuật toán không được hỗ trợ - - - Error decrypting: - Lỗi giải mã hóa: - - - Wrong password - Mật khẩu không chính xác - - - Enter Password - Nhập Mật khẩu - - - Key Selection - Chọn Khóa - - - No Private Key Selected - Không có Khóa riêng được chọn - - - Error signing: - Lỗi tạo chữ ký số: - GpgME::GpgContext @@ -407,337 +356,6 @@ Lỗi tạo chữ ký số: - - GpgWin - - &Open... - &Mở... - - - Open an existing file - Mở tệp đã tồn tại - - - &Save - &Lưu - - - Save the current File - Lưu Tệp hiện hành - - - Save &As - Lưu &như - - - Save the current File as... - Lưu Tệp hiện hành như... - - - &Print - &In - - - Print Document - In Tài liệu - - - &Close - &Đóng - - - Close file - Đóng tệp - - - &Quit - &Thoát - - - Quit Program - Thoát Chương trình - - - &Undo - &Hoàn tác - - - Undo Last Edit Action - Hoàn tác Thao tác Soạn thảo Sau cùng - - - &Redo - &Hủy hoàn tác - - - Redo Last Edit Action - Thực hiện lại Thao tác Soạn thảo Sau cùng - - - &Paste - &Dán - - - Paste Text From Clipboard - Chép Văn bản từ Clipboard - - - Cu&t - Cắ&t - - - Cut the current selection's contents to the clipboard - Cắt và sao nội dung được chọn vào clipboard - - - &Copy - &Sao chép - - - Copy the current selection's contents to the clipboard - Chép nội dung được chọn vào clipboard - - - &Quote - &Trích dẫn - - - Quote whole text - Trích dẫn toàn bộ đoạn văn bản - - - Select &All - Chọn &Toàn bộ - - - Select the whole text - Chọn toàn bộ đoạn văn bản - - - Remove double &Linebreaks - Bỏ cách dòng và &Xuống dòng - - - Remove double linebreaks, e.g. in pasted text from webmailer - Bỏ dấu cách dòng kép, ví dụ trong các đoạn văn bản sao chép từ thư từ trang web - - - Open settings dialog - Mở hộp thoại thiết đặt - - - &Encrypt - &Mã hóa - - - Encrypt Message - Mã hóa Tin nhắn - - - &Decrypt - &Giải Mã - - - Decrypt Message - Giải mã Tin nhắn - - - &File Encryption - &Mã hóa Tệp - - - Encrypt/Decrypt File - Mã hóa/Giải mã Tệp - - - &Sign - &Ký số - - - Sign Message - Ký Tin nhắn - - - &Verify - &Kiểm tra - - - Verify Message - Kiểm tra Tin nhắn - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Ứng dụng này cho phép mã hóa <br/>và giải mã văn bản hoặc tệp dữ liệu.<br>Bản quyền chương trình tuân thủ GPL v3<br><br><b>Nhóm phát triển:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Chuyển ngữ:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>Nếu bạn có bất kỳ thắc măc hay gợi ý nào hãy liên hệ với chúng tôi <br/>tại trang <a href="http://gpg4usb.cpunk.de/contact.php">liên hệ</a> hoặc qua<br/> địa chỉ thư <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Keyserver - &Máy chủ Khóa - - - Import New Key From Editor - Nhập Khóa Mới Từ Trình Soạn Thảo - - - Key Management - Quản lý Khóa - - - Open Keymanagement - Mở Trình Quản lý Khóa - - - Open Import New Key Dialog - Mở Hộp thoại Nhập Khóa mới - - - &About - &Thông tin - - - Show the application's About box - Hiện hộp Thông tin Ứng dụng - - - &File - &Tệp - - - &Edit - &Soạn thảo - - - &Help - &Trợ giúp - - - Append Selected Key(s) To Text - Nối tiếp Khóa Được Chọn vào Văn bản - - - Se&ttings - Thiế&t đặt - - - &New - &Tạo mới - - - Open a new file - Mở một tệp mới - - - Online &Tutorial - Hướng dẫn &Trực tuyến - - - Open Online Tutorial - Mở Hướng dẫn Trực tuyến - - - Translate gpg4usb - Chuyển ngữ cho gpg4usb - - - Translate gpg4usb yourself - Bạn hãy dịch gpg4usb sang ngôn ngữ khác - - - Append The Selected Keys To Text in Editor - Nối tiếp Khóa Được Chọn Vào Văn bản trong Trình Soạn Thảo - - - Copy EMail-address - Chép Địa chỉ EMail - - - Copy selected EMailaddress to clipboard - Chép Địa chỉ Email được chọn vào clipboard - - - Show Keydetails - Hiển thị thông tin Khóa - - - Show Details for this Key - Hiển thị Thông tin của Khóa này - - - &Keys - &Khóa mã hóa - - - &Import Key From... - &Nhập Khóa Từ... - - - &View - &Hiển thị - - - Ready - Sẵn sàng - - - Encrypt for: - Mã hóa cho: - - - Attached files: - Các tệp đính kèm: - - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v2.0<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>Ứng dụng này cho phép mã hóa <br/>và giải mã văn bản hoặc tệp dữ liệu.<br>Bản quyền chương trình tuân thủ GPL v2.0<br><br><b>Nhóm phát triển:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Chuyển ngữ:</b><br>Alessandro (pt_br), Kirill (ru), Viriato (es), Serse (it) <br><br>Nếu bạn có bất kỳ thắc măc hay gợi ý nào hãy liên hệ với chúng tôi <br/>tại trang <a href="http://gpg4usb.cpunk.de/contact.php">liên hệ</a> hoặc qua<br/> địa chỉ thư <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - There is one unencrypted file in attachment folder - Có một tệp không được mã hóa trong phần đính kèm - - - There are - - - - unencrypted files in attachment folder - các tệp không được mã hóa trong phần đính kèm - - - &Editor - &Trình soạn thảo - - - &Clipboard - &Clipboard - - - Import Key - Nhập Khóa mã hóa - - - &Crypt - &Mã hóa - - - Crypt - Mã hóa - - - Key - Khóa - - - Edit - Soạn thảo - - - About - Thông tin - - - Import Key From... - Nhập Khóa từ... - - ImportFromGnupgPage @@ -971,14 +589,6 @@ Make sure you keep it save.Do you really want to export your private key?Exporting private Key Đang xuất Khóa riêng - - You are about to export your private key. -This is NOT your public key, so don't give it away. -Make sure you keep it save. - Bạn chuẩn bị xuất khóa riêng. -Đây KHÔNG' phải khóa công khai của bạn, đừng tiết lộ cho ai. -Hãy chắc chắn bạn cất giữ khóa riêng này an toàn. - Export Key To File @@ -1439,72 +1049,6 @@ Yếu -> Mạnh Export Key To File Xuất Khóa ra Tệp - - Name: - Tên: - - - E-Mailaddress:: - Địa chỉ Email: - - - Comment: - Nhận xét: - - - KeySize (in Bit): - Kích thước Khóa (Bit): - - - Expiration Date: - Ngày hết hạn: - - - Password: - Mật khẩu: - - - Repeat Password: - Nhập lại Mật khẩu: - - - Never Expire - Không bao giời hết hạn - - - Password: Strength -Weak -> Strong - Mật khẩu: Độ mạnh -Yếu -> Mạnh - - - Password Strength - Độ mạnh Mật khẩu - - - Name must contain at least five characters. - - Tên phải gồm ít nhất năm ký tự. - - - - Password and Repeat don't match. - Mật khẩu và Xác nhận mật khẩu không khớp. - - - Generating Key... - Đang Tạo Khóa... - - - Collecting random data for key generation. - This may take a while. - To speed up the process use your computer - (e.g. browse the net, listen to music,...) - Đang lấy dữ liệu ngẫu nhiên để tạo khóa. - Thao tác này có thể mất chút thời gian. - Để đẩy nhanh tiến trình, hãy sử dụng máy tính - (ví dụ vào Internet, nghe nhạc,...) - KeyServerImportDialog @@ -1559,52 +1103,52 @@ Yếu -> Mạnh - + Couldn't contact keyserver! Không thể kết nối máy chủ khóa! - + Too many responses from keyserver! Quá nhiều trả lời từ máy chủ khóa! - + No keys found, input may be kexId, retrying search with 0x. - + No keys found containing the search string! Không tìm thấy khóa chứa chuỗi tìm kiếm! - + Insufficiently specific search string! Chuỗi tìm kiếm không đủ riêng biệt! - + revoked - + disabled - + %1 keys found. Doubleclick a key to import it. %1 khóa được tìm thấy. Nhấn đúp chuột để nhập khóa. - + Error while contacting keyserver! Lỗi kết nối máy chủ khóa! - + Key imported Khóa được nhập @@ -2169,11 +1713,6 @@ Yếu -> Mạnh SettingsDialog - - English - Insert local name of language here. This is used for the language menu of the settingsdialog - English - General @@ -2209,10 +1748,6 @@ Yếu -> Mạnh System Default Mặc định Hệ thống - - English - Tiếng Việt - TextEdit @@ -2299,18 +1834,6 @@ Yếu -> Mạnh - - Text was completly signed on %1 by: - - Văn bản đã được ký hoàn toàn vào %1 bởi: - - - - Text was partially signed on %1 by: - - Văn bản đã được ký từng phần vào %1 bởi: - - VerifyKeyDetailBox @@ -2402,23 +1925,11 @@ Yếu -> Mạnh Text was partially signed by: - - Key not present with Fingerprint: - Khóa không gồm Vân tay số: - Error for key with fingerprint Lỗi khóa với Vân tay số - - Text is completly signed by: - Văn bản được ký số hoàn toàn bởi: - - - Text is partially signed by: - Văn bản được ký số từng phần bởi: - Wizard diff --git a/release/ts/gpg4usb_zh.ts b/release/ts/gpg4usb_zh.ts index 20bcf40..9c36345 100644 --- a/release/ts/gpg4usb_zh.ts +++ b/release/ts/gpg4usb_zh.ts @@ -208,10 +208,6 @@ Action 动作 - - ... - ... - Decrypt File @@ -257,10 +253,6 @@ Couldn't Open file: 无法打开文件 - - couldn't open file: - 无法打开文件: - Cannot write file %1: @@ -311,14 +303,6 @@ Language 语言 - - Language change is applied after restarting program. - 修改界面语言重启后生效 - - - System Default - 系统默认 - GpgME::GpgContext @@ -608,14 +592,6 @@ Make sure you keep it save.Do you really want to export your private key?Exporting private Key 正在导出私钥 - - You are about to export your private key. -This is NOT your public key, so don't give it away. -Make sure you keep it save. - 你正准备导出你的私人密钥. -此密钥不是你的公共密钥, 不要将它散发 -并确保此密钥的安全. - Export Key To File @@ -1074,70 +1050,6 @@ gpg4usb将尝试导入密钥. Export Key To File 导出密钥到文件 - - Name: - 名称 - - - E-Mailaddress:: - 电邮地址 - - - Comment: - 备注 - - - KeySize (in Bit): - 密钥大小(字节): - - - Expiration Date: - 失效日期: - - - Password: - 密码: - - - Repeat Password: - 重复密码: - - - Never Expire - 永不失效 - - - Password: Strength -Weak -> Strong - 密码:强度 -弱->强 - - - Password Strength - 密码强度 - - - Name must contain at least five characters. - - 名称必须包含至少五个字符. - - - Password and Repeat don't match. - 密码与重复密码内容不同. - - - Generating Key... - 正在生成密钥... - - - Collecting random data for key generation. - This may take a while. - To speed up the process use your computer - (e.g. browse the net, listen to music,...) - 正在为密钥采集随机数据. -这可能会花费一些时间. -使用电脑可加速此过程(如: 浏览网页,听音乐,...) - KeyServerImportDialog @@ -1192,52 +1104,52 @@ Weak -> Strong 标记 - + Couldn't contact keyserver! 无法与密钥服务器通讯! - + Too many responses from keyserver! 密钥服务器回应过多! - + No keys found, input may be kexId, retrying search with 0x. 未发现密钥, 输入kexid , 尝试用0x再次查找. - + No keys found containing the search string! 没有找到含有查询字符串的密钥! - + Insufficiently specific search string! 无效的查询字符串! - + revoked 已失效 - + disabled 已禁用 - + %1 keys found. Doubleclick a key to import it. 找到%1个密钥. 双击密钥将其导入. - + Error while contacting keyserver! 与密钥服务器通讯时发生错误! - + Key imported 密钥已导入 @@ -1398,10 +1310,6 @@ Weak -> Strong Manage &keys 管理密钥 - - Remove double &Linebreaks - 删除双换行 - Remove double linebreaks, e.g. in pasted text from webmailer @@ -1482,32 +1390,16 @@ Weak -> Strong Verify Message 验证信息 - - <center>This application allows simple encryption <br/>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) <br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - <center>本程序为加密程序 <br/>可对文字信息或是文件进行加密.<br>本程序遵循GPL v3授权协议<br><br><b>开发者:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>翻译:</b><br>Alessandro (pt_br), Kirill (ru), Phol (es), Viriato (es), Serse (it), Tom (vi) , Toughworm(zh)<br><br>如果你有任何疑问或建设请查看<br/>我们的<a href="http://gpg4usb.cpunk.de/contact.php">联系方式</a> 或是发送邮件给我们<br/> 邮件地址 <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. - - - &Keyserver - 密钥服务器 - Import New Key From Editor 从编辑器中获得密钥 - - Key Management - 密钥管理 - Open Keymanagement 打开密钥管理 - - Open Import New Key Dialog - 打开导入新密钥对话框 - &About @@ -1578,14 +1470,6 @@ Weak -> Strong Open a new file 打新文件 - - Online &Tutorial - 在线教程 - - - Open Online Tutorial - 打开在线教程 - Translate gpg4usb @@ -1741,14 +1625,6 @@ Weak -> Strong &Editor 编辑器 - - &Clipboard - 剪切板 - - - Import Key - 导入密钥 - &Crypt @@ -1774,10 +1650,6 @@ Weak -> Strong About 关于 - - Import Key From... - 导入密钥 - MimeTab @@ -1842,11 +1714,6 @@ Weak -> Strong SettingsDialog - - English - Insert local name of language here. This is used for the language menu of the settingsdialog - English - General @@ -1882,10 +1749,6 @@ Weak -> Strong System Default 系统默认 - - English - 中文 - TextEdit diff --git a/release/ts/gpg4usb_zh_tw.qm b/release/ts/gpg4usb_zh_tw.qm new file mode 100644 index 0000000..8b875bb Binary files /dev/null and b/release/ts/gpg4usb_zh_tw.qm differ diff --git a/release/ts/gpg4usb_zh_tw.ts b/release/ts/gpg4usb_zh_tw.ts new file mode 100644 index 0000000..c34c3e6 --- /dev/null +++ b/release/ts/gpg4usb_zh_tw.ts @@ -0,0 +1,1975 @@ + + + + + AdvancedTab + + + Show Steganography Options [Advanced] + 顯示資訊偽裝選項 [進階] + + + + Show Steganographic Options. + 顯示資訊偽裝選項。 + + + + AppearanceTab + + + Iconsize + 圖示尺寸 + + + + small + + + + + medium + + + + + large + + + + + Iconstyle + 圖示樣式 + + + + just text + 僅文字 + + + + just icons + 僅圖示 + + + + text and icons + 文字與圖示 + + + + Windowstate + 視窗狀態 + + + + Save window size and position on exit. + 離開時儲存視窗尺寸及位置。 + + + + AttachmentTableModel + + + Filename + 檔案名稱 + + + + Contenttype + 內容類型 + + + + Attachments + + + + Save File + 儲存檔案 + + + + Save this file + 儲存此檔案 + + + + Open File + 開啟檔案 + + + + Open this file + 開啟此檔案 + + + + + File + 檔案 + + + + + Cannot write file %1: +%2. + 無法寫入檔案 %1: +%2。 + + + + ChoosePage + + + Choose your action... + 請選擇你的行動... + + + + ...點擊相對應的連結。 + + + + + If you have never used gpg4usb before and also don't own a gpg key yet you may possibly want to + 如果你從未使用過 gpg4usb,也還沒有任何 gpg 金鑰,你可能會想要 + + + + create a new keypair + 打造新的金鑰對 + + + + If you upgrade from an older version of gpg4usb you may want to + 如果你是從舊版的 gpg4usb 升級上來,你可能會想要 + + + + import settings and/or keys from gpg4usb + 匯入 gpg4usb 的設定和金鑰 + + + + If you are already using GnuPG you may want to + 如果你已經在使用 GnuPG,你可能會想要 + + + + import keys from GnuPG + 匯入 GnuPG 的金鑰 + + + + ConclusionPage + + + Ready. + 準備就緒。 + + + + Have fun with gpg4usb! + 祝你 gpg4usb 用得愉快! + + + + You are ready to use gpg4usb now.<br><br>The offline help will get you started with gpg4usb. It will open in the main window.<br> + 你已經準備好開始使用 gpg4usb 了。<br><br>離線說明文件將帶領你開始使用 gpg4usb。該說明文件將開啟於主視窗。<br> + + + + Open offline help. + 開啟離線說明文件。 + + + + Dont show the wizard again. + 不要再顯示這個精靈。 + + + + FileEncryptionDialog + + + Encrypt / Decrypt File + 檔案加密/解密 + + + + + + File + 檔案 + + + + Action + 行動 + + + + Decrypt File + 檔案解密 + + + + Encrypt File + 檔案加密 + + + + Input + 輸入 + + + + Output + 輸出 + + + + &Encrypt + 加密 (&E) + + + + &Decrypt + 解密 (&D) + + + + Open File + 開啟檔案 + + + + Save File + 儲存檔案 + + + + Couldn't Open file: + 無法開啟檔案: + + + + Cannot write file %1: +%2. + 無法寫入檔案 %1: +%2。 + + + + File exists! Do you want to overwrite it? + 檔案已存在!請問你是否想要覆蓋掉原本的檔案? + + + + GeneralTab + + + Remember Password + 記住密碼 + + + + Remember password until closing gpg4usb + 關閉 gpg4usb 前記住密碼 + + + + Save Checked Keys + 儲存已核選的金鑰 + + + + Save checked private keys on exit and restore them on next start. + 離開時儲存已核選的私鑰,並於下次執行時加以還原。 + + + + Confirm drag'n'drop key import + 確認拖曳金鑰匯入的動作 + + + + Import files dropped on the keylist without confirmation. + 將檔案拖曳至金鑰清單時,不另確認即匯入 + + + + Language + 語言 + + + + GpgME::GpgContext + + + No Key Selected + 未選擇任何金鑰 + + + + <br>No private key with id %1 present in keyring + <br>金鑰鑰匙圈中沒有 ID 為 %1 的私鑰 + + + + Unsupported algorithm + 未支援的演算法 + + + + Error decrypting: + 解密時出錯: + + + + Wrong password + 密碼錯誤 + + + + Enter Password for + 請輸入密碼: + + + + Enter Password + 輸入密碼 + + + + Key Selection + 金鑰選擇 + + + + No Private Key Selected + 未選擇任何私鑰 + + + + Error signing: + 簽署時出錯: + + + + ImportFromGnupgPage + + + Import keys... + 匯入金鑰... + + + + ...from existing GnuPG installation + ...從既有安裝的 GnuPG + + + + You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br> + 你可以從本地既有安裝的 GnuPG 匯入金鑰。<br><br>其安裝路徑會從 Windows 的登錄中讀取,或者假定為目前 Linux 使用者家目錄的 .gnupg 子目錄。<br> + + + + Import keys from GnuPG + 從 GnuPG 匯入金鑰 + + + + Import Error + 匯入出錯 + + + + Couldn't locate GnuPG home directory + 無法找出 GnuPG 的家目錄 + + + + ImportFromGpg4usbPage + + + Import from... + 由此匯入... + + + + ...existing gpg4usb + ....從既有的 gpg4usb + + + + You can import keys and/or settings from existing gpg4usb. <br><br>Just check what you want to import, click the import button and choose the directory of your other gpg4usb in the appearing file dialog. + 你可以從既有的 gpg4usb 匯入金鑰和設定。<br><br>只要核選想匯入的東西,按下匯入按鈕,然後從接下來出現的檔案對話框中,選擇其他 gpg4usb 目錄即可。 + + + + Keys + 金鑰 + + + + Configuration + 組態設定 + + + + Import from gpg4usb + 從 gpg4usb 匯入 + + + + Other gpg4usb directory + 其他的 gpg4usb 目錄 + + + + Configuration Imported + 已匯入組態設定 + + + + Imported Configuration from old gpg4usb.<br>Will now restart to activate the configuration. + 已匯入舊有 gpg4usb 的組態設定。<br>現在將重新啟動以啟用這些組態設定。 + + + + IntroPage + + + Getting started... + 入門使用.... + + + + ... with gpg4usb + ...gpg4usb + + + + To use gpg4usb for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br> + 如欲使用 gpg4usb 解密和簽署訊息,將需要用到私鑰。下一頁將協助你產生或匯入金鑰。<br><br>更多資訊請參見<a href='docu_concepts.html'>概念說明文件</a>(按下連結後將在主視窗開出該頁面)。<br> + + + + Choose a Language + 選擇語言 + + + + KeyDetailsDialog + + + Owner details + 持有人詳細資訊 + + + + Key details + 金鑰詳細資訊 + + + + Fingerprint + 指紋 + + + + Additional Uids + 附加的 UID + + + + Name: + 姓名: + + + + E-Mailaddress: + 電子郵件地址: + + + + Comment: + 註解: + + + + Expires on: + 有效期限: + + + + Created on: + 打造日期: + + + + Key ID: + 金鑰 ID: + + + + copy fingerprint to clipboard + 將指紋複製到剪貼簿 + + + + Warning: Key expired + 警告:金鑰已過期 + + + + Warning: Key revoked + 警告:金鑰已撤銷 + + + + Keydetails + 金鑰詳細資訊 + + + + You are about to export your private key. +This is NOT your public key, so don't give it away. +Make sure you keep it save.Do you really want to export your private key? + 你正要匯出私鑰。 +私鑰可不是公鑰,請千萬不要交給任何其他人。 +請確保私鑰安全。請問你是否真的想要匯出私鑰? + + + + Key Files + 金鑰檔案 + + + + Export error + 匯出出錯 + + + + Couldn't open %1 for writing + 無法開啟 %1 寫入 + + + + Key size: + 金鑰尺寸: + + + + Algorithm: + 演算法: + + + + Never + 永遠不過期 + + + + / Never + / 永遠不過期 + + + + Private Key + 私鑰 + + + + Export Private Key + 匯出私鑰 + + + + Exporting private Key + 正在匯出私鑰 + + + + Export Key To File + 匯出金鑰至檔案 + + + + KeyGenDialog + + + Generate Key + 產生金鑰 + + + + Password Strength + 密碼強度 + + + + Name: + 姓名: + + + + E-Mailaddress: + 電子郵件地址: + + + + Comment: + 註解: + + + + Expiration Date: + 有效期限: + + + + Never Expire + 永遠不會過期 + + + + KeySize (in Bit): + 金鑰尺寸 (位元): + + + + Password: + 密碼: + + + + Password: Strength +Weak -> Strong + 密碼: 強度 +弱 -> 強 + + + + Repeat Password: + 再輸入一次密碼: + + + + Name must contain at least five characters. + + 姓名至少要包含五個字符。 + + + + + Password and Repeat don't match. + 兩次輸入的密碼不相符合。 + + + + Generating Key... + 正在產生金鑰... + + + + Collecting random data for key generation. + This may take a while. + To speed up the process use your computer + (e.g. browse the net, listen to music,...) + 正在蒐集隨機資料以便產生金鑰。 +這可能會花上一段時間。 +如欲加速進行,請隨意使用電腦 +(例如瀏覽網頁、聽音樂等) + + + + Success + 成功 + + + + New key created + 已建立新的金鑰 + + + + KeyGenPage + + + Create a keypair... + 建立金鑰對... + + + + ...for decrypting and signing messages + ...以便解密和簽署訊息 + + + + You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window): + 你應該建立新的金鑰對。金鑰對由公鑰及私鑰組成。<br>其他使用者可以用你的公鑰,將訊息加密給你,並驗證由你所簽署的訊息;你則可以使用私鑰來解密及簽署訊息。<br>更多資訊請查看離線教學文件(會顯示在主視窗): + + + + Offline tutorial + 離線教學 + + + + Create New Key + 建立新的金鑰 + + + + KeyImportDetailDialog + + + + Key import details + 金鑰匯入詳細資訊 + + + + No keys found to import + 找不到可匯入的金鑰 + + + + Genral key import info + 一般金鑰匯入資訊 + + + + Considered: + 已處理: + + + + Public unchanged: + 公鑰未變更: + + + + Imported: + 已匯入: + + + + Not imported: + 未匯入: + + + + Private read: + 私鑰已讀取: + + + + Private imported: + 私鑰已匯入: + + + + Private unchanged: + 私鑰未變更: + + + + Name + 姓名 + + + + Email + 電子郵件 + + + + Status + 狀態 + + + + Fingerprint + 指紋 + + + + private + 私鑰 + + + + public + 公鑰 + + + + unchanged + 未變更 + + + + new key + 新金鑰 + + + + new subkey + 新子鑰 + + + + new signature + 新簽章 + + + + new uid + 新 UID + + + + KeyList + + + Name + 姓名 + + + + EMail + 電子郵件 + + + + Import Keys + 匯入金鑰 + + + + You've dropped something on the keylist. + gpg4usb will now try to import key(s). + 你拖曳了某些東西到金鑰清單上。 + 現在 gpg4usb 將嘗試匯入金鑰。 + + + + Always import without bothering. + 以後都直接匯入,別再煩我。 + + + + Couldn't Open File: + 無法開啟檔案: + + + + KeyMgmt + + + Keymanagement + 金鑰管理 + + + + &Close Key Management + 關閉金鑰管理 (&C) + + + + Ctrl+Q + Ctrl+Q + + + + Close Key Management + 關閉金鑰管理 + + + + Import New Key From File + 從檔案匯入新的金鑰 + + + + Import New Key From Clipboard + 從剪貼簿匯入新的金鑰 + + + + &Keyserver + 金鑰伺服器 (&K) + + + + Import New Key From Keyserver + 從金鑰伺服器匯入新的金鑰 + + + + Export To &Clipboard + 匯出至剪貼簿 (&C) + + + + Export Selected Key(s) To Clipboard + 匯出所選的金鑰至剪貼簿 + + + + Export To &File + 匯出至檔案 (&F) + + + + Export Selected Key(s) To File + 匯出所選的金鑰至檔案 + + + + Delete Selected Key(s) + 刪除所選的金鑰 + + + + Delete the Selected keys + 刪除所選的金鑰 + + + + Delete Checked Key(s) + 刪除已核選的金鑰 + + + + Delete the Checked keys + 刪除已核選的金鑰 + + + + Generate Key + 產生金鑰 + + + + Generate New Key + 產生新的金鑰 + + + + Show Keydetails + 顯示金鑰詳細資訊 + + + + Show Details for this Key + 顯示此金鑰的詳細資訊 + + + + Import key + 匯入金鑰 + + + + Import key from + 由此匯入金鑰: + + + + key(s) exported + 把金鑰已匯出 + + + + + &File + 檔案 (&F) + + + + &Clipboard + 剪貼簿 (&C) + + + + &Key + 金鑰 (&K) + + + + &Import Key From... + 由此匯入金鑰 (&I)... + + + + Key + 金鑰 + + + + Open Key + 開放金鑰 + + + + + Key Files + 金鑰檔案 + + + + Keyring files + 金鑰鑰匙圈檔案 + + + + Couldn't Open File: + 無法開啟檔案: + + + + Deleting Keys + 正在刪除金鑰 + + + + <b>Are you sure that you want to delete the following keys?.</b><br/><br/> + <b>請問你是否確定要刪除下列金鑰?</b><br/><br/> + + + + <br/>The action can not be undone. + <br/>這項操作的結果將無可挽回。 + + + + Export Key To File + 匯出金鑰至檔案 + + + + KeyServerImportDialog + + + &Close + 關閉 (&C) + + + + &Import + 匯入 (&I) + + + + &Search + 搜尋 (&S) + + + + Search string: + 搜尋字串: + + + + Keyserver: + 金鑰伺服器: + + + + Import Keys from Keyserver + 從金鑰伺服器匯入金鑰 + + + + UID + UID + + + + Creation date + 建立日期 + + + + KeyID + 金鑰 ID + + + + Tag + 標籤 + + + + Couldn't contact keyserver! + 無法連上金鑰伺服器! + + + + Too many responses from keyserver! + 金鑰伺服器傳回太多回應! + + + + No keys found, input may be kexId, retrying search with 0x. + 找不到金鑰,也許輸入值為金鑰 ID,正以 0x 開頭重新嘗試。 + + + + No keys found containing the search string! + 找不到含有搜尋字串的金鑰! + + + + Insufficiently specific search string! + 指定的搜尋字串不足! + + + + revoked + 已撤銷 + + + + disabled + 已停用 + + + + %1 keys found. Doubleclick a key to import it. + 找到 %1 把金鑰。雙擊金鑰即可匯入。 + + + + Error while contacting keyserver! + 聯繫金鑰伺服器時出錯! + + + + Key imported + 已匯入金鑰 + + + + KeyserverTab + + + Default Keyserver for import: + 預設用來匯入的金鑰伺服器: + + + + MainWindow + + + &New + 新增 (&N) + + + + Open a new file + 開啟新檔 + + + + &Open... + 開啟 (&O)... + + + + Open an existing file + 開啟既有的檔案 + + + + &Save + 儲存 (&S) + + + + Save the current File + 儲存目前的檔案 + + + + Save &As + 另存新檔 (&A) + + + + Save the current File as... + 將目前的檔案另存為... + + + + &Print + 列印 (&P) + + + + Print Document + 列印文件 + + + + + &Close + 關閉 (&C) + + + + Close file + 關閉檔案 + + + + &Quit + 離開 (&Q) + + + + Quit Program + 離開程式 + + + + &Undo + 還原 (&U) + + + + Undo Last Edit Action + 還原最後的編輯動作 + + + + &Redo + 重做 (&R) + + + + Redo Last Edit Action + 重做一次最後的編輯動作 + + + + Zoom In + 拉近 + + + + Zoom Out + 拉遠 + + + + &Paste + 貼上 (&P) + + + + Paste Text From Clipboard + 從剪貼簿貼上文字 + + + + Cu&t + 剪下 (&t) + + + + Cut the current selection's contents to the clipboard + 將目前選取的內容剪下並存放至剪貼簿 + + + + &Copy + 複製 (&C) + + + + Copy the current selection's contents to the clipboard + 將目前選取的內容複製到剪貼簿 + + + + &Quote + 引用 (&Q) + + + + Quote whole text + 引用整段文字 + + + + Select &All + 全選 (&A) + + + + Select the whole text + 選取整段文字 + + + + Remove &spacing + 移除空行 (&s) + + + + Remove double linebreaks, e.g. in pasted text from webmailer + 移除連續兩次的換列,可用於從網頁郵件服務貼上文字的時機 + + + + Se&ttings + 設定 (&t) + + + + Open settings dialog + 開啟設定對話框 + + + + &Encrypt + 加密 (&E) + + + + Encrypt Message + 訊息加密 + + + + &Decrypt + 解密 (&D) + + + + Decrypt Message + 訊息解密 + + + + &File Encryption + 檔案加密 (&F) + + + + Encrypt/Decrypt File + 檔案加密/解密 + + + + &Encrypt File + 檔案加密 (&E) + + + + Encrypt File + 檔案加密 + + + + &Decrypt File + 檔案解密 (&D) + + + + Decrypt File + 檔案解密 + + + + &Sign + 簽署 (&S) + + + + Sign Message + 簽署訊息 + + + + &Verify + 驗證 (&V) + + + + Verify Message + 驗證訊息 + + + + &Editor + 編輯器 (&E) + + + + Import New Key From Editor + 從編輯器匯入新的金鑰 + + + + Manage &keys + 管理金鑰 (&k) + + + + Open Keymanagement + 開啟金鑰管理 + + + + &About + 關於 (&A) + + + + Show the application's About box + 顯示應用程式的「關於」對話方塊 + + + + Integrated Help + 內建說明文件 + + + + Open integrated Help + 開啟內建說明文件 + + + + Online &Tutorials + 線上教學文件 (&T) + + + + Open Online Tutorials + 開啟線上教學文件 + + + + Translate gpg4usb + 翻譯 gpg4usb + + + + Translate gpg4usb yourself + 自行翻譯 gpg4usb + + + + Open &Wizard + 開啟精靈 (&W) + + + + Open the wizard + 開啟精靈 + + + + Append Selected Key(s) To Text + 將所選的金鑰附加至文字後 + + + + Append The Selected Keys To Text in Editor + 在編輯器中,將所選的金鑰附加至文字後 + + + + Copy EMail-address + 複製電子郵件地址 + + + + Copy selected EMailaddress to clipboard + 將所選的電子郵件地址複製到剪貼簿 + + + + Show Keydetails + 顯示金鑰詳細資訊 + + + + Show Details for this Key + 顯示此金鑰的詳細資訊 + + + + &File + 檔案 (&F) + + + + &Edit + 編輯 (&E) + + + + &Crypt + 編密 (&C) + + + + &Keys + 金鑰 (&K) + + + + &Import Key From... + 由此匯入金鑰 (&I)... + + + + &Steganography + 資訊偽裝 (&S) + + + + Remove PGP Header + 移除 PGP 標頭 + + + + Add PGP Header + 加上 PGP 標頭 + + + + &View + 檢視 (&V) + + + + &Help + 說明 (&H) + + + + File + 檔案 + + + + Crypt + 編密 + + + + Key + 金鑰 + + + + Edit + 編輯 + + + + Special edit + 特殊編輯 + + + + Import key from... + 由此匯入金鑰... + + + + Import key + 匯入金鑰 + + + + Encrypt or decrypt File + 檔案加密或解密 + + + + File.. + 檔案... + + + + Ready + 就緒 + + + + Encrypt for: + 加密對象: + + + + Attached files: + 附加檔案: + + + + About + 關於 + + + + <center>This application allows simple encryption <br>and decryption of text messages or files.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Viriato/Phol (es), <br>Serse (it), Russell (my),<br>Alessandro (pt_br), Kirill (ru), Tom (vi)<br><br>If you have any questions or suggestions have a look<br/>at our <a href="http://gpg4usb.cpunk.de/contact.php">contact page</a> or send a mail to our<br/> mailing list at <a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a>. + <center>本應用程式讓你能夠輕鬆地對文字訊息和檔案<br>予以加密和解密。<br>本程式係採用 GPL v3 授權<br><br><b>開發者:</b><br>Bene, Heimer, Juergen, Nils, Ubbo<br><br><b>Translation:</b><br>Viriato/Phol (es), <br>Serse (it), Russell (my),<br>Alessandro (pt_br), Kirill (ru), Tom (vi), Jedi (zh_TW)<br><br>如果你有任何疑問或建議事項,請至我們的<br/><a href="http://gpg4usb.cpunk.de/contact.php">聯絡頁面</a>或寫信至我們的郵遞論壇: <br/><a href="mailto:gpg4usb@gzehn.de">gpg4usb@gzehn.de</a><br/>繁體中文翻譯方面的建議或更正事項,請直接<br/>與 Jedi 聯繫: <a href="mailto:JediLin@Gmail.com">JediLin@Gmail.com</a> + + + + <br><br> Built with Qt + <br><br> 建造工具: Qt + + + + and GPGME + 及 GPGME + + + + There is one unencrypted file in attachment folder + 在附加檔案資料夾內有個未加密的檔案 + + + + There are + 在附加檔案資料夾內有 + + + + unencrypted files in attachment folder + 個未加密的檔案 + + + + MimeTab + + + Decode quoted printable + QP 解碼 + + + + Try to recognize quoted printable. + 嘗試辨認 QP 編碼過的內容。 + + + + Parse PGP/MIME (Experimental) + 剖析 PGP/MIME (實驗性功能) + + + + Try to split attachments from PGP-MIME ecrypted messages. + 嘗試將附加檔案從 PGP/MIME 加密過的訊息中分離出來 + + + + Open with external application (Experimental) + 以外部應用程式開啟 (實驗性功能) + + + + Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol> + 按照附加檔案的檔案型別,以預設的應用程式開啟。<br>這個行為至少有兩種可能的問題:<ol><li>檔案需要先以未加密的型態儲存於附加檔案資料夾。<br>你必須要自己手動清理這個資料夾。</li><li>外部應用程式可能會自己產生暫存檔。</li></ol> + + + + Enable opening with external applications. + 啟用以外部應用程式開啟檔案的功能。 + + + + QuitDialog + + + Unsaved files + 未儲存的檔案 + + + + <h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3> + <h3>%1 個檔案含有未儲存的資訊。<br/>請問是否要在關閉前儲存這些變更?</h3> + + + + Check the files you want to save: + 請核選欲儲存的檔案: + + + + <b>Note:</b> If you don't save these files, all changes are lost.<br/> + <b>注意:</b> 如果你不儲存這些檔案,將失去所有的變動。<br/> + + + + SettingsDialog + + + General + 一般 + + + + Appearance + 外觀 + + + + PGP/Mime + PGP/MIME + + + + Keyserver + 金鑰伺服器 + + + + Advanced + 進階 + + + + Settings + 設定 + + + + System Default + 系統預設 + + + + TextEdit + + + untitled + 未命名 + + + + Open file + 開啟檔案 + + + + + Application + 應用程式 + + + + + Cannot read file %1: +%2. + 無法讀取檔案 %1: +%2。 + + + + File + 檔案 + + + + Cannot write file %1: +%2. + 無法寫入檔案 %1: +%2。 + + + + Save file + 儲存檔案 + + + + Unsaved document + 未儲存的文件 + + + + <h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3> + <h3>此文件 "%1" 業已更動。<br/>請問你是否想要儲存你所做的變更?</h3> + + + + <b>Note:</b> If you don't save these files, all changes are lost.<br/> + <b>注意:</b> 如果你不儲存這些檔案,將失去所有的變動。<br/> + + + + VerifyDetailsDialog + + + Signaturedetails + 簽章詳細資訊 + + + + Error Validating signature + 驗證簽章時出錯 + + + + Text was completely signed on + %1 by: + + 文字係經完整簽署於 + %1 由: + + + + + Text was partially signed on + %1 by: + + 文字係經部分簽署於 + %1 由: + + + + + VerifyKeyDetailBox + + + Import from keyserver + 從金鑰伺服器匯入 + + + + + + Status: + 狀態: + + + + + Fingerprint: + 指紋: + + + + Key not present in keylist + 金鑰不存在於金鑰清單 + + + + Key not present with id 0x + 具此 ID 的金鑰不存在: 0x + + + + + Name: + 姓名: + + + + + EMail: + 電子郵件: + + + + OK + OK + + + + Error for key with id 0x + 具此 ID 的金鑰出錯: 0x + + + + VerifyNotification + + + Import missing key from Keyserver + 從金鑰伺服器匯入缺少的金鑰 + + + + Show detailed verify information + 顯示詳細的驗證資訊 + + + + Details + 詳細資訊 + + + + Key not present with id 0x + 具此 ID 之金鑰不存在: 0x + + + + Error validating signature by: + 驗證以下簽章時出錯: + + + + Text was completely signed by: + 文字係經此人完整簽署: + + + + Text was partially signed by: + 文字係經此人部分簽署: + + + + Error for key with fingerprint + 具此指紋之金鑰出錯: + + + + Wizard + + + First Start Wizard + 初次啟動精靈 + + + + Import Error + 匯入出錯 + + + + Couldn't locate any keyring file in %1 + 無法在 %1 找到任何金鑰鑰匙圈 + + + + + Import error + 匯入出錯 + + + + Couldn't open private keyringfile: %1 + 無法開啟私鑰鑰匙圈檔案: %1 + + + + Couldn't open public keyringfile: %1 + 無法開啟公鑰鑰匙圈檔案: %1 + + + diff --git a/release/ts/qt_linux_he.qm b/release/ts/qt_linux_he.qm new file mode 100644 index 0000000..4ff507e Binary files /dev/null and b/release/ts/qt_linux_he.qm differ diff --git a/release/ts/qt_linux_sv.qm b/release/ts/qt_linux_sv.qm new file mode 100644 index 0000000..f3556bc Binary files /dev/null and b/release/ts/qt_linux_sv.qm differ diff --git a/release/ts/qt_linux_zh_TW.qm b/release/ts/qt_linux_zh_TW.qm new file mode 100644 index 0000000..a9a25b2 Binary files /dev/null and b/release/ts/qt_linux_zh_TW.qm differ diff --git a/release/ts/qt_linux_zh_TW.ts b/release/ts/qt_linux_zh_TW.ts new file mode 100644 index 0000000..de0f888 --- /dev/null +++ b/release/ts/qt_linux_zh_TW.ts @@ -0,0 +1,8129 @@ + + + + + MAC_APPLICATION_MENU + + + Services + 服務 + + + + Hide %1 + 隱藏%1 + + + + Hide Others + 隱藏其他 + + + + Show All + 顯示全部 + + + + Preferences... + 偏好設定⋯ + + + + Quit %1 + 結束 %1 + + + + About %1 + 關於 %1 + + + + AudioOutput + + + <html>The audio playback device <b>%1</b> does not work.<br/>Falling back to <b>%2</b>.</html> + <html>音效播放裝置 <b>%1</b> 未能運作。<br/>改用預設裝置 <b>%2</b>。</html> + + + + <html>Switching to the audio playback device <b>%1</b><br/>which just became available and has higher preference.</html> + <html>音效播放裝置 <b>%1</b> 已可使用,因為有較高優先權,因此將切換到該裝置。</html> + + + + Revert back to device '%1' + 回復到裝置 %1 + + + + CloseButton + + + Close Tab + 關閉分頁 + + + + PPDOptionsModel + + Name + 名稱 + + + Value + + + + + Phonon:: + + + Notifications + 通知 + + + + Music + 音樂 + + + + Video + 影像 + + + + Communication + 通訊 + + + + Games + 遊戲 + + + + Accessibility + 輔助裝置 + + + + Phonon::Gstreamer::Backend + + + Warning: You do not seem to have the package gstreamer0.10-plugins-good installed. + Some video features have been disabled. + 警告:您可能沒有安裝 gstreamer0.10-plugins-good。 + 有些影像的功能將被關閉。 + + + + Warning: You do not seem to have the base GStreamer plugins installed. + All audio and video support has been disabled + 警告:您可能沒有安裝 GStreamer 外掛程式。 所有音效與影像支援將被關閉。 + + + + Phonon::Gstreamer::MediaObject + + + Cannot start playback. + +Check your Gstreamer installation and make sure you +have libgstreamer-plugins-base installed. + 無法開始播放。 + +請檢查您的 Gstreamer 安裝,並確定您有安裝 +libgstreamer-plugins-base 套件。 + + + + A required codec is missing. You need to install the following codec(s) to play this content: %0 + 找不到需要的編解碼器。您需要安裝以下的套件來播放此內容:%0 + + + + + + + + + + + Could not open media source. + 無法開啟媒體來源。 + + + + Invalid source type. + 不合法的來源型態。 + + + + Could not locate media source. + 無法定位媒體來源。 + + + + Could not open audio device. The device is already in use. + 無法開啟音效裝置。裝置已在使用中。 + + + + Could not decode media source. + 無法解碼媒體來源。 + + + + Phonon::VolumeSlider + + + + Volume: %1% + 音量:%1% + + + + + + Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1% + 使用此滑動器來調整音量。最左邊的位置為 0%,最右邊的為 %1%。 + + + + Q3Accel + + + %1, %2 not defined + %1,%2 未定義 + + + + Ambiguous %1 not handled + 不明確的 %1 尚未處理 + + + + Q3DataTable + + + True + + + + + False + + + + + Insert + 插入 + + + + Update + 更新 + + + + Delete + 刪除 + + + + Q3FileDialog + + + Copy or Move a File + 複製或移動檔案 + + + + Read: %1 + 讀取:%1 + + + + + Write: %1 + 寫入:%1 + + + + + Cancel + 取消 + + + + + + + All Files (*) + 所有檔案 (*) + + + + Name + 名稱 + + + + Size + 大小 + + + + Type + 型態 + + + + Date + 日期 + + + + Attributes + 屬性 + + + + + &OK + 確定(&O) + + + + Look &in: + 尋找於(&I): + + + + + + File &name: + 檔名(&N): + + + + File &type: + 檔案型態(&T): + + + + Back + 返回 + + + + One directory up + 往上一層目錄 + + + + Create New Folder + 建立新資料夾 + + + + List View + 列表檢視 + + + + Detail View + 詳細檢視 + + + + Preview File Info + 預覽檔案資訊 + + + + Preview File Contents + 預覽檔案內容 + + + + Read-write + 可讀寫 + + + + Read-only + 唯讀 + + + + Write-only + 唯寫 + + + + Inaccessible + 無法存取 + + + + Symlink to File + 到檔案的符號連結 + + + + Symlink to Directory + 到目錄的符號連結 + + + + Symlink to Special + 到特殊節點的符號連結 + + + + File + 檔案 + + + + Dir + 目錄 + + + + Special + 特殊節點 + + + + + + Open + 開啟 + + + + + Save As + 另存新檔 + + + + + + &Open + 開啟(&O) + + + + + &Save + 儲存(&S) + + + + &Rename + 重新命名(&R) + + + + &Delete + 刪除(&D) + + + + R&eload + 重新載入(&E) + + + + Sort by &Name + 依名稱排序(&N) + + + + Sort by &Size + 依大小排序(&S) + + + + Sort by &Date + 依日期排序(&D) + + + + &Unsorted + 未排序(&U) + + + + Sort + 排序 + + + + Show &hidden files + 顯示隱藏檔(&H) + + + + the file + 此檔案 + + + + the directory + 此目錄 + + + + the symlink + 此符號連結 + + + + Delete %1 + 刪除 %1 + + + + <qt>Are you sure you wish to delete %1 "%2"?</qt> + <qt>您確定要刪除 %1 "%2" 嗎?</qt> + + + + &Yes + 是(&Y) + + + + &No + 否(&N) + + + + New Folder 1 + 新資料夾 1 + + + + New Folder + 新資料夾 + + + + New Folder %1 + 新資料夾 %1 + + + + Find Directory + 尋找目錄 + + + + + Directories + 目錄 + + + + Directory: + 目錄: + + + + + Error + 錯誤 + + + + %1 +File not found. +Check path and filename. + %1 +找不到檔案。 +請檢查路徑與檔名。 + + + + All Files (*.*) + 所有檔案 (*.*) + + + + Open + 開啟 + + + + Select a Directory + 請選擇一個目錄 + + + + Q3LocalFs + + + + Could not read directory +%1 + 無法讀取目錄 +%1 + + + + Could not create directory +%1 + 無法建立目錄 +%1 + + + + Could not remove file or directory +%1 + 無法移除目錄 +%1 + + + + Could not rename +%1 +to +%2 + 無法將 +%1 +重新命名為 +%2 + + + + Could not open +%1 + 無法開啟 +%1 + + + + Could not write +%1 + 無法寫入 +%1 + + + + Q3MainWindow + + + Line up + 排列 + + + + Customize... + 自訂... + + + + Q3NetworkProtocol + + + Operation stopped by the user + 使用者已中止操作 + + + + Q3ProgressDialog + + + + Cancel + 取消 + + + + Q3TabDialog + + + + OK + 確定 + + + + Apply + 套用 + + + + Help + 說明 + + + + Defaults + 預設 + + + + Cancel + 取消 + + + + Q3TextEdit + + + &Undo + 復原(&U) + + + + &Redo + 重做(&R) + + + + Cu&t + 剪下(&T) + + + + &Copy + 複製(&C) + + + + &Paste + 貼上(&P) + + + + Clear + 清除 + + + + + Select All + 全部選擇 + + + + Q3TitleBar + + + System + 系統 + + + + Restore up + 向上恢復 + + + + Minimize + 最小化 + + + + Restore down + 向下恢復 + + + + Maximize + 最大化 + + + + Close + 關閉 + + + + Contains commands to manipulate the window + 包含要操作此視窗的指令 + + + + Puts a minimized back to normal + 將最小化視窗放回原大小 + + + + Moves the window out of the way + 把視窗移開 + + + + Puts a maximized window back to normal + 將最大化視窗放回原大小 + + + + Makes the window full screen + 將視窗放大到全畫面 + + + + Closes the window + 關閉視窗 + + + + Displays the name of the window and contains controls to manipulate it + 顯示視窗名稱,並包含操作它的控制元件 + + + + Q3ToolBar + + + More... + 更多... + + + + Q3UrlOperator + + + + + The protocol `%1' is not supported + 協定 %1 未支援 + + + + The protocol `%1' does not support listing directories + 協定 %1 未支援列出目錄 + + + + The protocol `%1' does not support creating new directories + 協定 %1 未支援建立新目錄 + + + + The protocol `%1' does not support removing files or directories + 協定 %1 未支援移除檔案或目錄 + + + + The protocol `%1' does not support renaming files or directories + 協定 %1 未支援重新命名檔案或目錄 + + + + The protocol `%1' does not support getting files + 協定 %1 未支援取得檔案 + + + + The protocol `%1' does not support putting files + 協定 %1 未支援寫入檔案 + + + + + The protocol `%1' does not support copying or moving files or directories + 協定 %1 未支援複製或移動檔案或目錄 + + + + + (unknown) + (未知) + + + + Q3Wizard + + + &Cancel + 取消(&C) + + + + < &Back + <返回(&B) + + + + &Next > + 下一個(&N)> + + + + &Finish + 完成(&F) + + + + &Help + 說明(&H) + + + + QAbstractSocket + + + + + + Host not found + 找不到主機 + + + + + + Connection refused + 連線被拒 + + + + Connection timed out + 連線逾時 + + + + + + Operation on socket is not supported + Socket 的操作未被支援 + + + + Socket operation timed out + Socket 操作逾時 + + + + Socket is not connected + Socket 未連線 + + + + Network unreachable + 無法使用網路 + + + + QAbstractSpinBox + + + &Step up + 單步向上(&S) + + + + Step &down + 單步向下(&D) + + + + &Select All + 全部選擇(&S) + + + + QApplication + + + Activate + 啟動 + + + + Executable '%1' requires Qt %2, found Qt %3. + 執行檔 %1 需要 Qt %2,但只找到 Qt %3。 + + + + Incompatible Qt Library Error + Qt 函式庫不相容的錯誤 + + + + QT_LAYOUT_DIRECTION + Translate this string to the string 'LTR' in left-to-right languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to get proper widget layout. + LTR + + + + Activates the program's main window + 啟動程式的主視窗 + + + + QAxSelect + + + Select ActiveX Control + 選擇 ActiveX 控制 + + + + OK + 確定 + + + + &Cancel + 取消(&C) + + + + COM &Object: + COM 物件(&O) + + + + QCheckBox + + + Uncheck + 取消勾選 + + + + Check + 勾選 + + + + Toggle + 切換 + + + + QColorDialog + + + Hu&e: + 色調(&E): + + + + &Sat: + 飽和度(&S): + + + + &Val: + 亮度(&V): + + + + &Red: + 紅(&R): + + + + &Green: + 綠(&G): + + + + Bl&ue: + 藍(&U): + + + + A&lpha channel: + Alpha 色頻(&L): + + + + Select Color + 選擇顏色 + + + + &Basic colors + 基本顏色(&B) + + + + &Custom colors + 自訂顏色(&C) + + + &Define Custom Colors >> + 定義自訂顏色(&D)>> + + + OK + 確定 + + + Cancel + 取消 + + + + &Add to Custom Colors + 新增到自訂顏色(&A) + + + Select color + 選擇顏色 + + + + QComboBox + + + + Open + 開啟 + + + + False + + + + + True + + + + + Close + 關閉 + + + + QCoreApplication + + %1: permission denied + QSystemSemaphore + %1:存取被拒 + + + %1: already exists + QSystemSemaphore + %1:已存在 + + + %1: doesn't exists + QSystemSemaphore + %1:不存在 + + + %1: out of resources + QSystemSemaphore + %1:資源不足 + + + %1: unknown error %2 + QSystemSemaphore + %1:未知的錯誤 %2 + + + + %1: key is empty + QSystemSemaphore + %1:鍵值是空的 + + + + %1: unable to make key + QSystemSemaphore + %1:無法產生鍵值 + + + + %1: ftok failed + QSystemSemaphore + %1:ftok 失敗 + + + + QDB2Driver + + + Unable to connect + 無法連接 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + Unable to set autocommit + 無法設定自動提交 + + + + QDB2Result + + + + Unable to execute statement + 無法執行敘述 + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to bind variable + 無法結合變數 + + + + Unable to fetch record %1 + 無法抓取紀錄 %1 + + + + Unable to fetch next + 無法抓取下一筆 + + + + Unable to fetch first + 無法抓取第一筆 + + + + QDateTimeEdit + + + AM + AM + + + + am + am + + + + PM + PM + + + + pm + pm + + + + QDial + + + QDial + QDial + + + + SpeedoMeter + SpeedoMeter + + + + SliderHandle + SliderHandle + + + + QDialog + + + What's This? + 這是什麼? + + + + Done + 完成 + + + + QDialogButtonBox + + + + + OK + 確定 + + + + Save + 儲存 + + + + &Save + 儲存(&S) + + + + Open + 開啟 + + + + Cancel + 取消 + + + + &Cancel + 取消(&C) + + + + Close + 關閉 + + + + &Close + 關閉(&C) + + + + Apply + 套用 + + + + Reset + 重置 + + + + Help + 說明 + + + + Don't Save + 不要儲存 + + + + Discard + 丟棄 + + + + &Yes + 是(&Y) + + + + Yes to &All + 全部回答是(&A) + + + + &No + 否(&N) + + + + N&o to All + 全部回答否(&O) + + + + Save All + 全部儲存 + + + + Abort + 中止 + + + + Retry + 重試 + + + + Ignore + 忽略 + + + + Restore Defaults + 回復預設值 + + + + Close without Saving + 關閉而不儲存 + + + + &OK + 確定(&O) + + + + QDirModel + + + Name + 名稱 + + + + Size + 大小 + + + + Kind + Match OS X Finder + 種類 + + + + Type + All other platforms + 型態 + + + + Date Modified + 變更日期 + + + + QDockWidget + + + Close + 關閉 + + + + Dock + 嵌入 + + + + Float + 飄浮 + + + + QDoubleSpinBox + + + More + 更多 + + + + Less + 較少 + + + + QErrorMessage + + + Debug Message: + 除錯訊息: + + + + Warning: + 警告: + + + + Fatal Error: + 嚴重錯誤: + + + + &Show this message again + 再度顯示此訊息(&S) + + + + &OK + 確定(&O) + + + + QFile + + + + Destination file exists + 目標檔已存在 + + + + Cannot remove source file + + + + + Cannot open %1 for input + 無法開啟 %1 以輸入 + + + + Cannot open for output + 無法開啟 %1 以輸出 + + + + Failure to write block + 寫入區塊時失敗 + + + + Cannot create %1 for output + 無法建立 %1 以輸出 + + + + QFileDialog + + + + All Files (*) + 所有檔案 (*) + + + + Directories + 目錄 + + + + + + + &Open + 開啟(&O) + + + + + &Save + 儲存(&S) + + + + Open + 開啟 + + + + %1 already exists. +Do you want to replace it? + %1 已存在 +您要取代它嗎? + + + + %1 +File not found. +Please verify the correct file name was given. + %1 +找不到檔案。 +請檢查檔名是否正確。 + + + + My Computer + 我的電腦 + + + + &Rename + 重新命名(&R) + + + + &Delete + 刪除(&D) + + + + Show &hidden files + 顯示隱藏檔(&H) + + + + + Back + 返回 + + + + + Parent Directory + 父目錄 + + + + + List View + 列表檢視 + + + + + Detail View + 詳細檢視 + + + + + Files of type: + 檔案型態: + + + + + Directory: + 目錄: + + + +File not found. +Please verify the correct file name was given + +檔案找不到。 +請檢查檔名是否正確。 + + + + + %1 +Directory not found. +Please verify the correct directory name was given. + %1 +找不到目錄。 +請檢查目錄名稱是否正確。 + + + + '%1' is write protected. +Do you want to delete it anyway? + %1 有寫入保護。 +您確定要刪除它嗎? + + + + Are sure you want to delete '%1'? + 您確定要刪除 %1 嗎? + + + + Could not delete directory. + 無法刪除目錄。 + + + + Recent Places + 最近的地方 + + + + All Files (*.*) + 所有檔案 (*.*) + + + + Save As + 另存新檔 + + + + Drive + 磁碟 + + + + + File + 檔案 + + + + Unknown + 未知 + + + + Find Directory + 尋找目錄 + + + + Show + 顯示 + + + + + Forward + 往前 + + + + New Folder + 新資料夾 + + + + &New Folder + 新增資料夾(&N) + + + + + &Choose + 選擇(&C) + + + + Remove + 移除 + + + + + File &name: + 檔名(&N): + + + + + Look in: + 尋找於: + + + + + Create New Folder + 建立新資料夾 + + + + QFileSystemModel + + + Invalid filename + 不合法的檔名 + + + + <b>The name "%1" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks. + <b>無法使用名稱 "%1"。</b><p>請使用其它名稱,字元數少一點,或是不要有標點符號。 + + + + Name + 名稱 + + + + Size + 大小 + + + + Kind + Match OS X Finder + 種類 + + + + Type + All other platforms + 型態 + + + + Date Modified + 變更日期 + + + + My Computer + 我的電腦 + + + + Computer + 電腦 + + + + %1 TB + %1 TB + + + + %1 GB + %1 GB + + + + %1 MB + %1 MB + + + + %1 KB + %1 KB + + + + %1 bytes + %1 位元組 + + + + QFontDatabase + + + + Normal + 正常 + + + + + + Bold + 粗體 + + + + + Demi Bold + 半粗體 + + + + + + Black + 黑體 + + + + Demi + 半體 + + + + + Light + 輕體 + + + + + Italic + 斜體 + + + + + Oblique + 傾斜體 + + + + Any + 任何 + + + + Latin + 拉丁 + + + + Greek + 希臘 + + + + Cyrillic + 斯拉夫 + + + + Armenian + 亞美尼亞 + + + + Hebrew + 希伯來 + + + + Arabic + 阿拉伯 + + + + Syriac + 敘利亞 + + + + Thaana + Thaana + + + + Devanagari + Devanagari + + + + Bengali + 孟加拉 + + + + Gurmukhi + Gurmukhi + + + + Gujarati + Gujarati + + + + Oriya + Oriya + + + + Tamil + 坦米爾 + + + + Telugu + Telugu + + + + Kannada + 坎達那 + + + + Malayalam + 馬來語 + + + + Sinhala + 錫蘭 + + + + Thai + 泰語 + + + + Lao + 寮國 + + + + Tibetan + 西藏 + + + + Myanmar + 緬甸 + + + + Georgian + 喬治亞 + + + + Khmer + 高棉 + + + + Simplified Chinese + 簡體中文 + + + + Traditional Chinese + 繁體中文 + + + + Japanese + 日語 + + + + Korean + 韓語 + + + + Vietnamese + 越南 + + + + Symbol + 符號 + + + + Ogham + 歐甘 + + + + Runic + 盧恩 + + + + QFontDialog + + + &Font + 字型(&F) + + + + Font st&yle + 字型樣式(&Y) + + + + &Size + 大小(&S) + + + + Effects + 效果 + + + + Stri&keout + 刪除線(&K) + + + + &Underline + 底線(&U) + + + + Sample + 範例 + + + + Wr&iting System + 寫入系統(&I) + + + + + Select Font + 選擇字型 + + + + QFtp + + + + Not connected + 未連線 + + + + + Host %1 not found + 找不到主機 %1 + + + + + Connection refused to host %1 + 連線到主機 %1 被拒 + + + + Connection timed out to host %1 + 連線到主機 %1 逾時 + + + + + + Connected to host %1 + 已連接到主機 %1 + + + + + Connection refused for data connection + 資料連線被拒 + + + + + + + Unknown error + 未知的錯誤 + + + + + Connecting to host failed: +%1 + 連線到主機失敗: +%1 + + + + + Login failed: +%1 + 登入失敗: +%1 + + + + + Listing directory failed: +%1 + 列出目錄時失敗: +%1 + + + + + Changing directory failed: +%1 + 變更目錄時失敗: +%1 + + + + + Downloading file failed: +%1 + 下載檔案時失敗: +%1 + + + + + Uploading file failed: +%1 + 上傳檔案時失敗: +%1 + + + + + Removing file failed: +%1 + 移除檔案時失敗: +%1 + + + + + Creating directory failed: +%1 + 建立目錄時失敗: +%1 + + + + + Removing directory failed: +%1 + 移除目錄時失敗: +%1 + + + + + + Connection closed + 連線已關閉 + + + + Host %1 found + 找到主機 %1 + + + + Connection to %1 closed + 到 %1 的連線已關閉 + + + + Host found + 找到主機 + + + + Connected to host + 已連線到主機 + + + + QHostInfo + + + Unknown error + 未知的錯誤 + + + + QHostInfoAgent + + + + + + + + + + Host not found + 找不到主機 + + + + + + + Unknown address type + 未知的位址型態 + + + + + + Unknown error + 未知的錯誤 + + + + QHttp + + + + + + Unknown error + 未知的錯誤 + + + + + Request aborted + 要求中止 + + + + + No server set to connect to + 沒有設定要連線到哪個伺服器 + + + + + Wrong content length + 錯誤的內容長度 + + + + + Server closed connection unexpectedly + 伺服器無預警關閉連線 + + + + Unknown authentication method + + + + + Error writing response to device + 寫入回應到裝置時發生錯誤 + + + + + Connection refused + 連線被拒 + + + + + + Host %1 not found + 找不到主機 %1 + + + + + + + HTTP request failed + HTTP 要求失敗 + + + + + Invalid HTTP response header + 不合法的 HTTP 回覆標頭 + + + + + + + Invalid HTTP chunked body + 不合法的 HTTP 區塊主體 + + + + Host %1 found + 找到主機 %1 + + + + Connected to host %1 + 已連接到主機 %1 + + + + Connection to %1 closed + 到 %1 的連線已關閉 + + + + Host found + 找到主機 + + + + Connected to host + 已連線到主機 + + + + + Connection closed + 連線已關閉 + + + + Proxy authentication required + 代理伺服器需要認證 + + + + Authentication required + 需要認證 + + + + Connection refused (or timed out) + 連線被拒(或連線逾時) + + + + Proxy requires authentication + 代理伺服器需要認證 + + + + Host requires authentication + 主機需要認證 + + + + Data corrupted + 資料已損毀 + + + + Unknown protocol specified + 指定了未知的協定 + + + + SSL handshake failed + SSL 溝通失敗 + + + + HTTPS connection requested but SSL support not compiled in + HTTPS 連線需要的 SSL 支援並未編譯進來 + + + + QHttpSocketEngine + + + Did not receive HTTP response from proxy + 未從代理伺服器接收到 HTTP 回應 + + + + Error parsing authentication request from proxy + 剖析從代理伺服器傳來的認證要求時發生錯誤 + + + + Authentication required + 需要認證 + + + + Proxy denied connection + 代理伺服器拒絕連線 + + + + Error communicating with HTTP proxy + 與 HTTP 代理伺服器聯繫時發生錯誤 + + + + Proxy server not found + 找不到代理伺服器 + + + + Proxy connection refused + 代理伺服器連線被拒 + + + + Proxy server connection timed out + 代理伺服器連線逾時 + + + + Proxy connection closed prematurely + 代理伺服器連線已不正常關閉 + + + + QIBaseDriver + + + Error opening database + 開啟資料庫發生錯誤 + + + + Could not start transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QIBaseResult + + + Unable to create BLOB + 無法建立 BLOB + + + + Unable to write BLOB + 無法寫入 BLOB + + + + Unable to open BLOB + 無法開啟 BLOB + + + + Unable to read BLOB + 無法讀取 BLOB + + + + + Could not find array + 找不到陣列 + + + + Could not get array data + 無法取得陣列資料 + + + + Could not get query info + 無法取得查詢資訊 + + + + Could not start transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Could not allocate statement + 無法配置敘述 + + + + Could not prepare statement + 無法準備敘述 + + + + + Could not describe input statement + 無法描述輸入敘述 + + + + Could not describe statement + 無法描述敘述 + + + + Unable to close statement + 無法關閉敘述 + + + + Unable to execute query + 無法執行查詢 + + + + Could not fetch next item + 無法抓取下一個項目 + + + + Could not get statement info + 無法取得敘述資訊 + + + + QIODevice + + + Permission denied + 權限不足 + + + + Too many open files + 開啟過多檔案 + + + + No such file or directory + 找不到該檔案或目錄 + + + + No space left on device + 裝置上已無空間 + + + + Unknown error + 未知的錯誤 + + + + QInputContext + + + XIM + XIM + + + + XIM input method + XIM 輸入法 + + + + Windows input method + Windows 輸入法 + + + + Mac OS X input method + Mac OS X 輸入法 + + + + QInputDialog + + + Enter a value: + 請輸入值: + + + + QLibrary + + QLibrary::load_sys: Cannot load %1 (%2) + QLibrary::load_sys: 無法載入 %1 (%2) + + + QLibrary::unload_sys: Cannot unload %1 (%2) + QLibrary::unload_sys: 無法卸載 %1 (%2) + + + QLibrary::resolve_sys: Symbol "%1" undefined in %2 (%3) + QLibrary::resolve_sys: 符號 "%1" 未定義於 %2 (%3) + + + + Could not mmap '%1': %2 + 無法 mmap '%1':%2 + + + + Plugin verification data mismatch in '%1' + 在 %1 中的外掛程式確認資料不符合 + + + + Could not unmap '%1': %2 + 無法 unmap '%1':%2 + + + + The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5] + 外掛程式 %1 使用不相容的 Qt 函式庫(%2.%3.%4)【%5】 + + + + The plugin '%1' uses incompatible Qt library. Expected build key "%2", got "%3" + 外掛程式 %1 使用不相容的 Qt 函式庫。預期建構鑰 %2,卻得到 %3 + + + + Unknown error + 未知的錯誤 + + + + + The shared library was not found. + 找不到分享函式庫 + + + + The file '%1' is not a valid Qt plugin. + 檔案 %1 不是合法的 Qt 外掛程式。 + + + + The plugin '%1' uses incompatible Qt library. (Cannot mix debug and release libraries.) + 外掛程式 %1 使用不相容的 Qt 函式庫。(不能將除錯與釋出版的函式庫混在一起。) + + + + + Cannot load library %1: %2 + 無法載入函式庫 %1:%2 + + + + + Cannot unload library %1: %2 + 無法卸載函式庫 %1:%2 + + + + + Cannot resolve symbol "%1" in %2: %3 + 無法反解 %2 內的符號 %1:%3 + + + + QLineEdit + + + &Undo + 復原(&U) + + + + &Redo + 重做(&R) + + + + Cu&t + 剪下(&T) + + + + &Copy + 複製(&C) + + + + &Paste + 貼上(&P) + + + + Delete + 刪除 + + + + Select All + 全部選擇 + + + + QLocalServer + + + + %1: Name error + %1:名稱錯誤 + + + + %1: Permission denied + %1:存取被拒 + + + + %1: Address in use + %1:位址使用中 + + + + + %1: Unknown error %2 + %1:未知的錯誤 %2 + + + + QLocalSocket + + + + %1: Connection refused + %1:連線被拒 + + + + + %1: Remote closed + %1:遠端已關閉 + + + + + + + %1: Invalid name + %1:不合法的名稱 + + + + + %1: Socket access error + %1:Socket 位址錯誤 + + + + + %1: Socket resource error + %1:Socket 資源錯誤 + + + + + %1: Socket operation timed out + %1:Socket 操作逾時 + + + + + %1: Datagram too large + %1:資料包過大 + + + + + + %1: Connection error + %1:連線錯誤 + + + + + %1: The socket operation is not supported + %1:socket 操作未支援 + + + + %1: Unknown error + %1:未知的錯誤 + + + + + %1: Unknown error %2 + %1:未知的錯誤 %2 + + + + QMYSQLDriver + + + Unable to open database ' + 無法開啟資料庫 + + + + Unable to connect + 無法連線 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QMYSQLResult + + + Unable to fetch data + 無法抓取資料 + + + + Unable to execute query + 無法執行查詢 + + + + Unable to store result + 無法儲存結果 + + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to reset statement + 無法重置敘述 + + + + Unable to bind value + 無法結合數值 + + + + Unable to execute statement + 無法執行敘述 + + + + + Unable to bind outvalues + 無法結合輸出值 + + + + Unable to store statement results + 無法儲存敘述結果 + + + + Unable to execute next query + 無法執行下一個查詢 + + + + Unable to store next result + 無法儲存下一個結果 + + + + QMdiArea + + + (Untitled) + (未命名) + + + + QMdiSubWindow + + + %1 - [%2] + %1 - [%2] + + + + Close + 關閉 + + + + Minimize + 最小化 + + + + Restore Down + 向下恢復 + + + + &Restore + 回復(&R) + + + + &Move + 移動(&M) + + + + &Size + 大小(&S) + + + + Mi&nimize + 最小化(&N) + + + + Ma&ximize + 最大化(&X) + + + + Stay on &Top + 留在頂端(&T) + + + + &Close + 關閉(&C) + + + + - [%1] + - [%1] + + + + Maximize + 最大化 + + + + Unshade + 取消遮蔽 + + + + Shade + 遮蔽 + + + + Restore + 回復 + + + + Help + 說明 + + + + Menu + 選單 + + + + QMenu + + + + Close + 關閉 + + + + + Open + 開啟 + + + + + + Execute + 執行 + + + + QMenuBar + + About + 關於 + + + Config + 設定 + + + Preference + 喜好設定 + + + Options + 選項 + + + Setting + 設定 + + + Setup + 設定 + + + Quit + 離開 + + + Exit + 離開 + + + About %1 + 關於 %1 + + + About Qt + 關於 Qt + + + Preferences + 喜好設定 + + + Quit %1 + 離開 %1 + + + + QMessageBox + + + Help + 說明 + + + + + + + OK + 確定 + + + + About Qt + 關於 Qt + + + <p>This program uses Qt version %1.</p> + <p> 這個程式使用 Qt 版本 %1</p> + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qtopia Core.</p><p>Qt is a Trolltech product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + <h3>關於 Qt</h3>%1<p>Qt 為一個跨平台的 C++ 開發工具。</p><p>Qt 提供各平台相容機制,只要寫一份程式碼,就可以在 MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux 與各主要的商業 Unix 平台上編譯。Qt 也可以用 Qtopia Core 用於嵌入式系統。</p><p>Qt 為 Trolltech 的產品。詳情請參考 <a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + + Show Details... + 顯示詳情... + + + + Hide Details... + 隱藏詳情... + + + + <h3>About Qt</h3><p>This program uses Qt version %1.</p><p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is available under three different licensing options designed to accommodate the needs of our various users.</p>Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of the GNU LGPL version 2.1 or GNU GPL version 3.0.</p><p>Qt licensed under the GNU LGPL version 2.1 is appropriate for the development of Qt applications (proprietary or open source) provided you can comply with the terms and conditions of the GNU LGPL version 2.1.</p><p>Qt licensed under the GNU General Public License version 3.0 is appropriate for the development of Qt applications where you wish to use such applications in combination with software subject to the terms of the GNU GPL version 3.0 or where you are otherwise willing to comply with the terms of the GNU GPL version 3.0.</p><p>Please see <a href="http://qt.nokia.com/products/licensing">qt.nokia.com/products/licensing</a> for an overview of Qt licensing.</p><p>Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).</p><p>Qt is a Nokia product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is a Nokia product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + <h3>關於 Qt</h3>%1<p>Qt 為一個跨平台的 C++ 開發工具。</p><p>Qt 提供各平台相容機制,只要寫一份程式碼,就可以在 MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux 與各主要的商業 Unix 平台上編譯。Qt 也有用於嵌入式 Linux 與 Windows CE 的版本。</p><p>Qt 為 Nokia 的產品。詳情請參考 <a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + <p>This program uses Qt Open Source Edition version %1.</p><p>Qt Open Source Edition is intended for the development of Open Source applications. You need a commercial Qt license for development of proprietary (closed source) applications.</p><p>Please see <a href="http://qt.nokia.com/company/model/">qt.nokia.com/company/model/</a> for an overview of Qt licensing.</p> + <p>這個程式使用了 Qt 開放源碼版本 %1。</p><p>Qt 開放源碼版本是專門為了開發開放源碼應用程式使用的版本。若是您要開發專利私有(封閉)軟體,您需要 Qt 的商業授權。</p><p>Qt 的授權概要請參考 <a href="http://qt.nokia.com/company/model/">qt.nokia.com/company/model/</a>。</p> + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt Embedded.</p><p>Qt is a Trolltech product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + <h3>關於 Qt</h3>%1<p>Qt 為一個跨平台的 C++ 開發工具。</p><p>Qt 提供各平台相容機制,只要寫一份程式碼,就可以在 MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux 與各主要的商業 Unix 平台上編譯。Qt 也可以用 Qtopia Core 用於嵌入式系統。</p><p>Qt 為 Trolltech 的產品。詳情請參考 <a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + + QMultiInputContext + + + Select IM + 選擇輸入法 + + + + QMultiInputContextPlugin + + + Multiple input method switcher + 多重輸入法切換器 + + + + Multiple input method switcher that uses the context menu of the text widgets + 使用文字元件中的內文選單的多重輸入法切換器 + + + + QNativeSocketEngine + + + The remote host closed the connection + 遠端主機關閉了連線 + + + + Network operation timed out + 網路操作逾時 + + + + Out of resources + 資源不足 + + + + Unsupported socket operation + 未支援的 socket 操作 + + + + Protocol type not supported + 協定型態未支援 + + + + Invalid socket descriptor + 不合法的 socket 描述子 + + + + Network unreachable + 無法使用網路 + + + + Permission denied + 權限不足 + + + + Connection timed out + 連線逾時 + + + + Connection refused + 連線被拒 + + + + The bound address is already in use + 結合的位址已經在使用中 + + + + The address is not available + 無法取得位址 + + + + The address is protected + 此位址已被保護 + + + + Unable to send a message + 無法送出訊息 + + + + Unable to receive a message + 無法接收訊息 + + + + Unable to write + 無法寫入 + + + + Network error + 網路錯誤 + + + + Another socket is already listening on the same port + 另一個 socket 已經在監聽同一個連接埠 + + + + Unable to initialize non-blocking socket + 無法初始化非阻擋性 socket + + + + Unable to initialize broadcast socket + 無法初始化廣播 socket + + + + Attempt to use IPv6 socket on a platform with no IPv6 support + 試圖在沒有 IPv6 支援的平台上使用 IPv6 socket + + + + Host unreachable + 無法連線到主機 + + + + Datagram was too large to send + 資料過大無法送出 + + + + Operation on non-socket + 對非 socket 操作 + + + + Unknown error + 未知的錯誤 + + + + The proxy type is invalid for this operation + 代理伺服器型態無法支援此操作 + + + + QNetworkAccessCacheBackend + + + Error opening %1 + 開啟 %1 發生錯誤 + + + + QNetworkAccessFileBackend + + + Request for opening non-local file %1 + 要求開啟非本地端檔案 %1 + + + + Error opening %1: %2 + 開啟 %1 發生錯誤:%2 + + + + Write error writing to %1: %2 + 寫入 %1 時發生錯誤:%2 + + + + Cannot open %1: Path is a directory + 無法開啟 %1:此路徑是一個目錄 + + + + Read error reading from %1: %2 + 從 %1 讀取錯誤:%2 + + + + QNetworkAccessFtpBackend + + + No suitable proxy found + 找不到合適的代理伺服器 + + + + Cannot open %1: is a directory + 無法開啟 %1:是一個目錄 + + + + Logging in to %1 failed: authentication required + 登入 %1 失敗:需要認證 + + + + Error while downloading %1: %2 + 下載 %1 時發生錯誤:%2 + + + + Error while uploading %1: %2 + 上傳 %1 時發生錯誤:%2 + + + + QNetworkAccessHttpBackend + + + No suitable proxy found + 找不到合適的代理伺服器 + + + + QNetworkReply + + + Error downloading %1 - server replied: %2 + 下載 %1 時發生錯誤─伺服器回應:%2 + + + + Protocol "%1" is unknown + 未知的協定 %1 + + + + QNetworkReplyImpl + + + + Operation canceled + 取消操作 + + + + QOCIDriver + + + Unable to logon + 無法登入 + + + + Unable to initialize + QOCIDriver + 無法初始化 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QOCIResult + + + + + Unable to bind column for batch execute + 無法結合欄位以做批次執行 + + + + Unable to execute batch statement + 無法執行批次敘述 + + + + Unable to goto next + 無法跳到下一個 + + + + Unable to alloc statement + 無法配置敘述 + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to bind value + 無法結合數值 + + + Unable to execute select statement + 無法執行選取的敘述 + + + + Unable to execute statement + 無法執行敘述 + + + + QODBCDriver + + + Unable to connect + 無法連接 + + + + Unable to connect - Driver doesn't support all needed functionality + 無法連接─驅動程式無法支援所有需要的功能 + + + + Unable to disable autocommit + 無法關閉自動提交功能 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + Unable to enable autocommit + 無法開啟自動提交功能 + + + + QODBCResult + + + + QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration + QODBCResult::reset: 無法設定 SQL_CURSOR_STATIC 做為敘述屬性。請檢查您的 ODBC 驅動程式的設定 + + + + + Unable to execute statement + 無法執行敘述 + + + + Unable to fetch next + 無法抓取下一筆 + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to bind variable + 無法結合變數 + + + + + + Unable to fetch last + 無法抓取最後一筆 + + + + Unable to fetch + 無法抓取 + + + + Unable to fetch first + 無法抓取第一筆 + + + + Unable to fetch previous + 無法抓取前一筆 + + + + QObject + + + Home + 首頁 + + + + Operation not supported on %1 + 在 %1 上不支援此操作 + + + + Invalid URI: %1 + 不合法的網址:%1 + + + + Write error writing to %1: %2 + 寫入 %1 時發生錯誤:%2 + + + + Read error reading from %1: %2 + 從 %1 讀取錯誤:%2 + + + + Socket error on %1: %2 + %1 上發生 socket 錯誤:%2 + + + + Remote host closed the connection prematurely on %1 + 於 %1 上遠端主機關閉了不正常的連線 + + + + Protocol error: packet of size 0 received + 協定錯誤:接收到大小為 0 的封包 + + + + + No host name given + 未指定主機 + + + + QPPDOptionsModel + + + Name + 名稱 + + + + Value + + + + + QPSQLDriver + + + Unable to connect + 無法連線 + + + + Could not begin transaction + 無法開始事務 + + + + Could not commit transaction + 無法提交事務 + + + + Could not rollback transaction + 無法反轉事務 + + + + Unable to subscribe + 無法訂閱 + + + + Unable to unsubscribe + 無法取消訂閱 + + + + QPSQLResult + + + Unable to create query + 無法建立查詢 + + + + Unable to prepare statement + 無法準備敘述 + + + + QPageSetupWidget + + + Centimeters (cm) + 公分 + + + + Millimeters (mm) + 公厘 + + + + Inches (in) + 英吋 + + + + Points (pt) + + + + + Form + 表單 + + + + Paper + 紙張 + + + + Page size: + 紙張大小: + + + + Width: + 寬度: + + + + Height: + 高度: + + + + Paper source: + 紙張來源: + + + + Orientation + 方向 + + + + Portrait + 縱向 + + + + Landscape + 橫向 + + + + Reverse landscape + 反序橫向 + + + + Reverse portrait + 反序縱向 + + + + Margins + 邊緣 + + + + top margin + 上緣 + + + + left margin + 左緣 + + + + right margin + 右緣 + + + + bottom margin + 下緣 + + + + QPluginLoader + + + Unknown error + 未知的錯誤 + + + + The plugin was not loaded. + 外掛程式未載入。 + + + + QPrintDialog + + + locally connected + 本地連接 + + + + + Aliases: %1 + 別名:%1 + + + + + unknown + 未知 + + + Portrait + 縱向 + + + Landscape + 橫向 + + + + A0 (841 x 1189 mm) + A0 (841 x 1189 mm) + + + + A1 (594 x 841 mm) + A1 (594 x 841 mm) + + + + A2 (420 x 594 mm) + A2 (420 x 594 mm) + + + + A3 (297 x 420 mm) + A3 (297 x 420 mm) + + + + A4 (210 x 297 mm, 8.26 x 11.7 inches) + A4 (210 x 297 mm, 8.26 x 11.7 英吋) + + + + A5 (148 x 210 mm) + A5 (148 x 210 mm) + + + + A6 (105 x 148 mm) + A6 (105 x 148 mm) + + + + A7 (74 x 105 mm) + A7 (74 x 105 mm) + + + + A8 (52 x 74 mm) + A8 (52 x 74 mm) + + + + A9 (37 x 52 mm) + A9 (37 x 52 mm) + + + + B0 (1000 x 1414 mm) + B0 (1000 x 1414 mm) + + + + B1 (707 x 1000 mm) + B1 (707 x 1000 mm) + + + + B2 (500 x 707 mm) + B2 (500 x 707 mm) + + + + B3 (353 x 500 mm) + B3 (353 x 500 mm) + + + + B4 (250 x 353 mm) + B4 (250 x 353 mm) + + + + B5 (176 x 250 mm, 6.93 x 9.84 inches) + B5 (176 x 250 mm, 6.93 x 9.84 英吋) + + + + B6 (125 x 176 mm) + B6 (125 x 176 mm) + + + + B7 (88 x 125 mm) + B7 (88 x 125 mm) + + + + B8 (62 x 88 mm) + B8 (62 x 88 mm) + + + + B9 (44 x 62 mm) + B9 (44 x 62 mm) + + + + B10 (31 x 44 mm) + B10 (31 x 44 mm) + + + + C5E (163 x 229 mm) + C5E (163 x 229 mm) + + + + DLE (110 x 220 mm) + DLE (110 x 220 mm) + + + + Executive (7.5 x 10 inches, 191 x 254 mm) + Executive (7.5 x 10 英吋, 191 x 254 mm) + + + + Folio (210 x 330 mm) + 對開 (210 x 330 mm) + + + + Ledger (432 x 279 mm) + Ledger (432 x 279 mm) + + + + Legal (8.5 x 14 inches, 216 x 356 mm) + Legal (8.5 x 14 英吋, 216 x 356 mm) + + + + Letter (8.5 x 11 inches, 216 x 279 mm) + Letter (8.5 x 11 英吋, 216 x 279 mm) + + + + Tabloid (279 x 432 mm) + Tabloid (279 x 432 mm) + + + + US Common #10 Envelope (105 x 241 mm) + US 常用 10 號信封 (105x241 mm) + + + + OK + 確定 + + + Cancel + 取消 + + + Page size: + 紙張大小: + + + Orientation: + 方向: + + + Paper source: + 紙張來源: + + + + + + Print + 列印 + + + File + 檔案 + + + Printer + 印表機 + + + + Print To File ... + 列印到檔案... + + + Print dialog + 列印對話框 + + + Paper format + 紙張格式 + + + Size: + 大小: + + + Properties + 內容 + + + Printer info: + 印表機資訊: + + + Browse + 瀏覽 + + + Print to file + 列印到檔案 + + + + Print range + 列印範圍 + + + + Print all + 全部列印 + + + Pages from + 指定頁面:從 + + + to + + + + Selection + 選擇區 + + + Copies + 份數 + + + Number of copies: + 列印份數: + + + Collate + 校對 + + + Print last page first + 從最後一頁印起 + + + Other + 其他 + + + Print in color if available + 可以的話用彩色列印 + + + Double side printing + 雙面列印 + + + + File %1 is not writable. +Please choose a different file name. + 檔案 %1 無法寫入。 +請選擇其它檔名。 + + + + %1 already exists. +Do you want to overwrite it? + %1 已存在。 +您要覆寫它嗎? + + + + File exists + 檔案已存在 + + + + <qt>Do you want to overwrite it?</qt> + <qt>您要覆寫它嗎?</qt> + + + + Print selection + 列印選擇區 + + + + %1 is a directory. +Please choose a different file name. + %1 是一個目錄。 +請選擇其他檔名。 + + + + A0 + A0 + + + + A1 + A1 + + + + A2 + A2 + + + + A3 + A3 + + + + A4 + A4 + + + + A5 + A5 + + + + A6 + A6 + + + + A7 + A7 + + + + A8 + A8 + + + + A9 + A9 + + + + B0 + B0 + + + + B1 + B1 + + + + B2 + B2 + + + + B3 + B3 + + + + B4 + B4 + + + + B5 + B5 + + + + B6 + B6 + + + + B7 + B7 + + + + B8 + B8 + + + + B9 + B9 + + + + B10 + B10 + + + + C5E + C5E + + + + DLE + DLE + + + + Executive + Executive + + + + Folio + Folio + + + + Ledger + Ledger + + + + Legal + Legal + + + + Letter + Letter + + + + Tabloid + Tabloid + + + + US Common #10 Envelope + US Common #10 Envelope + + + + Custom + 自訂 + + + + + &Options >> + 操作 (&O) >> + + + + &Print + 列印(&P) + + + + &Options << + 操作 (&O) << + + + + Print to File (PDF) + 列印到檔案(PDF) + + + + Print to File (Postscript) + 列印到檔案(Postscript) + + + + Local file + 本地端檔案 + + + + Write %1 file + 寫入 %1 檔案 + + + + The 'From' value cannot be greater than the 'To' value. + 起始數值不能大於結束數值 + + + + QPrintPreviewDialog + + + + Page Setup + 頁面設定 + + + + %1% + %1% + + + + Print Preview + 列印預覽 + + + + Next page + 下一頁 + + + + Previous page + 前一頁 + + + + First page + 第一頁 + + + + Last page + 最後一頁 + + + + Fit width + 符合寬度 + + + + Fit page + 符合頁面 + + + + Zoom in + 放大 + + + + Zoom out + 縮小 + + + + Portrait + 縱向 + + + + Landscape + 橫向 + + + + Show single page + 顯示單一頁面 + + + + Show facing pages + 顯示封面 + + + + Show overview of all pages + 顯示所有頁面預覽 + + + + Print + 列印 + + + + Page setup + 列印設定 + + + + Close + 關閉 + + + + Export to PDF + 匯出到 PDF 檔 + + + + Export to PostScript + 匯出到 PostScript 檔 + + + + QPrintPropertiesDialog + + PPD Properties + PPD 內容 + + + Save + 儲存 + + + OK + 確定 + + + + QPrintPropertiesWidget + + + Form + 表單 + + + + Page + 頁面 + + + + Advanced + 進階 + + + + QPrintSettingsOutput + + + Form + 表單 + + + + Copies + 份數 + + + + Print range + 列印範圍 + + + + Print all + 全部列印 + + + + Pages from + 指定頁面:從 + + + + to + + + + + Selection + 選擇區 + + + + Output Settings + 輸出設定 + + + + Copies: + 份數: + + + + Collate + 校對 + + + + Reverse + 反向 + + + + Options + 選項 + + + + Color Mode + 顏色模式 + + + + Color + 顏色 + + + + Grayscale + 灰階 + + + + Duplex Printing + 雙工列印 + + + + None + + + + + Long side + 長邊 + + + + Short side + 短邊 + + + + QPrintWidget + + + Form + 表單 + + + + Printer + 印表機 + + + + &Name: + 名稱(&N): + + + + P&roperties + 屬性(&R) + + + + Location: + 位置: + + + + Preview + 預覽 + + + + Type: + 型態: + + + + Output &file: + 輸出檔案(&F): + + + + ... + ... + + + + QProcess + + + + Could not open input redirection for reading + 無法開啟輸入導向以讀取 + + + + + Could not open output redirection for writing + 無法開啟輸出導向以寫入 + + + + Resource error (fork failure): %1 + 資源錯誤(fork 失敗):%1 + + + + + + + + + + + + Process operation timed out + 行程操作逾時 + + + + + + + Error reading from process + 從行程讀取時發生錯誤 + + + + + + Error writing to process + 寫入行程時發生錯誤 + + + + Process crashed + 行程已崩潰 + + + + No program defined + + + + + Process failed to start + 啟動行程失敗 + + + + QProgressDialog + + + Cancel + 取消 + + + + QPushButton + + + Open + 開啟 + + + + QRadioButton + + + Check + 勾選 + + + + QRegExp + + + no error occurred + 沒有發生錯誤 + + + + disabled feature used + 使用已關閉的功能 + + + + bad char class syntax + 錯誤的字元類別語法 + + + + bad lookahead syntax + 錯誤的 lookahead 語法 + + + + bad repetition syntax + 錯誤的重覆語法 + + + + invalid octal value + 不合法的八進位值 + + + + missing left delim + 少了左方的區隔符 + + + + unexpected end + 未預期遇到結尾 + + + + met internal limit + 遇到內部限制 + + + + QSQLite2Driver + + + Error to open database + 開啟資料庫時發生錯誤 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback Transaction + 無法反轉事務 + + + + QSQLite2Result + + + Unable to fetch results + 無法抓取結果 + + + + Unable to execute statement + 無法執行敘述 + + + + QSQLiteDriver + + + Error opening database + 開啟資料庫發生錯誤 + + + + Error closing database + 關閉資料庫發生錯誤 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + Unable to roll back transaction + 無法反轉事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QSQLiteResult + + + + + Unable to fetch row + 無法抓取列 + + + + Unable to execute statement + 無法執行敘述 + + + + Unable to reset statement + 無法重置敘述 + + + + Unable to bind parameters + 無法結合參數 + + + + Parameter count mismatch + 參數數量不符合 + + + + No query + 沒有查詢 + + + + QScrollBar + + + Scroll here + 在此捲軸 + + + + Left edge + 左邊緣 + + + + Top + 頂端 + + + + Right edge + 右邊緣 + + + + Bottom + 底端 + + + + Page left + 頁面左方 + + + + + Page up + 頁面上方 + + + + Page right + 頁面右方 + + + + + Page down + 頁面下方 + + + + Scroll left + 往左捲軸 + + + + Scroll up + 往上捲軸 + + + + Scroll right + 往右捲軸 + + + + Scroll down + 往下捲軸 + + + + Line up + 對上排列 + + + + Position + 位置 + + + + Line down + 對下排列 + + + + QSharedMemory + + + %1: unable to set key on lock + %1:無法設定鍵值 + + + + %1: create size is less then 0 + %1:建立大小小於 0 + + + + + %1: unable to lock + %1:無法鎖定 + + + + %1: unable to unlock + %1:無法解除鎖定 + + + + + %1: permission denied + %1:存取被拒 + + + + + %1: already exists + %1:已存在 + + + + + %1: doesn't exists + %1:不存在 + + + + + %1: out of resources + %1:資源不足 + + + + + %1: unknown error %2 + %1:未知的錯誤 %2 + + + + %1: key is empty + %1:鍵值是空的 + + + + %1: unix key file doesn't exists + %1:unix 鍵值檔不存在 + + + + %1: ftok failed + %1:ftok 失敗 + + + + + %1: unable to make key + %1:無法產生鍵值 + + + + %1: system-imposed size restrictions + %1:系統大小限制 + + + + %1: not attached + %1:未附加 + + + + %1: invalid size + %1:不合法的大小 + + + + %1: key error + %1:鍵值錯誤 + + + + %1: size query failed + %1:大小查詢失敗 + + + + QShortcut + + + Space + 空白鍵 + + + + Esc + Esc + + + + Tab + Tab + + + + Backtab + Backtab + + + + Backspace + Backspace + + + + Return + Return + + + + Enter + Enter + + + + Ins + Ins + + + + Del + Del + + + + Pause + Pause + + + + Print + Print + + + + SysReq + SysReq + + + + Home + Home + + + + End + End + + + + Left + 左鍵 + + + + Up + 上鍵 + + + + Right + 右鍵 + + + + Down + 下鍵 + + + + PgUp + PgUp + + + + PgDown + PgDown + + + + CapsLock + 大寫鎖定 + + + + NumLock + 數字鎖定 + + + + ScrollLock + 捲軸鎖定 + + + + Menu + 選單 + + + + Help + 說明 + + + + Back + 返回 + + + + Forward + 往前 + + + + Stop + 停止 + + + + Refresh + 刷新 + + + + Volume Down + 音量降低 + + + + Volume Mute + 靜音 + + + + Volume Up + 音量提高 + + + + Bass Boost + 重低音 + + + + Bass Up + Bass Up + + + + Bass Down + Bass Down + + + + Treble Up + Treble Up + + + + Treble Down + Treble Down + + + + Media Play + 媒體播放 + + + + Media Stop + 媒體停止 + + + + Media Previous + 媒體前一首 + + + + Media Next + 媒體下一首 + + + + Media Record + 媒體錄音 + + + + Favorites + 我的最愛 + + + + Search + 搜尋 + + + + Standby + 待命 + + + + Open URL + 開啟網址 + + + + Launch Mail + 啟動郵件程式 + + + + Launch Media + 啟動媒體程式 + + + + Launch (0) + 啟動(0) + + + + Launch (1) + 啟動(1) + + + + Launch (2) + 啟動(2) + + + + Launch (3) + 啟動(3) + + + + Launch (4) + 啟動(4) + + + + Launch (5) + 啟動(5) + + + + Launch (6) + 啟動(6) + + + + Launch (7) + 啟動(7) + + + + Launch (8) + 啟動(8) + + + + Launch (9) + 啟動(9) + + + + Launch (A) + 啟動(A) + + + + Launch (B) + 啟動(B) + + + + Launch (C) + 啟動(C) + + + + Launch (D) + 啟動(D) + + + + Launch (E) + 啟動(E) + + + + Launch (F) + 啟動(F) + + + + Print Screen + 列印螢幕 + + + + Page Up + 往上一頁 + + + + Page Down + 往下一頁 + + + + Caps Lock + 大寫鎖定 + + + + Num Lock + 數字鎖定 + + + + Number Lock + 數字鎖定 + + + + Scroll Lock + 捲軸鎖定 + + + + Insert + 插入 + + + + Delete + 刪除 + + + + Escape + Escape + + + + System Request + 系統要求 SysRq + + + + Select + 選擇 + + + + Yes + + + + + No + + + + + Context1 + 內文1 + + + + Context2 + 內文2 + + + + Context3 + 內文3 + + + + Context4 + 內文4 + + + + Call + 呼叫 + + + + Hangup + 掛斷 + + + + Flip + 反轉 + + + + + Ctrl + Ctrl + + + + + Shift + Shift + + + + + Alt + Alt + + + + + Meta + Meta + + + + + + + + + + + F%1 + F%1 + + + + Home Page + 首頁 + + + + QSlider + + + Page left + 頁面左方 + + + + Page up + 頁面上方 + + + + Position + 位置 + + + + Page right + 頁面右方 + + + + Page down + 頁面下方 + + + + QSocks5SocketEngine + + + Connection to proxy refused + 代理伺服器連線被拒 + + + + Connection to proxy closed prematurely + 代理伺服器連線已不正常關閉 + + + + Proxy host not found + 找不到代理伺服器 + + + + Connection to proxy timed out + 代理伺服器連線逾時 + + + + Proxy authentication failed + 代理伺服器認證失敗 + + + + Proxy authentication failed: %1 + 代理伺服器認證失敗:%1 + + + + SOCKS version 5 protocol error + SOCKS 5 的協定錯誤 + + + + General SOCKSv5 server failure + 一般的 SOCKSv5 伺服器錯誤 + + + + Connection not allowed by SOCKSv5 server + 連線未被 SOCKSv5 伺服器允許 + + + + TTL expired + TTL 逾時 + + + + SOCKSv5 command not supported + SOCKSv5 指令未被支援 + + + + Address type not supported + 位址型態未被支援 + + + + Unknown SOCKSv5 proxy error code 0x%1 + 未知的 SOCKSv5 代理伺服器錯誤代碼 0x%1 + + + Socks5 timeout error connecting to socks server + 連接到 socks 伺服器時發生 socks5 逾時錯誤 + + + + Network operation timed out + 網路操作逾時 + + + + QSpinBox + + + More + 更多 + + + + Less + 較少 + + + + QSql + + + Delete + 刪除 + + + + Delete this record? + 要刪除這筆紀錄嗎? + + + + + + Yes + + + + + + + No + + + + + Insert + 插入 + + + + Update + 更新 + + + + Save edits? + 要儲存編輯過的內容嗎? + + + + Cancel + 取消 + + + + Confirm + 確認 + + + + Cancel your edits? + 要取消編輯嗎? + + + + QSslSocket + + + Unable to write data: %1 + 無法寫入資料:%1 + + + + Error while reading: %1 + 讀取時發生錯誤:%1 + + + + Error during SSL handshake: %1 + SSL 同步時發生錯誤:%1 + + + + Error creating SSL context (%1) + 建立 SSL 內文時發生錯誤(%1) + + + + Invalid or empty cipher list (%1) + 不合法或空白的加密清單(%1) + + + + Error creating SSL session, %1 + 建立 SSL 工作階段時發生錯誤:%1 + + + + Error creating SSL session: %1 + 建立 SSL 工作階段時發生錯誤:%1 + + + + Cannot provide a certificate with no key, %1 + 沒有金鑰無法提供憑證:%1 + + + + Error loading local certificate, %1 + 載入本地憑證時發生錯誤:%1 + + + + Error loading private key, %1 + 載入私鑰時發生錯誤:%1 + + + Private key do not certificate public key, %1 + 私鑰與公鑰不符:%1 + + + + Private key does not certificate public key, %1 + 私密金鑰無法認證公開金鑰,%1 + + + + QSystemSemaphore + + + + %1: out of resources + %1:資源不足 + + + + + %1: permission denied + %1:存取被拒 + + + + %1: already exists + %1:已存在 + + + + %1: does not exist + %1:不存在 + + + + + %1: unknown error %2 + %1:未知的錯誤 %2 + + + + QTDSDriver + + + Unable to open connection + 無法開啟連線 + + + + Unable to use database + 無法使用資料庫 + + + + QTabBar + + + Scroll Left + 往左捲軸 + + + + Scroll Right + 往右捲軸 + + + + QTcpServer + + Socket operation unsupported + 未支援的 socket 操作 + + + + Operation on socket is not supported + Socket 的操作未被支援 + + + + QTextControl + + + &Undo + 復原(&U) + + + + &Redo + 重做(&R) + + + + Cu&t + 剪下(&T) + + + + &Copy + 複製(&C) + + + + Copy &Link Location + 複製連結位址(&L) + + + + &Paste + 貼上(&P) + + + + Delete + 刪除 + + + + Select All + 全部選擇 + + + + QToolButton + + + + Press + 按下 + + + + + Open + 開啟 + + + + QUdpSocket + + + This platform does not support IPv6 + 此平台不支援 IPv6 + + + + QUndoGroup + + + Undo + 復原 + + + + Redo + 重做 + + + + QUndoModel + + + <empty> + <空白> + + + + QUndoStack + + + Undo + 復原 + + + + Redo + 重做 + + + + QUnicodeControlCharacterMenu + + + LRM Left-to-right mark + LRM 左到右標記 + + + + RLM Right-to-left mark + RLM 右到左標記 + + + + ZWJ Zero width joiner + ZWJ 零寬度連接器 + + + + ZWNJ Zero width non-joiner + ZWNJ 零寬度非連接器 + + + + ZWSP Zero width space + ZWSP 零寬度空白 + + + + LRE Start of left-to-right embedding + LRE 左到右嵌入起點 + + + + RLE Start of right-to-left embedding + RLE 右到左嵌入起點 + + + + LRO Start of left-to-right override + LRO 左到右覆寫起點 + + + + RLO Start of right-to-left override + RLO 右到左覆寫起點 + + + + PDF Pop directional formatting + PDF 彈出方向格式 + + + + Insert Unicode control character + 插入萬國碼控制字元 + + + + QWebFrame + + + Request cancelled + 請求已取消 + + + + Request blocked + 請求已被阻擋 + + + + Cannot show URL + 無法顯示網址 + + + + Frame load interruped by policy change + 影像載入因政策變更而中斷 + + + + Cannot show mimetype + 無法顯示 MIME 型態 + + + + File does not exist + 檔案不存在 + + + + QWebPage + + + Bad HTTP request + 不良的 HTTP 請求 + + + + Submit + default label for Submit buttons in forms on web pages + 提交 + + + + Submit + Submit (input element) alt text for <input> elements with no alt, title, or value + 提交 + + + + Reset + default label for Reset buttons in forms on web pages + 重置 + + + + This is a searchable index. Enter search keywords: + text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index' + 這是可搜尋的索引。請輸入關鍵字:  + + + + Choose File + title for file button used in HTML forms + 選擇檔案 + + + + No file selected + text to display in file button used in HTML forms when no file is selected + 未選取任何檔案 + + + + Open in New Window + Open in New Window context menu item + 在新視窗開啟 + + + + Save Link... + Download Linked File context menu item + 儲存連結... + + + + Copy Link + Copy Link context menu item + 複製連結 + + + + Open Image + Open Image in New Window context menu item + 開啟影像 + + + + Save Image + Download Image context menu item + 儲存影像 + + + + Copy Image + Copy Link context menu item + 複製影像 + + + + Open Frame + Open Frame in New Window context menu item + 開啟框架 + + + + Copy + Copy context menu item + 複製 + + + + Go Back + Back context menu item + 往回 + + + + Go Forward + Forward context menu item + 往前 + + + + Stop + Stop context menu item + 停止 + + + + Reload + Reload context menu item + 重新載入 + + + + Cut + Cut context menu item + 剪下 + + + + Paste + Paste context menu item + 貼上 + + + + No Guesses Found + No Guesses Found context menu item + 找不到可能的內容 + + + + Ignore + Ignore Spelling context menu item + 忽略 + + + + Add To Dictionary + Learn Spelling context menu item + 新增到字典 + + + + Search The Web + Search The Web context menu item + 搜尋站台 + + + + Look Up In Dictionary + Look Up in Dictionary context menu item + 在字典裡搜尋 + + + + Open Link + Open Link context menu item + 開啟連結 + + + + Ignore + Ignore Grammar context menu item + 忽略 + + + + Spelling + Spelling and Grammar context sub-menu item + 拼字 + + + + Show Spelling and Grammar + menu item title + 顯示拼字與文法 + + + + Hide Spelling and Grammar + menu item title + 隱藏拼字與文法 + + + + Check Spelling + Check spelling context menu item + 檢查拼字 + + + + Check Spelling While Typing + Check spelling while typing context menu item + 打字時立即檢查拼字 + + + + Check Grammar With Spelling + Check grammar with spelling context menu item + 檢查拼字與文法 + + + + Fonts + Font context sub-menu item + 字型 + + + + Bold + Bold context menu item + 粗體 + + + + Italic + Italic context menu item + 斜體 + + + + Underline + Underline context menu item + 底線 + + + + Outline + Outline context menu item + 外框線 + + + + Direction + Writing direction context sub-menu item + 方向 + + + + Text Direction + Text direction context sub-menu item + 文字方向 + + + + Default + Default writing direction context menu item + 預設 + + + + LTR + Left to Right context menu item + 左到右 + + + + RTL + Right to Left context menu item + 右到左 + + + + Inspect + Inspect Element context menu item + 查驗 + + + + No recent searches + Label for only item in menu that appears when clicking on the search field image, when no searches have been performed + 沒有最近的搜尋 + + + + Recent searches + label for first item in the menu that appears when clicking on the search field image, used as embedded menu title + 最近的搜尋 + + + + Clear recent searches + menu item in Recent Searches menu that empties menu's contents + 清除最近的搜尋 + + + + Unknown + Unknown filesize FTP directory listing item + 未知 + + + + %1 (%2x%3 pixels) + Title string for images + %1(%2x%3 像素) + + + + Web Inspector - %2 + 網站查驗器─%2 + + + + Scroll here + 在此捲軸 + + + + Left edge + 左邊緣 + + + + Top + 頂端 + + + + Right edge + 右邊緣 + + + + Bottom + 底端 + + + + Page left + 頁面左方 + + + + Page up + 頁面上方 + + + + Page right + 頁面右方 + + + + Page down + 頁面下方 + + + + Scroll left + 往左捲軸 + + + + Scroll up + 往上捲軸 + + + + Scroll right + 往右捲軸 + + + + Scroll down + 往下捲軸 + + + + %n file(s) + number of chosen file + + %n 個檔案 + + + + + JavaScript Alert - %1 + JavaScript 警告 ─ %1 + + + + JavaScript Confirm - %1 + JavaScript 確認 ─ %1 + + + + JavaScript Prompt - %1 + JavaScript 提示 ─ %1 + + + + Move the cursor to the next character + 移動游標到下一個字元 + + + + Move the cursor to the previous character + 移動游標到前一個字元 + + + + Move the cursor to the next word + 移動游標到下一個單字 + + + + Move the cursor to the previous word + 移動游標到前一個單字 + + + + Move the cursor to the next line + 移動游標到下一行 + + + + Move the cursor to the previous line + 移動游標到前一行 + + + + Move the cursor to the start of the line + 移動游標到這一行的起頭 + + + + Move the cursor to the end of the line + 移動游標到這一行的結尾 + + + + Move the cursor to the start of the block + 移動游標到這一個區塊的起頭 + + + + Move the cursor to the end of the block + 移動游標到這一個區塊的結尾 + + + + Move the cursor to the start of the document + 移動游標到這一個文件的起頭 + + + + Move the cursor to the end of the document + 移動游標到這一個文件的結尾 + + + + Select all + + + + + Select to the next character + 選擇到下一個字元 + + + + Select to the previous character + 選擇到前一個字元 + + + + Select to the next word + 選擇到下一個單字 + + + + Select to the previous word + 選擇到前一個單字 + + + + Select to the next line + 選擇到下一行 + + + + Select to the previous line + 選擇到前一行 + + + + Select to the start of the line + 選擇到這一行的起頭 + + + + Select to the end of the line + 選擇到這一行的結尾 + + + + Select to the start of the block + 選擇到這一個區塊的起頭 + + + + Select to the end of the block + 選擇到這一個區塊的結尾 + + + + Select to the start of the document + 選擇到這一個文件的起頭 + + + + Select to the end of the document + 選擇到這一個文件的結尾 + + + + Delete to the start of the word + 刪除到此單字的起頭 + + + + Delete to the end of the word + 刪除到此單字的結尾 + + + + Insert a new paragraph + + + + + Insert a new line + + + + + QWhatsThisAction + + + What's This? + 這是什麼? + + + + QWidget + + + * + + + + + + QWizard + + + Go Back + 往回 + + + + Continue + 繼續 + + + + Commit + 提交 + + + + Done + 完成 + + + Quit + 離開 + + + + Help + 說明 + + + + < &Back + <返回(&B) + + + + &Finish + 完成(&F) + + + + Cancel + 取消 + + + + &Help + 說明(&H) + + + + &Next + 下一個(&N) + + + + &Next > + 下一個(&N)> + + + + QWorkspace + + + &Restore + 回復(&R) + + + + &Move + 移動(&M) + + + + &Size + 大小(&S) + + + + Mi&nimize + 最小化(&N) + + + + Ma&ximize + 最大化(&X) + + + + &Close + 關閉(&C) + + + + Stay on &Top + 留在頂端(&T) + + + + + Sh&ade + 遮蔽(&A) + + + + + %1 - [%2] + %1 - [%2] + + + + Minimize + 最小化 + + + + Restore Down + 向下恢復 + + + + Close + 關閉 + + + + &Unshade + 取消遮蔽(&U) + + + + QXml + + + no error occurred + 沒有發生錯誤 + + + + error triggered by consumer + 用戶觸發的錯誤 + + + + unexpected end of file + 未預期遇到檔案結尾 + + + + more than one document type definition + 定義了一個以上的文件型態 + + + + error occurred while parsing element + 剖析元素時發生錯誤 + + + + tag mismatch + 標籤不對稱 + + + + error occurred while parsing content + 剖析內容時發生錯誤 + + + + unexpected character + 非預期的字元 + + + + invalid name for processing instruction + 處理指令時的不合法名稱 + + + + version expected while reading the XML declaration + 讀取 XML 宣告時應有版本號 + + + + wrong value for standalone declaration + 獨立宣告時的值錯誤 + + + + encoding declaration or standalone declaration expected while reading the XML declaration + 讀取 XML 宣告時應有編碼宣告或獨立宣告 + + + + standalone declaration expected while reading the XML declaration + 讀取 XML 宣告時應有讀立宣告 + + + + error occurred while parsing document type definition + 剖析文件型態定義時發生錯誤 + + + + letter is expected + 預期應為字母 + + + + error occurred while parsing comment + 剖析註解時發生錯誤 + + + + error occurred while parsing reference + 剖析參考時發生錯誤 + + + + internal general entity reference not allowed in DTD + 在 DTD 中不允許內部產生的實體參考 + + + + external parsed general entity reference not allowed in attribute value + 在屬性值中不允許使用外部剖析的實體參考 + + + + external parsed general entity reference not allowed in DTD + 在 DTD 中不允許使用外部剖析的實體參考 + + + + unparsed entity reference in wrong context + 在錯誤的內文中有未剖析的實體參考 + + + + recursive entities + 遞迴的實體 + + + + error in the text declaration of an external entity + 在外部實體中的文字宣告有錯誤 + + + + QXmlStream + + + + Extra content at end of document. + 文件尾端有多餘的內容。 + + + + Invalid entity value. + 不合法的實體值 + + + + Invalid XML character. + 不合法的 XML 字元。 + + + + Sequence ']]>' not allowed in content. + 在內文中不允許有序列 "]]>"。 + + + + Namespace prefix '%1' not declared + 命名空間的前置字串 %1 未宣告 + + + + Attribute redefined. + 屬性重定義。 + + + + Unexpected character '%1' in public id literal. + 在公開代碼字元中遇到非預期的字元 %1。 + + + + Invalid XML version string. + 不合法的 XML 版本字串。 + + + + Unsupported XML version. + 未支援的 XML 版本。 + + + + %1 is an invalid encoding name. + %1 為不合法的編碼名稱。 + + + + Encoding %1 is unsupported + 編碼 %1 不支援。 + + + Invalid XML encoding name. + 不合法的 XML 編碼名稱。 + + + + Standalone accepts only yes or no. + 獨立實體只接受 yes 或 no。 + + + + Invalid attribute in XML declaration. + XML 宣告中有不合法的屬性。 + + + + Premature end of document. + 文件結尾不正確。 + + + + Invalid document. + 不合法的文件。 + + + + Expected + 預期應為 + + + + , but got ' + ,但是看到的是 + + + + Unexpected ' + 非預期 + + + + Expected character data. + 預期的字元資料。 + + + + Recursive entity detected. + 偵測到遞迴實體。 + + + + Start tag expected. + 預期應有開始標籤。 + + + + XML declaration not at start of document. + XML 宣告沒有在文件開始處。 + + + + NDATA in parameter entity declaration. + 在參數實體宣告有 NDATA。 + + + + %1 is an invalid processing instruction name. + %1 是不合法的處理指令名稱。 + + + + Invalid processing instruction name. + 不合法的處理指令名稱。 + + + + + + + Illegal namespace declaration. + 不合法的命名空間宣告。 + + + + Invalid XML name. + 不合法的 XML 名稱。 + + + + Opening and ending tag mismatch. + 開啟與結束的標籤不對稱。 + + + + Reference to unparsed entity '%1'. + 參考到未剖析的實體 %1。 + + + + + + Entity '%1' not declared. + 實體 %1 未宣告。 + + + + Reference to external entity '%1' in attribute value. + 在屬性值中參考到外部實體 %1。 + + + + Invalid character reference. + 不合法的字元參考。 + + + + + Encountered incorrectly encoded content. + 遇到不正確的編碼內容。 + + + + The standalone pseudo attribute must appear after the encoding. + 獨立的虛擬屬性必須在編碼之後出現。 + + + + %1 is an invalid PUBLIC identifier. + %1 為不合法的 PUBLIC 識別子。 + + + + QtXmlPatterns + + + An %1-attribute with value %2 has already been declared. + 已宣告屬性 %1 的值為 %2。 + + + + An %1-attribute must have a valid %2 as value, which %3 isn't. + 屬性 %1 必須以合法的 %2 為值,而 %3 是不合法的。 + + + + Network timeout. + 網路逾時。 + + + + Element %1 can't be serialized because it appears outside the document element. + 元素 %1 無法序列化,因為似乎是在文件元素之外。 + + + Attribute element %1 can't be serialized because it appears at the top level. + 屬性元素 %1 無法序列化,因為似乎是在頂層。 + + + + Year %1 is invalid because it begins with %2. + 年份 %1 不合法,因為是從 %2 開始的。 + + + + Day %1 is outside the range %2..%3. + 日期 %1 已超出 %2 到 %3 的範圍。 + + + + Month %1 is outside the range %2..%3. + 月份 %1 已超出 %2 到 %3 的範圍。 + + + + Overflow: Can't represent date %1. + 溢位:無法表示日期 %1。 + + + + Day %1 is invalid for month %2. + 月份 %2 中沒有日期 %1。 + + + + Time 24:%1:%2.%3 is invalid. Hour is 24, but minutes, seconds, and milliseconds are not all 0; + 時間 24:%1:%2.%3 不合法。小時為 24 則分、秒與毫秒都必須是 0。 + + + + + Time %1:%2:%3.%4 is invalid. + 時間 %1:%2:%3.%4 不合法。 + + + + Overflow: Date can't be represented. + 溢位:無法表示日期。 + + + + + At least one component must be present. + 必須表達至少一個組件。 + + + + At least one time component must appear after the %1-delimiter. + 在分隔符 %1 後必須至少有一個時間組件。 + + + + No operand in an integer division, %1, can be %2. + 整數除法沒有運作對象,%1,可以是 %2 + + + + The first operand in an integer division, %1, cannot be infinity (%2). + 整數除法的第一個運算對象 %1 不能是無限大(%2)。 + + + + The second operand in a division, %1, cannot be zero (%2). + 整數除法的第二個運算對象 %1 不能是零(%2)。 + + + + %1 is not a valid value of type %2. + %1 不是合法的 %2 型態的值。 + + + + When casting to %1 from %2, the source value cannot be %3. + 從 %2 轉換型態為 %1 的時候,來源數值不能是 %3。 + + + + Integer division (%1) by zero (%2) is undefined. + 整數除法 %1 除以零(%2)的行為未定義。 + + + + Division (%1) by zero (%2) is undefined. + 除法 %1 除以零(%2)的行為未定義。 + + + + Modulus division (%1) by zero (%2) is undefined. + 餘數除法 %1 除以零(%2)的行為未定義。 + + + + + Dividing a value of type %1 by %2 (not-a-number) is not allowed. + 將型態 %1 除以 %2(非數值)是不允許的。 + + + + Dividing a value of type %1 by %2 or %3 (plus or minus zero) is not allowed. + 將型態 %1 除以 %2 或 %3(正或負零)是不允許的。 + + + + Multiplication of a value of type %1 by %2 or %3 (plus or minus infinity) is not allowed. + 將型態 %1 乘以 %2 或 %3(正或負無限大)是不允許的。 + + + + A value of type %1 cannot have an Effective Boolean Value. + 型態 %1 不能有實際布林值。 + + + + Effective Boolean Value cannot be calculated for a sequence containing two or more atomic values. + 實際布林值(Effective Boolean)無法用在兩個或兩個以上的原數值(atomic value)的計算。 + + + + Value %1 of type %2 exceeds maximum (%3). + 型態 %2 的數值 %1 已超過最大值(%3)。 + + + + Value %1 of type %2 is below minimum (%3). + 型態 %2 的數值 %1 已低過最小值(%3)。 + + + + A value of type %1 must contain an even number of digits. The value %2 does not. + 型態 %1 的值必須包含偶數個數字。數值 %2 未符合此條件。 + + + + %1 is not valid as a value of type %2. + %1 不是合法的 %2 型態的值。 + + + + Operator %1 cannot be used on type %2. + 操作元 %1 不能用於型態 %2。 + + + + Operator %1 cannot be used on atomic values of type %2 and %3. + 操作元 %1 不能用於型態 %2 與 %3 的原數值。 + + + + The namespace URI in the name for a computed attribute cannot be %1. + 在已計算屬性的名稱的命名空間網址不能是 %1。 + + + + The name for a computed attribute cannot have the namespace URI %1 with the local name %2. + 在已計算屬性的名稱不能同時有命名空間網址 %1 與本地端名稱 %2。 + + + + Type error in cast, expected %1, received %2. + 轉換型態錯誤,應為 %1 但接收到 %2。 + + + + When casting to %1 or types derived from it, the source value must be of the same type, or it must be a string literal. Type %2 is not allowed. + 轉換為型態 %1 或其衍生型態時,來源數值必須是相同型態,或者是字串。型態 %2 是不被允許的。 + + + + No casting is possible with %1 as the target type. + 不能轉換到 %1 型態。 + + + + It is not possible to cast from %1 to %2. + 不能從 %1 轉換到 %2。 + + + + Casting to %1 is not possible because it is an abstract type, and can therefore never be instantiated. + 無法轉換到 %1 因為它是一個抽象型態,不能被實體化。 + + + + It's not possible to cast the value %1 of type %2 to %3 + 無法轉換型態 %2 的數值 %1 到 %3 + + + + Failure when casting from %1 to %2: %3 + 從 %1 轉換到 %2 時失敗:%3 + + + + A comment cannot contain %1 + 註解不能包含 %1 + + + + A comment cannot end with a %1. + 註解不能以 %1 做結尾 + + + + No comparisons can be done involving the type %1. + 包含型態 %1 時不能做比較。 + + + + Operator %1 is not available between atomic values of type %2 and %3. + 操作元 %1 不能用於型態 %2 與 %3 的原數值。 + + + + An attribute node cannot be a child of a document node. Therefore, the attribute %1 is out of place. + 屬性點不能做為文件點的子節點。因此,屬性 %1 的位置不合適。 + + + + A library module cannot be evaluated directly. It must be imported from a main module. + 不能直接計算函式模組。必須要從主模組匯入。 + + + + No template by name %1 exists. + 沒有名為 %1 的樣本存在。 + + + + A value of type %1 cannot be a predicate. A predicate must have either a numeric type or an Effective Boolean Value type. + 型態 %1 的值不能是謂詞(predicate)。謂詞必須是數值型態,或是實際布林值。 + + + + A positional predicate must evaluate to a single numeric value. + 位置謂詞必須能計算出單一的數值。 + + + + The target name in a processing instruction cannot be %1 in any combination of upper and lower case. Therefore, is %2 invalid. + 處理指令的目標名稱不能是任何大小寫組合的 %1。因此,%2 是不合法的值。 + + + + %1 is not a valid target name in a processing instruction. It must be a %2 value, e.g. %3. + %1 不是一個合法的處理指令的目標名稱。必須是 %2 的值,例如 %3。 + + + + The last step in a path must contain either nodes or atomic values. It cannot be a mixture between the two. + 路徑的最後一步必須是節點或原值,而不能在兩者之間。 + + + + The data of a processing instruction cannot contain the string %1 + 處理指令的資料不能包含字串 %1 + + + + No namespace binding exists for the prefix %1 + 前置字串 %1 沒有結合命名空間 + + + + No namespace binding exists for the prefix %1 in %2 + 在 %2 的前置字串 %1 沒有結合命名空間 + + + + + %1 is an invalid %2 + %1 是不合法的 %2 + + + + %1 takes at most %n argument(s). %2 is therefore invalid. + + %1 最多只能有 %n 個參數,因此 %2 是不合法的。 + + + + + %1 requires at least %n argument(s). %2 is therefore invalid. + + %1 至少需要 %n 個參數,因此 %2 是不合法的。 + + + + + The first argument to %1 cannot be of type %2. It must be a numeric type, xs:yearMonthDuration or xs:dayTimeDuration. + 呼叫 %1 的第一個參數不能是 %2 型態。必須是數值型態,xs.yearMonthDuration 或 xs.dayTimeDuration。 + + + + The first argument to %1 cannot be of type %2. It must be of type %3, %4, or %5. + 呼叫 %1 的第一個參數不能是 %2 型態。必須是 %3、%4 或 %5 型態。 + + + + The second argument to %1 cannot be of type %2. It must be of type %3, %4, or %5. + 呼叫 %1 的第二個參數不能是 %2 型態。必須是 %3、%4 或 %5 型態。 + + + + %1 is not a valid XML 1.0 character. + %1 不是合法的 XML 1.0 字元。 + + + + The first argument to %1 cannot be of type %2. + 呼叫 %1 的第一個參數不能是 %2 型態。 + + + + If both values have zone offsets, they must have the same zone offset. %1 and %2 are not the same. + 如果兩個值都有區域位移,則必須是相同的區域位移。%1 與 %2 並不相同。 + + + + %1 was called. + %1 已被呼叫。 + + + + %1 must be followed by %2 or %3, not at the end of the replacement string. + %1 後面必須跟著 %2 或 %3,而非取代字串的結尾。 + + + + In the replacement string, %1 must be followed by at least one digit when not escaped. + 在取代字串中,在未脫逸的情形下 %1 必須至少跟著一位數字。 + + + + In the replacement string, %1 can only be used to escape itself or %2, not %3 + 在取代字串中,%1 只能用於自身或 %2 的脫逸,而非 %3。 + + + + %1 matches newline characters + %1 符合了換行字元 + + + + %1 and %2 match the start and end of a line. + %1 與 %2 符合了一行的開始與結尾。 + + + + Matches are case insensitive + 比對為區分大小寫 + + + + Whitespace characters are removed, except when they appear in character classes + 空白字元已移除,除非它們出現在字元類別 + + + + %1 is an invalid regular expression pattern: %2 + %1 是不合法的正規表示式樣式:%2 + + + + %1 is an invalid flag for regular expressions. Valid flags are: + %1 是正規表示式中不合法的旗標。合法的旗標有: + + + + If the first argument is the empty sequence or a zero-length string (no namespace), a prefix cannot be specified. Prefix %1 was specified. + 如果第一個參數是空序列,或是長度為 0 的字串(沒有命名空間),則無法指定前置字串。但是您指定了 %1。 + + + + It will not be possible to retrieve %1. + 無法取得 %1。 + + + + The root node of the second argument to function %1 must be a document node. %2 is not a document node. + 函式 %1 的第二個參數的根節點必須是文件節點。%2 不是文件節點。 + + + + The default collection is undefined + 預設的收藏未定義 + + + + %1 cannot be retrieved + %1 無法取得 + + + + The normalization form %1 is unsupported. The supported forms are %2, %3, %4, and %5, and none, i.e. the empty string (no normalization). + 未支援常態化表單 %1。支援的表單有 %2、%3、%4、%5,以及無(也就是空字串,未常態化)。 + + + + A zone offset must be in the range %1..%2 inclusive. %3 is out of range. + 區域位移必須是在 %1 到 %2 範圍之內。%3 已超出範圍。 + + + + %1 is not a whole number of minutes. + %1 不是分鐘的數值。 + + + + Required cardinality is %1; got cardinality %2. + 需要的基數為 %1;得到的是 %2。 + + + + The item %1 did not match the required type %2. + 項目 %1 未符合需要的型態 %2。 + + + + + %1 is an unknown schema type. + %1 是未知的機制型態。 + + + + Only one %1 declaration can occur in the query prolog. + 只有一個 %1 宣告可以在查詢中。 + + + + The initialization of variable %1 depends on itself + 變數 %1 的初始化與自身相依。 + + + + No variable by name %1 exists + 沒有名為 %1 的變數存在 + + + + The variable %1 is unused + 變數 %1 未使用 + + + + Version %1 is not supported. The supported XQuery version is 1.0. + 版本 %1 未支援。支援的 XQuery 版本為 1.0。 + + + + The encoding %1 is invalid. It must contain Latin characters only, must not contain whitespace, and must match the regular expression %2. + 編碼 %1 不合法。必須只能包含拉丁字元,不含空白,並且要符合正規表示式 %2。 + + + + No function with signature %1 is available + 沒有簽章為 %1 的函式可使用 + + + + + A default namespace declaration must occur before function, variable, and option declarations. + 預設的命名空間宣告必須在函式、變數與選項宣告之前。 + + + + Namespace declarations must occur before function, variable, and option declarations. + 命名空間宣告必須在函式、變數與選項宣告之前。 + + + + Module imports must occur before function, variable, and option declarations. + 模組匯入必須在函式、變數與選項宣告之前。 + + + + It is not possible to redeclare prefix %1. + 無法重宣告前置字串 %1。 + + + Only the prefix %1 can be declared to bind the namespace %2. By default, it is already bound to the prefix %1. + 只有前置字串 %1 可以被宣告與命名空間 %2 結合。它預設已經與前置字串 %1 結合。 + + + + Prefix %1 is already declared in the prolog. + 前置字串 %1 已在 prolog 中宣告。 + + + + The name of an option must have a prefix. There is no default namespace for options. + 選項名稱必須有前置字串。沒有選項的預設命名空間。 + + + + The Schema Import feature is not supported, and therefore %1 declarations cannot occur. + 機制匯入功能未支援,因此有 %1 個宣告無法達成。 + + + + The target namespace of a %1 cannot be empty. + %1 的目標命名空間不能是空的。 + + + + The module import feature is not supported + 模組匯入功能未支援。 + + + A variable by name %1 has already been declared in the prolog. + 名稱為 %1 的變數已經在 prolog 中宣告。 + + + + No value is available for the external variable by name %1. + 名為 %1 的外部變數沒有可用的值。 + + + The namespace for a user defined function cannot be empty(try the predefined prefix %1 which exists for cases like this) + 使用者定義的函式的命名空間不能是空的(請試試使用預定義前置字串 %1) + + + + A construct was encountered which only is allowed in XQuery. + 遇到了建構,實際上只能允許在 XQuery 內。 + + + + A template by name %1 has already been declared. + 名為 %1 的屬性已被宣告。 + + + + The keyword %1 cannot occur with any other mode name. + 關鍵字 %1 不能與任何其它模式名稱一起存在。 + + + + The value of attribute %1 must of type %2, which %3 isn't. + 屬性 %1 的值必須為型態 %2,但 %3 不是。 + + + + The prefix %1 can not be bound. By default, it is already bound to the namespace %2. + 前置字串 %1 不能被結合。預設它已與命名空間 %2 結合。 + + + + A variable by name %1 has already been declared. + 名為 %1 的變數已被宣告。 + + + + A stylesheet function must have a prefixed name. + 樣式表函式必須有前置名稱。 + + + + The namespace for a user defined function cannot be empty (try the predefined prefix %1 which exists for cases like this) + 使用者定義函式的命名空間不能為空白(請試著用預先定義的前置字串 %1) + + + + The namespace %1 is reserved; therefore user defined functions may not use it. Try the predefined prefix %2, which exists for these cases. + 命名空間 %1 已被保留,因此使用者定義函式不能使用它。請試試預定義前置字串 %2。 + + + + The namespace of a user defined function in a library module must be equivalent to the module namespace. In other words, it should be %1 instead of %2 + 在函式模組中的使用者定義函式的命名空間必須與模組的命名空間相同。也就是,應該為 %1 而不是 %2。 + + + + A function already exists with the signature %1. + 已經有簽章為 %1 的函式存在。 + + + + No external functions are supported. All supported functions can be used directly, without first declaring them as external + 未支援外部函式。所有支援的含式可以直接使用而不需要先宣告為外部函式。 + + + + An argument by name %1 has already been declared. Every argument name must be unique. + 名稱為 %1 的參數已被宣告。每個參數名稱必須唯一。 + + + + When function %1 is used for matching inside a pattern, the argument must be a variable reference or a string literal. + 當函式 %1 用於樣式比對時,參數必須是變數參考或字串。 + + + + In an XSL-T pattern, the first argument to function %1 must be a string literal, when used for matching. + 在 XSL-T 樣式內,函式 %1 的第一個參數必須是字串,以便用於比對。 + + + + In an XSL-T pattern, the first argument to function %1 must be a literal or a variable reference, when used for matching. + 在 XSL-T 樣式內,函式 %1 的第一個參數必須是文字或變數參考,以便用於比對。 + + + + In an XSL-T pattern, function %1 cannot have a third argument. + 在 XSL-T 樣式內,函式 %1 的不能有第三個參數。 + + + + In an XSL-T pattern, only function %1 and %2, not %3, can be used for matching. + 在 XSL-T 樣式內,只有函式 %1,%2 可以用於比對。%3 不行。 + + + + In an XSL-T pattern, axis %1 cannot be used, only axis %2 or %3 can. + 在 XSL-T 樣式內,不能用 %1 軸,只能用 %2 或 %3。 + + + + %1 is an invalid template mode name. + %1 不是合法的樣本模式名稱。 + + + + The name of a variable bound in a for-expression must be different from the positional variable. Hence, the two variables named %1 collide. + 與 for 敘述結合的變數名稱必須與位置變數不同。因此,有兩個名為 %1 的變數衝突了。 + + + + The Schema Validation Feature is not supported. Hence, %1-expressions may not be used. + 未支援機制確認功能。%1 敘述無法使用。 + + + + None of the pragma expressions are supported. Therefore, a fallback expression must be present + 未支援 pragma 敘述。因次,必須有預設的敘述。 + + + + Each name of a template parameter must be unique; %1 is duplicated. + 每個樣本參數的名稱必須唯一;%1 已經被使用。 + + + + The %1-axis is unsupported in XQuery + XQuery 中未支援 %1 軸 + + + + %1 is not a valid name for a processing-instruction. + %1 不是處理指令的合法名稱。 + + + + %1 is not a valid numeric literal. + %1 不是合法的數值。 + + + + No function by name %1 is available. + 沒有名為 %1 的函式。 + + + + The namespace URI cannot be the empty string when binding to a prefix, %1. + 要與前置字串 %1 結合的命名空間網址不能是空字串。 + + + + %1 is an invalid namespace URI. + %1 是不合法的命名空間網址。 + + + + It is not possible to bind to the prefix %1 + 無法與前置字串 %1 結合。 + + + + Namespace %1 can only be bound to %2 (and it is, in either case, pre-declared). + 命名空間 %1 只能與 %2 結合(也就是說,要預先定義)。 + + + + Prefix %1 can only be bound to %2 (and it is, in either case, pre-declared). + 前置字串 %1 只能與 %2 結合(也就是說,要預先定義)。 + + + + Two namespace declaration attributes have the same name: %1. + 有兩個命名空間宣告的屬性有相同的名稱:%1 + + + + The namespace URI must be a constant and cannot use enclosed expressions. + 命名空間網址必須是常數,並且不能使用封閉敘述。 + + + + An attribute by name %1 has already appeared on this element. + 名為 %1 的屬性已出現在此元素。 + + + + A direct element constructor is not well-formed. %1 is ended with %2. + 直接元素建構器沒有完整產生。%1 以 %2 結束。 + + + + The name %1 does not refer to any schema type. + 名稱 %1 未指向任何機制型態。 + + + + %1 is an complex type. Casting to complex types is not possible. However, casting to atomic types such as %2 works. + %1 是複數型態,無法轉換成複數型態。然而,轉換為原型態,如 %2 是可行的。 + + + + %1 is not an atomic type. Casting is only possible to atomic types. + %1 不是一個原型態。只能轉換為原型態。 + + + %1 is not a valid name for a processing-instruction. Therefore this name test will never match. + %1 不是一個合法的處理指令的名稱。因此名稱測試永遠不會成功。 + + + + + %1 is not in the in-scope attribute declarations. Note that the schema import feature is not supported. + %1 不是範圍內屬性宣告。注意機制匯入功能未支援。 + + + + The name of an extension expression must be in a namespace. + 延伸敘述的名稱必須在命名空間內。 + + + + empty + 空白 + + + + zero or one + 0 或 1 個 + + + + exactly one + 剛好一個 + + + + one or more + 一個以上 + + + + zero or more + 0 個以上 + + + + Required type is %1, but %2 was found. + 需要的型態為 %1,但找到 %2。 + + + + Promoting %1 to %2 may cause loss of precision. + 將 %1 抬升為 %2 可能會失去精確度。 + + + + The focus is undefined. + 焦點未定義。 + + + + It's not possible to add attributes after any other kind of node. + 不能在任何其它種類的節點後面加入屬性。 + + + + An attribute by name %1 has already been created. + 名為 %1 的屬性已被建立。 + + + + Only the Unicode Codepoint Collation is supported(%1). %2 is unsupported. + 只支援 Unicode Codepoint Collation(%1)。%2 未支援。; + + + + Attribute %1 can't be serialized because it appears at the top level. + 屬性元素 %1 無法序列化,因為似乎是在頂層。 + + + + %1 is an unsupported encoding. + %1 是個未被支援的編碼。 + + + + %1 contains octets which are disallowed in the requested encoding %2. + %1 包含了在要求的編碼 %2 內不允許的八進位值。 + + + + The codepoint %1, occurring in %2 using encoding %3, is an invalid XML character. + 在 %2 內的代碼點 %1(編碼 %3)是一個不合法的 XML 字元。 + + + + Ambiguous rule match. + 不明確的規則符合。 + + + In a namespace constructor, the value for a namespace value cannot be an empty string. + 在命名空間建構子中,命名空間的值不能是空字串。 + + + + In a namespace constructor, the value for a namespace cannot be an empty string. + + + + + The prefix must be a valid %1, which %2 is not. + 前置字串必須是合法的 %1,但 %2 不是。 + + + + The prefix %1 cannot be bound. + 前置字串 %1 不能被結合。 + + + + Only the prefix %1 can be bound to %2 and vice versa. + 只有前置字串 %1 能與 %2 結合。反之亦然。 + + + + Circularity detected + 偵測到環狀 + + + + The parameter %1 is required, but no corresponding %2 is supplied. + 需要參數 %1,但是沒有提供相關的 %2。 + + + + The parameter %1 is passed, but no corresponding %2 exists. + 參數 %1 已傳送,但找不到相關的 %2。 + + + + The URI cannot have a fragment + URI 不能有片段。 + + + + Element %1 is not allowed at this location. + 元素 %1 不能在此位置。 + + + + Text nodes are not allowed at this location. + 文字節點不能在此位置。 + + + + Parse error: %1 + 剖析錯誤:%1 + + + + The value of the XSL-T version attribute must be a value of type %1, which %2 isn't. + XLS-T 版本屬性的值必須是型態 %1 的值,而 %2 不是。 + + + + Running an XSL-T 1.0 stylesheet with a 2.0 processor. + 使用 2.0 處理器執行 XSL-T 1.0 樣式表中。 + + + + Unknown XSL-T attribute %1. + 未知的 XSL-T 屬性 %1。 + + + + Attribute %1 and %2 are mutually exclusive. + 屬性 %1 與 %2 彼此互斥。 + + + + In a simplified stylesheet module, attribute %1 must be present. + 在簡化的樣式表模組中,屬性 %1 必須存在。 + + + + If element %1 has no attribute %2, it cannot have attribute %3 or %4. + 若元素 %1 沒有屬性 %2,則也不能有屬性 %3 或 %4。 + + + + Element %1 must have at least one of the attributes %2 or %3. + 元素 %1 必須至少有屬性 %2 或 %3 其中一個。 + + + + At least one mode must be specified in the %1-attribute on element %2. + 在元素 %2 的 %1 屬性中至少要指定一個模式。 + + + + Attribute %1 cannot appear on the element %2. Only the standard attributes can appear. + 屬性 %1 不能出現在元素 %2。只能有標準屬性。 + + + + Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes. + 屬性 %1 不能出現在元素 %2。只能有 %3 以及標準屬性。 + + + + Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes. + 屬性 %1 不能出現在元素 %2。只能有 %3,%4 以及標準屬性。 + + + + Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes. + 屬性 %1 不能出現在元素 %2。只能有 %3 以及標準屬性。 + + + + XSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is. + XSL-T 元素內的 XSL-T 屬性必須放在空(null)的命名空間,而不是像 %1 在 XSL-T 命名空間。 + + + + The attribute %1 must appear on element %2. + 屬性 %1 必須在元素 %2 內出現。 + + + + The element with local name %1 does not exist in XSL-T. + 有本地名稱 %1 的元素在 XSL-T 內不存在。 + + + + Element %1 must come last. + 元素 %1 必須最後出現。 + + + + At least one %1-element must occur before %2. + 至少一個元素 %1 要出現在 %2 之前。 + + + + Only one %1-element can appear. + 只能出現一個元素 %1。 + + + + At least one %1-element must occur inside %2. + 至少一個元素 %1 要出現在 %2 之內。 + + + + When attribute %1 is present on %2, a sequence constructor cannot be used. + 當屬性 %1 出現在 %2 內時,不能使用序列建構子。 + + + + Element %1 must have either a %2-attribute or a sequence constructor. + 元素 %1 必須至少有一個屬性 %2 或一個序列建構子。 + + + + When a parameter is required, a default value cannot be supplied through a %1-attribute or a sequence constructor. + 當需要參數時,不能透過屬性 %1 或序列建構子提供預設值。 + + + + Element %1 cannot have children. + 元素 %1 不能有子元素。 + + + + Element %1 cannot have a sequence constructor. + 元素 %1不能有序列建構子。 + + + + + The attribute %1 cannot appear on %2, when it is a child of %3. + 屬性 %1 不能出現在 %2,因為它是 %3 的子元素。 + + + + A parameter in a function cannot be declared to be a tunnel. + 函式內的參數不能被宣告為通道(tunnel)。 + + + + This processor is not Schema-aware and therefore %1 cannot be used. + 此處理器不是 Schema-aware,因此不能使用 %1。 + + + + Top level stylesheet elements must be in a non-null namespace, which %1 isn't. + 頂層樣式表元素必須是非空白的命名空間,而 %1 不是。 + + + + The value for attribute %1 on element %2 must either be %3 or %4, not %5. + 元素 %2 內屬性 %1 的值必須是 %3 或 %4,而不是 %5。 + + + + Attribute %1 cannot have the value %2. + 屬性 %1 的值不能為 %2。 + + + + The attribute %1 can only appear on the first %2 element. + 屬性 %1 只能出現在前 %2 個元素內。 + + + + At least one %1 element must appear as child of %2. + %2 必須至少有一個子元素 %1。 + + + + VolumeSlider + + + Muted + 靜音 + + + + + Volume: %1% + 音量:%1% + + + + WebCore::PlatformScrollbar + + Scroll here + 在此捲軸 + + + Left edge + 左邊緣 + + + Top + 頂端 + + + Right edge + 右邊緣 + + + Bottom + 底端 + + + Page left + 頁面左方 + + + Page up + 頁面上方 + + + Page right + 頁面右方 + + + Page down + 頁面下方 + + + Scroll left + 往左捲軸 + + + Scroll up + 往上捲軸 + + + Scroll right + 往右捲軸 + + + Scroll down + 往下捲軸 + + + diff --git a/release/ts/qt_windows_he.qm b/release/ts/qt_windows_he.qm new file mode 100644 index 0000000..4ff507e Binary files /dev/null and b/release/ts/qt_windows_he.qm differ diff --git a/release/ts/qt_windows_sv.qm b/release/ts/qt_windows_sv.qm new file mode 100644 index 0000000..f3556bc Binary files /dev/null and b/release/ts/qt_windows_sv.qm differ diff --git a/release/ts/qt_windows_zh.qm b/release/ts/qt_windows_zh.qm new file mode 100644 index 0000000..623b8e3 Binary files /dev/null and b/release/ts/qt_windows_zh.qm differ diff --git a/release/ts/qt_windows_zh.ts b/release/ts/qt_windows_zh.ts new file mode 100644 index 0000000..e84fe8e --- /dev/null +++ b/release/ts/qt_windows_zh.ts @@ -0,0 +1,7964 @@ + + + + + MAC_APPLICATION_MENU + + + Services + 服务 + + + + Hide %1 + 隐藏%1 + + + + Hide Others + 隐藏其他 + + + + Show All + 全部显示 + + + + Preferences... + 偏好设置… + + + + Quit %1 + 退出 %1 + + + + About %1 + 关于 %1 + + + + AudioOutput + + + <html>The audio playback device <b>%1</b> does not work.<br/>Falling back to <b>%2</b>.</html> + <html>音频回放设备 <b>%1</b> 没有工作。<br/>回滚到 <b>%2</b>。</html> + + + + <html>Switching to the audio playback device <b>%1</b><br/>which just became available and has higher preference.</html> + <html>切换到音频回放设备 <b>%1</b>,<br/>它刚刚变为可用并且具有更高的优先级。</html> + + + + Revert back to device '%1' + 恢复到设备“%1” + + + + CloseButton + + + Close Tab + 关闭标签页 + + + + Phonon:: + + + Notifications + 通知 + + + + Music + 音乐 + + + + Video + 视频 + + + + Communication + 通讯 + + + + Games + 游戏 + + + + Accessibility + 无障碍环境 + + + + Phonon::Gstreamer::Backend + + + Warning: You do not seem to have the package gstreamer0.10-plugins-good installed. + Some video features have been disabled. + 警告:看起来,您没有安装 gstreamer0.10-plugins-good 包。 + 一些视频特性已经被关闭。 + + + + Warning: You do not seem to have the base GStreamer plugins installed. + All audio and video support has been disabled + 警告:看起来,您没有安装基础的 GStreamer 插件。 + 所有的音频和视频支持都已经被关闭。 + + + + Phonon::Gstreamer::MediaObject + + + Cannot start playback. + +Check your Gstreamer installation and make sure you +have libgstreamer-plugins-base installed. + 不能开始回放。 + +请检查您的 Gstreamer 安装并且确认您 +已经安装 libgstreamer-plugins-base。 + + + + A required codec is missing. You need to install the following codec(s) to play this content: %0 + 缺少一个需要的解码器。您需要安装如下解码器来播放这个内容:%0 + + + + + + + + + + + Could not open media source. + 不能打开媒体源。 + + + + Invalid source type. + 无效的源类型。 + + + + Could not locate media source. + 不能定位媒体源。 + + + + Could not open audio device. The device is already in use. + 不能打开音频设备。这个设备正在被使用。 + + + + Could not decode media source. + 不能解码媒体源。 + + + + Phonon::VolumeSlider + + + + Volume: %1% + 音量:%1% + + + + + + Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1% + 请使用这个滑块调节音量。最左为%0,最右为%1% + + + + Q3Accel + + + %1, %2 not defined + %1,%2未定义 + + + + Ambiguous %1 not handled + 不明确的%1没有被处理 + + + + Q3DataTable + + + True + + + + + False + + + + + Insert + 插入 + + + + Update + 更新 + + + + Delete + 删除 + + + + Q3FileDialog + + + Copy or Move a File + 复制或者移动一个文件 + + + + Read: %1 + 读取:%1 + + + + + Write: %1 + 写入:%1 + + + + + Cancel + 取消 + + + + + + + All Files (*) + 所有文件 (*) + + + + Name + 名称 + + + + Size + 大小 + + + + Type + 类型 + + + + Date + 日期 + + + + Attributes + 属性 + + + + + &OK + 确定(&O) + + + + Look &in: + 查找范围(&I): + + + + + + File &name: + 文件名称(&N): + + + + File &type: + 文件类型(&T): + + + + Back + 后退 + + + + One directory up + 向上一级 + + + + Create New Folder + 创建新文件夹 + + + + List View + 列表视图 + + + + Detail View + 详细视图 + + + + Preview File Info + 预览文件信息 + + + + Preview File Contents + 预览文件内容 + + + + Read-write + 读写 + + + + Read-only + 只读 + + + + Write-only + 只写 + + + + Inaccessible + 不可访问的 + + + + Symlink to File + 文件的系统链接 + + + + Symlink to Directory + 目录的系统链接 + + + + Symlink to Special + 特殊的系统链接 + + + + File + 文件 + + + + Dir + 目录 + + + + Special + 特殊 + + + + + + Open + 打开 + + + + + Save As + 另存为 + + + + + + &Open + 打开(&O) + + + + + &Save + 保存(&S) + + + + &Rename + 重命名(&R) + + + + &Delete + 删除(&D) + + + + R&eload + 重新载入(&E) + + + + Sort by &Name + 按名称排列(&N) + + + + Sort by &Size + 按大小排列(&S) + + + + Sort by &Date + 按日期排列(&D) + + + + &Unsorted + 未排列的(&U) + + + + Sort + 排列 + + + + Show &hidden files + 显示隐藏文件(&H) + + + + the file + 文件 + + + + the directory + 目录 + + + + the symlink + 系统链接 + + + + Delete %1 + 删除%1 + + + + <qt>Are you sure you wish to delete %1 "%2"?</qt> + <qt>你确认你想删除%1,“%2”?</qt> + + + + &Yes + 是(&Y) + + + + &No + 否(&N) + + + + New Folder 1 + 新建文件夹1 + + + + New Folder + 新建文件夹 + + + + New Folder %1 + 新建文件夹%1 + + + + Find Directory + 查找目录 + + + + + Directories + 目录 + + + + Directory: + 目录: + + + + + Error + 错误 + + + + %1 +File not found. +Check path and filename. + 文件%1 +未找到。 +请检查路径和文件名。 + + + + + All Files (*.*) + 所有文件 (*.*) + + + + Open + 打开 + + + + Select a Directory + 选择一个目录 + + + + Q3LocalFs + + + + Could not read directory +%1 + 不能读取目录 +%1 + + + + Could not create directory +%1 + 不能创建目录 +%1 + + + + Could not remove file or directory +%1 + 不能移除文件或者目录 +%1 + + + + Could not rename +%1 +to +%2 + 不能把 +%1 +重命名为 +%2 + + + + Could not open +%1 + 不能打开 +%1 + + + + Could not write +%1 + 不能写入 +%1 + + + + Q3MainWindow + + + Line up + 排列 + + + + Customize... + 自定义... + + + + Q3NetworkProtocol + + + Operation stopped by the user + 操作被用户停止 + + + + Q3ProgressDialog + + + + Cancel + 取消 + + + + Q3TabDialog + + + + OK + 确认 + + + + Apply + 应用 + + + + Help + 帮助 + + + + Defaults + 默认 + + + + Cancel + 取消 + + + + Q3TextEdit + + + &Undo + 撤消(&U) + + + + &Redo + 恢复(&R) + + + + Cu&t + 剪切(&T) + + + + &Copy + 复制(&C) + + + + &Paste + 粘贴(&P) + + + + Clear + 清空 + + + + + Select All + 选择全部 + + + + Q3TitleBar + + + System + 系统 + + + + Restore up + 向上恢复 + + + + Minimize + 最小化 + + + + Restore down + 向下恢复 + + + + Maximize + 最大化 + + + + Close + 关闭 + + + + Contains commands to manipulate the window + 包含操作窗口的命令。 + + + + Puts a minimized back to normal + 把一个最小化窗口恢复为普通状态 + + + + Moves the window out of the way + 把窗口移到外面 + + + + Puts a maximized window back to normal + 把一个最大化窗口恢复为普通状态 + + + + Makes the window full screen + 窗口全屏化 + + + + Closes the window + 关闭窗口 + + + + Displays the name of the window and contains controls to manipulate it + 显示窗口名称并且包含维护它的控件 + + + + Q3ToolBar + + + More... + 更多... + + + + Q3UrlOperator + + + + + The protocol `%1' is not supported + 协议“%1”不被支持 + + + + The protocol `%1' does not support listing directories + 协议“%1”不支持列出目录 + + + + The protocol `%1' does not support creating new directories + 协议“%1”不支持创建新目录 + + + + The protocol `%1' does not support removing files or directories + 协议“%1”不支持移除文件或者目录 + + + + The protocol `%1' does not support renaming files or directories + 协议“%1”不支持重命名文件或者目录 + + + + The protocol `%1' does not support getting files + 协议“%1”不支持获取文件 + + + + The protocol `%1' does not support putting files + 协议“%1”不支持上传文件 + + + + + The protocol `%1' does not support copying or moving files or directories + 协议“%1”不支持复制或者移动文件或者目录 + + + + + (unknown) + (未知的) + + + + Q3Wizard + + + &Cancel + 取消(&C) + + + + < &Back + < 上一步(&B) + + + + &Next > + 下一步(&N) > + + + + &Finish + 完成(&F) + + + + &Help + 帮助(&H) + + + + QAbstractSocket + + + + + + Host not found + 主机未找到 + + + + + + Connection refused + 连接被拒绝 + + + + Connection timed out + 连接超时 + + + + + + Operation on socket is not supported + Socket操作不被支持 + + + + Socket operation timed out + 套接字操作超时 + + + + Socket is not connected + 套接字没有被连接 + + + + Network unreachable + 网络不能访问 + + + + QAbstractSpinBox + + + &Step up + 增加(&S) + + + + Step &down + 减少(&D) + + + + &Select All + 选择全部(&S) + + + + QApplication + + + Activate + 激活 + + + + Executable '%1' requires Qt %2, found Qt %3. + 执行“%1”需要Qt %2,只找到了Qt %3。 + + + + Incompatible Qt Library Error + 不兼容的Qt错误 + + + + QT_LAYOUT_DIRECTION + Translate this string to the string 'LTR' in left-to-right languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to get proper widget layout. + LTR + + + + Activates the program's main window + 激活这个程序的主窗口 + + + + QAxSelect + + + Select ActiveX Control + 选择ActiveX控件 + + + + OK + 确定 + + + + &Cancel + 取消(&C) + + + + COM &Object: + COM对象(&O): + + + + QCheckBox + + + Uncheck + 取消选中 + + + + Check + 选中 + + + + Toggle + 切换 + + + + QColorDialog + + + Hu&e: + 色调(&E): + + + + &Sat: + 饱和度(&S): + + + + &Val: + 亮度(&V): + + + + &Red: + 红色(&R): + + + + &Green: + 绿色(&G): + + + + Bl&ue: + 蓝色(&U): + + + + A&lpha channel: + Alpha通道(&A): + + + + Select Color + 选择颜色 + + + + &Basic colors + 基本颜色(&B) + + + + &Custom colors + 自定义颜色(&C) + + + + &Add to Custom Colors + 添加到自定义颜色(&A) + + + Select color + 选择颜色 + + + + QComboBox + + + + Open + 打开 + + + + False + + + + + True + + + + + Close + 关闭 + + + + QCoreApplication + + %1: permission denied + QSystemSemaphore + %1:权限被拒绝 + + + %1: already exists + QSystemSemaphore + %1:已经存在 + + + %1: doesn't exists + QSystemSemaphore + %1:不存在 + + + %1: out of resources + QSystemSemaphore + %1:资源耗尽了 + + + %1: unknown error %2 + QSystemSemaphore + %1:未知错误 %2 + + + + %1: key is empty + QSystemSemaphore + %1:键是空的 + + + + %1: unable to make key + QSystemSemaphore + %1:不能制造键 + + + + %1: ftok failed + QSystemSemaphore + %1:ftok 失败 + + + + QDB2Driver + + + Unable to connect + 不能连接 + + + + Unable to commit transaction + 不能提交事务 + + + + Unable to rollback transaction + 不能回滚事务 + + + + Unable to set autocommit + 不能设置自动提交 + + + + QDB2Result + + + + Unable to execute statement + 不能执行语句 + + + + Unable to prepare statement + 不能准备语句 + + + + Unable to bind variable + 不能帮定变量 + + + + Unable to fetch record %1 + 不能获取记录%1 + + + + Unable to fetch next + 不能获取下一个 + + + + Unable to fetch first + 不能获取第一个 + + + + QDateTimeEdit + + + AM + AM + + + + am + am + + + + PM + PM + + + + pm + pm + + + + QDial + + + QDial + QDial + + + + SpeedoMeter + SpeedoMeter + + + + SliderHandle + SliderHandle + + + + QDialog + + + What's This? + 这是什么? + + + + Done + 完成 + + + + QDialogButtonBox + + + + + OK + 确定 + + + + Save + 保存 + + + + &Save + 保存(&S) + + + + Open + 打开 + + + + Cancel + 取消 + + + + &Cancel + 取消(&C) + + + + Close + 关闭 + + + + &Close + 关闭(&C) + + + + Apply + 应用 + + + + Reset + 重置 + + + + Help + 帮助 + + + + Don't Save + 不保存 + + + + Discard + 抛弃 + + + + &Yes + 是(&Y) + + + + Yes to &All + 全部是(&A) + + + + &No + 否(&N) + + + + N&o to All + 全部否(&O) + + + + Save All + 保存全部 + + + + Abort + 放弃 + + + + Retry + 重试 + + + + Ignore + 忽略 + + + + Restore Defaults + 恢复默认 + + + + Close without Saving + 不保存关闭 + + + + &OK + 确定(&O) + + + + QDirModel + + + Name + 名称 + + + + Size + 大小 + + + + Kind + Match OS X Finder + 类型 + + + + Type + All other platforms + 类型 + + + + Date Modified + 日期被修改 + + + + QDockWidget + + + Close + 关闭 + + + + Dock + 锚接 + + + + Float + 浮动 + + + + QDoubleSpinBox + + + More + 更多 + + + + Less + 更少 + + + + QErrorMessage + + + Debug Message: + 调试消息: + + + + Warning: + 警告: + + + + Fatal Error: + 致命错误: + + + + &Show this message again + 再次显示这个消息(&S) + + + + &OK + 确定(&O) + + + + QFile + + + + Destination file exists + 目标文件已存在 + + + + Cannot remove source file + + + + + Cannot open %1 for input + 无法输入 %1 + + + + Cannot open for output + 无法输出 + + + + Failure to write block + 写块失败 + + + + Cannot create %1 for output + 无法创建 %1 + + + + QFileDialog + + + + All Files (*) + 所有文件 (*) + + + + Directories + 目录 + + + + + + + &Open + 打开(&O) + + + + + &Save + 保存(&S) + + + + Open + 打开 + + + + %1 already exists. +Do you want to replace it? + %1已经存在。 +你想要替换它么? + + + + %1 +File not found. +Please verify the correct file name was given. + 文件%1 +没有找到。 +请核实已给定正确文件名。 + + + + My Computer + 我的计算机 + + + + &Rename + 重命名(&R) + + + + &Delete + 删除(&D) + + + + Show &hidden files + 显示隐藏文件(&H) + + + + + Back + 后退 + + + + + Parent Directory + 父目录 + + + + + List View + 列表视图 + + + + + Detail View + 详细视图 + + + + + Files of type: + 文件类型: + + + + + Directory: + 目录: + + + + + %1 +Directory not found. +Please verify the correct directory name was given. + 目录%1 +没有找到。 +请核实已给定正确目录名。 + + + + '%1' is write protected. +Do you want to delete it anyway? + “%1“是写保护的。 +你还是想删除它么? + + + + Are sure you want to delete '%1'? + 你确认你想删除“%1“? + + + + Could not delete directory. + 不能删除目录。 + + + + Recent Places + 最近的地方 + + + + Save As + 另存为 + + + + Drive + 驱动器 + + + + + File + 文件 + + + + Unknown + 未知的 + + + + Find Directory + 查找目录 + + + + Show + 显示 + + + + + Forward + 前进 + + + + New Folder + 新建文件夹 + + + + &New Folder + 新建文件夹(&N) + + + + + &Choose + 选择(&C) + + + + Remove + 移除 + + + + + File &name: + 文件名称(&N): + + + + + Look in: + 查看: + + + + + Create New Folder + 创建新文件夹 + + + + All Files (*.*) + 所有文件 (*.*) + + + + QFileSystemModel + + + %1 TB + %1 TB + + + + %1 GB + %1 GB + + + + %1 MB + %1 MB + + + + %1 KB + %1千字节 + + + + %1 bytes + %1字节 + + + + Invalid filename + 无效文件名 + + + + <b>The name "%1" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks. + <b>名称“%1“不能被使用。</b><p>请使用另外一个包含更少字符或者不含有标点符号的名称。 + + + + Name + 名称 + + + + Size + 大小 + + + + Kind + Match OS X Finder + 类型 + + + + Type + All other platforms + 类型 + + + + Date Modified + 日期被修改 + + + + My Computer + 我的计算机 + + + + Computer + 计算机 + + + + QFontDatabase + + + + Normal + 普通 + + + + + + Bold + 粗体 + + + + + Demi Bold + 半粗体 + + + + + + Black + 黑体 + + + + Demi + 半体 + + + + + Light + 轻体 + + + + + Italic + 意大利体 + + + + + Oblique + 斜体 + + + + Any + 任意 + + + + Latin + 拉丁文 + + + + Greek + 希腊文 + + + + Cyrillic + 西里尔文 + + + + Armenian + 亚美尼亚文 + + + + Hebrew + 希伯来文 + + + + Arabic + 阿拉伯文 + + + + Syriac + 叙利亚文 + + + + Thaana + 马尔代夫文 + + + + Devanagari + 梵文 + + + + Bengali + 孟加拉文 + + + + Gurmukhi + 旁遮普文 + + + + Gujarati + 古吉拉特文 + + + + Oriya + 奥里雅文 + + + + Tamil + 泰米尔文 + + + + Telugu + 泰卢固文 + + + + Kannada + 埃纳德文 + + + + Malayalam + 马拉亚拉姆文 + + + + Sinhala + 僧伽罗文 + + + + Thai + 泰国文 + + + + Lao + 老挝文 + + + + Tibetan + 藏文 + + + + Myanmar + 缅甸文 + + + + Georgian + 格鲁吉亚文 + + + + Khmer + 谷美尔文 + + + + Simplified Chinese + 简体中文 + + + + Traditional Chinese + 繁体中文 + + + + Japanese + 日文 + + + + Korean + 韩文 + + + + Vietnamese + 越南文 + + + + Symbol + 符号 + + + + Ogham + 欧甘文 + + + + Runic + 古北欧文 + + + + QFontDialog + + + &Font + 字体(&F) + + + + Font st&yle + 字体风格(&Y) + + + + &Size + 大小(&S) + + + + Effects + 效果 + + + + Stri&keout + 删除线(&K) + + + + &Underline + 下划线(&U) + + + + Sample + 实例 + + + + Wr&iting System + 书写系统(&I) + + + + + Select Font + 选择字体 + + + + QFtp + + + + Not connected + 没有连接 + + + + + Host %1 not found + 主机%1没有找到 + + + + + Connection refused to host %1 + 连接被主机 %1 拒绝 + + + + Connection timed out to host %1 + 主机%1连接超时 + + + + + + Connected to host %1 + 连接到主机%1了 + + + + + Connection refused for data connection + 因为数据连接而被拒绝连接 + + + + + + + Unknown error + 未知的错误 + + + + + Connecting to host failed: +%1 + 连接主机失败: +%1 + + + + + Login failed: +%1 + 登录失败: +%1 + + + + + Listing directory failed: +%1 + 列出目录失败: +%1 + + + + + Changing directory failed: +%1 + 改变目录失败: +%1 + + + + + Downloading file failed: +%1 + 下载文件失败: +%1 + + + + + Uploading file failed: +%1 + 上传文件失败: +%1 + + + + + Removing file failed: +%1 + 移除文件失败: +%1 + + + + + Creating directory failed: +%1 + 创建目录失败: +%1 + + + + + Removing directory failed: +%1 + 移除目录失败: +%1 + + + + + + Connection closed + 连接关闭了 + + + + Host %1 found + 主机%1找到了 + + + + Connection to %1 closed + 到%1的连接关闭了 + + + + Host found + 主机找到了 + + + + Connected to host + 连接到主机了 + + + + QHostInfo + + + Unknown error + 未知的错误 + + + + QHostInfoAgent + + + + + + + + + + Host not found + 主机未找到 + + + + + + + Unknown address type + 未知的地址类型 + + + + + + Unknown error + 未知的错误 + + + + QHttp + + + + + + Unknown error + 未知的错误 + + + + + Request aborted + 请求被放弃了 + + + + + No server set to connect to + 没有设置要连接的服务器 + + + + + Wrong content length + 错误的内容长度 + + + + + Server closed connection unexpectedly + 服务器异常地关闭了连接 + + + + Unknown authentication method + + + + + Error writing response to device + 向设备中进行写回复时发生错误 + + + + + Connection refused + 连接被拒绝 + + + + + + Host %1 not found + 主机%1没有找到 + + + + + + + HTTP request failed + HTTP请求失败 + + + + + Invalid HTTP response header + 无效的HTTP响应头 + + + + + + + Invalid HTTP chunked body + 无效的HTTP臃肿体 + + + + Host %1 found + 主机%1找到了 + + + + Connected to host %1 + 连接到%1主机了 + + + + Connection to %1 closed + 到%1的连接关闭了 + + + + Host found + 主机找到了 + + + + Connected to host + 连接到主机了 + + + + + Connection closed + 连接关闭了 + + + + Proxy authentication required + 代理需要认证 + + + + Authentication required + 需要认证 + + + + Connection refused (or timed out) + 连接被拒绝(或者超时) + + + + Proxy requires authentication + 代理需要验证 + + + + Host requires authentication + 主机需要验证 + + + + Data corrupted + 数据错误 + + + + Unknown protocol specified + 所指定的协议是未知的 + + + + SSL handshake failed + SSL 握手失败 + + + + HTTPS connection requested but SSL support not compiled in + HTTPS 连接需要 SSL,但它没有被编译进来 + + + + QHttpSocketEngine + + + Did not receive HTTP response from proxy + 未收到代理的HTTP响应 + + + + Error parsing authentication request from proxy + 解析代理的认证请求出错 + + + + Authentication required + 需要认证 + + + + Proxy denied connection + 代理拒绝连接 + + + + Error communicating with HTTP proxy + 和HTTP代理通讯时发生错误 + + + + Proxy server not found + 未找到代理服务器 + + + + Proxy connection refused + 代理连接被拒绝 + + + + Proxy server connection timed out + 代理服务器连接超时 + + + + Proxy connection closed prematurely + 代理连接过早关闭 + + + + QIBaseDriver + + + Error opening database + 打开数据库错误 + + + + Could not start transaction + 不能开始事务 + + + + Unable to commit transaction + 不能提交事务 + + + + Unable to rollback transaction + 不能回滚事务 + + + + QIBaseResult + + + Unable to create BLOB + 不能创建BLOB + + + + Unable to write BLOB + 不能写入BLOB + + + + Unable to open BLOB + 不能打开BLOB + + + + Unable to read BLOB + 不能读取BLOB + + + + + Could not find array + 不能找到数组 + + + + Could not get array data + 不能得到数组数据 + + + + Could not get query info + 不能得到查询信息 + + + + Could not start transaction + 不能开始事务 + + + + Unable to commit transaction + 不能提交事务 + + + + Could not allocate statement + 不能分配语句 + + + + Could not prepare statement + 不能准备语句 + + + + + Could not describe input statement + 不能描述输入语句 + + + + Could not describe statement + 不能描述语句 + + + + Unable to close statement + 不能关闭语句 + + + + Unable to execute query + 不能执行查询 + + + + Could not fetch next item + 不能获取下一项 + + + + Could not get statement info + 不能得到语句信息 + + + + QIODevice + + + Permission denied + 权限被拒绝 + + + + Too many open files + 太多打开的文件 + + + + No such file or directory + 没有这个文件或者目录 + + + + No space left on device + 设备上没有空间了 + + + + Unknown error + 未知的错误 + + + + QInputContext + + + XIM + XIM + + + + XIM input method + XIM输入法 + + + + Windows input method + Windows输入法 + + + + Mac OS X input method + Mac OS X输入法 + + + + QInputDialog + + + Enter a value: + 输入一个值: + + + + QLibrary + + QLibrary::load_sys: Cannot load %1 (%2) + QLibrary::load_sys: 不能载入%1 (%2) + + + QLibrary::unload_sys: Cannot unload %1 (%2) + QLibrary::unload_sys:不能卸载%1 (%2) + + + QLibrary::resolve_sys: Symbol "%1" undefined in %2 (%3) + QLibrary::resolve_sys: 符号“%1”在%2(%3)没有被定义 + + + + Could not mmap '%1': %2 + 不能映射”%1“:%2 + + + + Plugin verification data mismatch in '%1' + “%1“中的插件验证数据不匹配 + + + + Could not unmap '%1': %2 + 不能取消映射“%1“:%2 + + + + The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5] + 插件“%1”使用了不兼容的Qt库。(%2.%3.%4) [%5] + + + + The plugin '%1' uses incompatible Qt library. Expected build key "%2", got "%3" + 插件“%1“使用了不兼容的Qt库。期待的构建键是“%2“,得到的却是”%3“ + + + + Unknown error + 未知的错误 + + + + + The shared library was not found. + 共享库没有被找到。 + + + + The file '%1' is not a valid Qt plugin. + 文件“%1“不是有效的Qt插件。 + + + + The plugin '%1' uses incompatible Qt library. (Cannot mix debug and release libraries.) + 插件“%1“使用了不兼容的Qt库。(不能混合使用库的调试版本和发布版本。) + + + + + Cannot load library %1: %2 + 无法加载库%1:%2 + + + + + Cannot unload library %1: %2 + 无法卸载库%1:%2 + + + + + Cannot resolve symbol "%1" in %2: %3 + 无法解析%2中的符号“%2”:%3 + + + + QLineEdit + + + &Undo + 撤消(&U) + + + + &Redo + 恢复(&R) + + + + Cu&t + 剪切(&T) + + + + &Copy + 复制(&C) + + + + &Paste + 粘贴(&P) + + + + Delete + 删除 + + + + Select All + 选择全部 + + + + QLocalServer + + + + %1: Name error + %1: 名称错误 + + + + %1: Permission denied + %1:权限被拒绝 + + + + %1: Address in use + %1:地址正在被使用 + + + + + %1: Unknown error %2 + %1:未知错误 %2 + + + + QLocalSocket + + + + %1: Connection refused + %1:连接被拒绝 + + + + + %1: Remote closed + %1:远程已关闭 + + + + + + + %1: Invalid name + %1:无效名称 + + + + + %1: Socket access error + %1:套接字访问错误 + + + + + %1: Socket resource error + %1:套接字资源错误 + + + + + %1: Socket operation timed out + %1:套接字操作超时 + + + + + %1: Datagram too large + %1:数据报太大 + + + + + + %1: Connection error + %1:连接错误 + + + + + %1: The socket operation is not supported + %1:套接字操作不被支持 + + + + %1: Unknown error + %1:未知错误 + + + + + %1: Unknown error %2 + %1:未知错误 %2 + + + + QMYSQLDriver + + + Unable to open database ' + 不能打开数据库 + + + + Unable to connect + 不能连接 + + + + Unable to begin transaction + 不能开始事务 + + + + Unable to commit transaction + 不能提交事务 + + + + Unable to rollback transaction + 不能回滚事务 + + + + QMYSQLResult + + + Unable to fetch data + 不能获取数据 + + + + Unable to execute query + 不能执行查询 + + + + Unable to store result + 不能存储结果 + + + + + Unable to prepare statement + 不能准备语句 + + + + Unable to reset statement + 不能重置语句 + + + + Unable to bind value + 不能绑定值 + + + + Unable to execute statement + 不能执行语句 + + + + + Unable to bind outvalues + 不能绑定外值 + + + + Unable to store statement results + 不能存储语句结果 + + + + Unable to execute next query + 不能执行下一个查询 + + + + Unable to store next result + 不能存储下一个结果 + + + + QMdiArea + + + (Untitled) + (未命名的) + + + + QMdiSubWindow + + + %1 - [%2] + %1 - [%2] + + + + Close + 关闭 + + + + Minimize + 最小化 + + + + Restore Down + 向下恢复 + + + + &Restore + 恢复(&R) + + + + &Move + 移动(&M) + + + + &Size + 大小(&S) + + + + Mi&nimize + 最小化(&N) + + + + Ma&ximize + 最大化(&X) + + + + Stay on &Top + 总在最前(&T) + + + + &Close + 关闭(&C) + + + + - [%1] + - [%1] + + + + Maximize + 最大化 + + + + Unshade + 取消遮蔽 + + + + Shade + 遮蔽 + + + + Restore + 恢复 + + + + Help + 帮助 + + + + Menu + 菜单 + + + + QMenu + + + + Close + 关闭 + + + + + Open + 打开 + + + + + + Execute + 执行 + + + + QMenuBar + + About + 关于 + + + Config + 配置 + + + Preference + 首选项 + + + Options + 选项 + + + Setting + 设置 + + + Setup + 安装 + + + Quit + 退出 + + + Exit + 退出 + + + About %1 + 关于%1 + + + About Qt + 关于Qt + + + Preferences + 首选项 + + + Quit %1 + 退出%1 + + + + QMessageBox + + + Help + 帮助 + + + + + + + OK + 确定 + + + + About Qt + 关于Qt + + + <p>This program uses Qt version %1.</p> + <p>这个程序使用的是Qt %1版。</p> + + + + Show Details... + 显示细节…… + + + + Hide Details... + 隐藏细节…… + + + + <h3>About Qt</h3><p>This program uses Qt version %1.</p><p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is available under three different licensing options designed to accommodate the needs of our various users.</p>Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of the GNU LGPL version 2.1 or GNU GPL version 3.0.</p><p>Qt licensed under the GNU LGPL version 2.1 is appropriate for the development of Qt applications (proprietary or open source) provided you can comply with the terms and conditions of the GNU LGPL version 2.1.</p><p>Qt licensed under the GNU General Public License version 3.0 is appropriate for the development of Qt applications where you wish to use such applications in combination with software subject to the terms of the GNU GPL version 3.0 or where you are otherwise willing to comply with the terms of the GNU GPL version 3.0.</p><p>Please see <a href="http://qt.nokia.com/products/licensing">qt.nokia.com/products/licensing</a> for an overview of Qt licensing.</p><p>Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).</p><p>Qt is a Nokia product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is a Nokia product. See <a href="http://qt.nokia.com/">qt.nokiae.com</a> for more information.</p> + <h3>关于Qt</h3>%1<p>Qt是一个用于跨平台应用程序开发的C++工具包。</p><p>对于MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux和所有主流商业Unix,Qt提供了单一源程序的可移植性。Qt也有用于嵌入式Linux和Windows CE的版本。</p><p>Qt是Nokia的产品。有关更多信息,请参考<a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + <p>This program uses Qt Open Source Edition version %1.</p><p>Qt Open Source Edition is intended for the development of Open Source applications. You need a commercial Qt license for development of proprietary (closed source) applications.</p><p>Please see <a href="http://qt.nokia.com/company/model/">qt.nokia.com/company/model/</a> for an overview of Qt licensing.</p> + <p>这个程序使用了Qt %1开源版本。</p><p>Qt开源版本只用于开源应用程序的开发。如果要开发私有(闭源)软件,你需要一个商业的Qt协议。</p><p>有关Qt协议的概览,请参考<a href="http://qt.nokia.com/company/model/">qt.nokia.com/company/model/</a>。</p> + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt Embedded.</p><p>Qt is a Trolltech product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + <h3>关于Qt</h3>%1<p>Qt是一个用于跨平台应用程序开发的C++工具包。</p><p>对于MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux和所有主流商业Unix,Qt提供了单一源程序的可移植性。Qt对于嵌入式平台也是可用的,在嵌入式平台上它被称为Qt Embedded。</p><p>Qt是Trolltech的产品。有关更多信息,请参考<a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + + QMultiInputContext + + + Select IM + 选择输入法 + + + + QMultiInputContextPlugin + + + Multiple input method switcher + 多输入法切换器 + + + + Multiple input method switcher that uses the context menu of the text widgets + 使用文本窗口部件上下文菜单的多输入法切换器 + + + + QNativeSocketEngine + + + The remote host closed the connection + 远端主机关闭了这个连接 + + + + Network operation timed out + 网络操作超时 + + + + Out of resources + 资源耗尽了 + + + + Unsupported socket operation + 不被支持的套接字操作 + + + + Protocol type not supported + 协议类型不被支持 + + + + Invalid socket descriptor + 无效的套接字描述符 + + + + Network unreachable + 网络不能访问 + + + + Permission denied + 权限被拒绝 + + + + Connection timed out + 连接超时 + + + + Connection refused + 连接被拒绝 + + + + The bound address is already in use + 要启用的地址已经被使用 + + + + The address is not available + 这个地址不可用 + + + + The address is protected + 这个地址被保护了 + + + + Unable to send a message + 不能发送一个消息 + + + + Unable to receive a message + 不能接收一个消息 + + + + Unable to write + 不能写入 + + + + Network error + 网络错误 + + + + Another socket is already listening on the same port + 另一个套接字已经正在监听同一端口 + + + + Unable to initialize non-blocking socket + 不能初始化非阻塞套接字 + + + + Unable to initialize broadcast socket + 不能初始化广播套接字 + + + + Attempt to use IPv6 socket on a platform with no IPv6 support + 试图在不支持IPv6支持的平台上使用IPv6套接字 + + + + Host unreachable + 主机不能访问 + + + + Datagram was too large to send + 不能发送过大的数据报 + + + + Operation on non-socket + 对非套接字操作 + + + + Unknown error + 未知的错误 + + + + The proxy type is invalid for this operation + 对于这个操作代理类型是无效的。 + + + + QNetworkAccessCacheBackend + + + Error opening %1 + 打开%1发生错误 + + + + QNetworkAccessFileBackend + + + Request for opening non-local file %1 + 正在打开非本地文件 %1 的请求 + + + + Error opening %1: %2 + 打开 %1 错误:%2 + + + + Write error writing to %1: %2 + 写入 %1 错误:%2 + + + + Cannot open %1: Path is a directory + 无法打开 %1:路径是一个目录 + + + + Read error reading from %1: %2 + 读取 %1 错误:%2 + + + + QNetworkAccessFtpBackend + + + No suitable proxy found + 未找到合适的代理 + + + + Cannot open %1: is a directory + 无法读取 %1:是一个目录 + + + + Logging in to %1 failed: authentication required + 登入 %1 失败:需要验证 + + + + Error while downloading %1: %2 + 下载 %1 时错误:%2 + + + + Error while uploading %1: %2 + 上载 %1 时错误:%2 + + + + QNetworkAccessHttpBackend + + + No suitable proxy found + 未找到合适的代理 + + + + QNetworkReply + + + Error downloading %1 - server replied: %2 + 下载 %1 错误 - 服务器回复:%2 + + + + Protocol "%1" is unknown + 协议“%1”是未知的 + + + + QNetworkReplyImpl + + + + Operation canceled + 操作被取消 + + + + QOCIDriver + + + Unable to logon + 不能登录 + + + + Unable to initialize + QOCIDriver + 不能初始化 + + + + Unable to begin transaction + 不能开始事务 + + + + Unable to commit transaction + 不能提交事务 + + + + Unable to rollback transaction + 不能回滚事务 + + + + QOCIResult + + + + + Unable to bind column for batch execute + 不能绑定批处理执行的列 + + + + Unable to execute batch statement + 不能执行批处理语句 + + + + Unable to goto next + 不能进入下一个 + + + + Unable to alloc statement + 不能分配语句 + + + + Unable to prepare statement + 不能准备语句 + + + + Unable to bind value + 不能绑定值 + + + Unable to execute select statement + 不能执行选择语句 + + + + Unable to execute statement + 不能执行语句 + + + + QODBCDriver + + + Unable to connect + 不能连接 + + + + Unable to connect - Driver doesn't support all needed functionality + 不能连接—驱动程序不支持所有功能 + + + + Unable to disable autocommit + 不能禁止自动提交 + + + + Unable to commit transaction + 不能提交事务 + + + + Unable to rollback transaction + 不能回滚事务 + + + + Unable to enable autocommit + 不能打开自动提交 + + + + QODBCResult + + + + QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration + QODBCResult::reset: 不能把“SQL_CURSOR_STATIC”设置为语句属性。请检查你的ODBC驱动程序设置。 + + + + + Unable to execute statement + 不能执行语句 + + + + Unable to fetch next + 不能获取下一个 + + + + Unable to prepare statement + 不能准备语句 + + + + Unable to bind variable + 不能帮定变量 + + + + + + Unable to fetch last + 不能获取最后一个 + + + + Unable to fetch + 不能获取 + + + + Unable to fetch first + 不能获取第一个 + + + + Unable to fetch previous + 不能获取上一个 + + + + QObject + + + Home + + + + + Operation not supported on %1 + 在 %1 上不被支持的操作 + + + + Invalid URI: %1 + 无效的 URI:%1 + + + + Write error writing to %1: %2 + 写入 %1 错误:%2 + + + + Read error reading from %1: %2 + 读取 %1 错误:%2 + + + + Socket error on %1: %2 + %1 上的套接字错误:%2 + + + + Remote host closed the connection prematurely on %1 + 远程主机过早地关闭了在 %1 上的这个连接 + + + + Protocol error: packet of size 0 received + 协议错误:收到了大小为 0 的包 + + + + + No host name given + 未指定主机名 + + + + QPPDOptionsModel + + + Name + 名称 + + + + Value + + + + + QPSQLDriver + + + Unable to connect + 不能连接 + + + + Could not begin transaction + 不能开始事务 + + + + Could not commit transaction + 不能提交事务 + + + + Could not rollback transaction + 不能回滚事务 + + + + Unable to subscribe + 不能订阅 + + + + Unable to unsubscribe + 不能取消订阅 + + + + QPSQLResult + + + Unable to create query + 不能创建查询 + + + + Unable to prepare statement + 不能准备语句 + + + + QPageSetupWidget + + + Centimeters (cm) + 厘米 (cm) + + + + Millimeters (mm) + 毫米 (mm) + + + + Inches (in) + 英寸 (in) + + + + Points (pt) + 点 (pt) + + + + Form + 窗体 + + + + Paper + 纸张 + + + + Page size: + 纸张大小: + + + + Width: + 宽度: + + + + Height: + 高度: + + + + Paper source: + 纸张源: + + + + Orientation + 方向 + + + + Portrait + 纵向 + + + + Landscape + 横向 + + + + Reverse landscape + 反向横向 + + + + Reverse portrait + 反向纵向 + + + + Margins + 边距 + + + + top margin + 上边距 + + + + left margin + 左边距 + + + + right margin + 右边距 + + + + bottom margin + 下边距 + + + + QPluginLoader + + + Unknown error + 未知的错误 + + + + The plugin was not loaded. + 插件没有被载入。 + + + + QPrintDialog + + + locally connected + 本地已经连接的 + + + + + Aliases: %1 + 别名:%1 + + + + + unknown + 未知的 + + + + Print all + 打印全部 + + + + Print selection + 打印选择 + + + + Print range + 打印范围 + + + + A0 (841 x 1189 mm) + A0 (841 x 1189 毫米) + + + + A1 (594 x 841 mm) + A1 (594 x 841 毫米) + + + + A2 (420 x 594 mm) + A2 (420 x 594 毫米) + + + + A3 (297 x 420 mm) + A3 (297 x 420 毫米) + + + + A4 (210 x 297 mm, 8.26 x 11.7 inches) + A4 (210 x 297 毫米,8.26 x 11.7 英寸) + + + + A5 (148 x 210 mm) + A5 (148 x 210 毫米) + + + + A6 (105 x 148 mm) + A6 (105 x 148 毫米) + + + + A7 (74 x 105 mm) + A7 (74 x 105 毫米) + + + + A8 (52 x 74 mm) + A8 (52 x 74 毫米) + + + + A9 (37 x 52 mm) + A9 (37 x 52 毫米) + + + + B0 (1000 x 1414 mm) + B0 (1000 x 1414 毫米) + + + + B1 (707 x 1000 mm) + B1 (707 x 1000 毫米) + + + + B2 (500 x 707 mm) + B2 (500 x 707 毫米) + + + + B3 (353 x 500 mm) + B3 (353 x 500 毫米) + + + + B4 (250 x 353 mm) + B4 (250 x 353 毫米) + + + + B5 (176 x 250 mm, 6.93 x 9.84 inches) + B5 (176 x 250 毫米,6.93 x 9.84 英寸) + + + + B6 (125 x 176 mm) + B6 (125 x 176 毫米) + + + + B7 (88 x 125 mm) + B7 (88 x 125 毫米) + + + + B8 (62 x 88 mm) + B8 (62 x 88 毫米) + + + + B9 (44 x 62 mm) + B9 (44 x 62 毫米) + + + + B10 (31 x 44 mm) + B10 (31 x 44 毫米) + + + + C5E (163 x 229 mm) + C5E (163 x 229 毫米) + + + + DLE (110 x 220 mm) + DLE (110 x 220 毫米) + + + + Executive (7.5 x 10 inches, 191 x 254 mm) + Executive (7.5 x 10 英寸,191 x 254 毫米) + + + + Folio (210 x 330 mm) + Folio (210 x 330 毫米) + + + + Ledger (432 x 279 mm) + Ledger (432 x 279 毫米) + + + + Legal (8.5 x 14 inches, 216 x 356 mm) + Legal (8.5 x 14 英寸,216 x 356 毫米) + + + + Letter (8.5 x 11 inches, 216 x 279 mm) + Letter (8.5 x 11 英寸,216 x 279 毫米) + + + + Tabloid (279 x 432 mm) + Tabloid (279 x 432 毫米) + + + + US Common #10 Envelope (105 x 241 mm) + 美国普通10号信封 (105 x 241 毫米) + + + + OK + 确定 + + + + + + Print + 打印 + + + + Print To File ... + 打印到文件…… + + + + File %1 is not writable. +Please choose a different file name. + 文件%1不可写。 +请选择一个不同的文件名。 + + + + %1 already exists. +Do you want to overwrite it? + %1已经存在。 +你想覆盖它么? + + + + File exists + 文件存在 + + + + <qt>Do you want to overwrite it?</qt> + <qt>你想覆盖它么?</qt> + + + + %1 is a directory. +Please choose a different file name. + %1是目录。 +请选择一个不同的文件名。 + + + + The 'From' value cannot be greater than the 'To' value. + “从”的数值不能大于“到”的数值。 + + + + A0 + A0 + + + + A1 + A1 + + + + A2 + A2 + + + + A3 + A3 + + + + A4 + A4 + + + + A5 + A5 + + + + A6 + A6 + + + + A7 + A7 + + + + A8 + A8 + + + + A9 + A9 + + + + B0 + B0 + + + + B1 + B1 + + + + B2 + B2 + + + + B3 + B3 + + + + B4 + B4 + + + + B5 + B5 + + + + B6 + B6 + + + + B7 + B7 + + + + B8 + B8 + + + + B9 + B9 + + + + B10 + B10 + + + + C5E + C5E + + + + DLE + DLE + + + + Executive + 决策文书 + + + + Folio + 对开纸 + + + + Ledger + 帐页 + + + + Legal + 法律文书 + + + + Letter + 信纸 + + + + Tabloid + 小型报纸 + + + + US Common #10 Envelope + 美国普通10号信封 + + + + Custom + 自定义 + + + + + &Options >> + 选项(&O) >> + + + + &Print + 打印(&P) + + + + &Options << + 选项(&O) << + + + + Print to File (PDF) + 打印到文件(PDF) + + + + Print to File (Postscript) + 打印到文件(Postscript) + + + + Local file + 本地文件 + + + + Write %1 file + 写入 %1 文件 + + + + QPrintPreviewDialog + + + + Page Setup + 页面设置 + + + + %1% + %1% + + + + Print Preview + 打印预览 + + + + Next page + 下一页 + + + + Previous page + 上一页 + + + + First page + 第一页 + + + + Last page + 最后一页 + + + + Fit width + 适应宽度 + + + + Fit page + 适应页面 + + + + Zoom in + 放大 + + + + Zoom out + 缩小 + + + + Portrait + 纵向 + + + + Landscape + 横向 + + + + Show single page + 显示单页 + + + + Show facing pages + 显示当前页 + + + + Show overview of all pages + 显示所有页的概览 + + + + Print + 打印 + + + + Page setup + 打印设置 + + + + Close + 关闭 + + + + Export to PDF + 导出为PDF + + + + Export to PostScript + 导出为PostScript + + + + QPrintPropertiesWidget + + + Form + 窗体 + + + + Page + + + + + Advanced + 高级 + + + + QPrintSettingsOutput + + + Form + 窗体 + + + + Copies + 拷贝 + + + + Print range + 打印范围 + + + + Print all + 打印全部 + + + + Pages from + 页数从 + + + + to + + + + + Selection + 选择 + + + + Output Settings + 输出设置 + + + + Copies: + 备份: + + + + Collate + 校对 + + + + Reverse + 反向 + + + + Options + 选项 + + + + Color Mode + 彩色模式 + + + + Color + 彩色 + + + + Grayscale + 灰度 + + + + Duplex Printing + 两部分打印 + + + + None + + + + + Long side + 长侧 + + + + Short side + 短侧 + + + + QPrintWidget + + + Form + 窗体 + + + + Printer + 打印机 + + + + &Name: + 名称(&N): + + + + P&roperties + 属性(&R) + + + + Location: + 位置: + + + + Preview + 预览 + + + + Type: + 类型: + + + + Output &file: + 输出文件(&F): + + + + ... + ... + + + + QProcess + + + + Could not open input redirection for reading + 无法打开用于读取的输入重定向 + + + + + Could not open output redirection for writing + 无法打开用于写入的输出重定向 + + + + Resource error (fork failure): %1 + 资源错误(fork失败):%1 + + + + + + + + + + + + Process operation timed out + 进程处理超时 + + + + + + + Error reading from process + 从进程中读取时发生错误 + + + + + + Error writing to process + 向进程写入时发生错误 + + + + Process crashed + 进程已崩溃 + + + + No program defined + + + + + Process failed to start + 启动进程失败 + + + + QProgressDialog + + + Cancel + 撤消 + + + + QPushButton + + + Open + 打开 + + + + QRadioButton + + + Check + 选中 + + + + QRegExp + + + no error occurred + 没有错误发生 + + + + disabled feature used + 使用了失效的特效 + + + + bad char class syntax + 错误的字符类语法 + + + + bad lookahead syntax + 错误的预测语法 + + + + bad repetition syntax + 错误的重复语法 + + + + invalid octal value + 无效的八进制数值 + + + + missing left delim + 找不到左分隔符 + + + + unexpected end + 意外的终止 + + + + met internal limit + 遇到内部限制 + + + + QSQLite2Driver + + + Error to open database + 打开数据库错误 + + + + Unable to begin transaction + 不能开始事务 + + + + Unable to commit transaction + 不能提交事务 + + + + Unable to rollback Transaction + 不能回滚事务 + + + + QSQLite2Result + + + Unable to fetch results + 不能获取结果 + + + + Unable to execute statement + 不能执行语句 + + + + QSQLiteDriver + + + Error opening database + 打开数据库错误 + + + + Error closing database + 关闭数据库错误 + + + + Unable to begin transaction + 不能开始事务 + + + + Unable to commit transaction + 不能提交事务 + + + + Unable to rollback transaction + 不能回滚事务 + + + + QSQLiteResult + + + + + Unable to fetch row + 不能获取行 + + + + Unable to execute statement + 不能执行语句 + + + + Unable to reset statement + 不能重置语句 + + + + Unable to bind parameters + 不能绑定参数 + + + + Parameter count mismatch + 参数数量不匹配 + + + + No query + 没有查询 + + + + QScrollBar + + + Scroll here + 滚动到这里 + + + + Left edge + 左边缘 + + + + Top + 顶部 + + + + Right edge + 右边缘 + + + + Bottom + 底部 + + + + Page left + 左一页 + + + + + Page up + 上一页 + + + + Page right + 右一页 + + + + + Page down + 下一页 + + + + Scroll left + 向左滚动 + + + + Scroll up + 向上滚动 + + + + Scroll right + 向右滚动 + + + + Scroll down + 向下滚动 + + + + Line up + 向上排列 + + + + Position + 位置 + + + + Line down + 向下排列 + + + + QSharedMemory + + + %1: unable to set key on lock + %1:无法设置锁定的键 + + + + %1: create size is less then 0 + %1:创建的大小小于 0 + + + + + %1: unable to lock + %1:无法锁定 + + + + %1: unable to unlock + %1:无法取消锁定 + + + + + %1: permission denied + %1:权限被拒绝 + + + + + %1: already exists + %1:已经存在 + + + + + %1: doesn't exists + %1:不存在 + + + + + %1: out of resources + %1:资源耗尽了 + + + + + %1: unknown error %2 + %1:未知错误 %2 + + + + %1: key is empty + %1:键是空的 + + + + %1: unix key file doesn't exists + %1:Unix 键文件不存在 + + + + %1: ftok failed + %1:ftok 失败 + + + + + %1: unable to make key + %1:不能制造键 + + + + %1: system-imposed size restrictions + %1:系统预设大小限制 + + + + %1: not attached + %1:没有附加 + + + + %1: invalid size + %1:无效大小 + + + + %1: key error + %1: 键错误 + + + + %1: size query failed + %1:大小查询失败 + + + + QShortcut + + + Space + 空格 + + + + Esc + Esc + + + + Tab + Tab + + + + Backtab + Backtab + + + + Backspace + Backspace + + + + Return + Return + + + + Enter + Enter + + + + Ins + Ins + + + + Del + Del + + + + Pause + Pause + + + + Print + Print + + + + SysReq + SysReq + + + + Home + Home + + + + End + End + + + + Left + Left + + + + Up + Up + + + + Right + Right + + + + Down + Down + + + + PgUp + PgUp + + + + PgDown + PgDown + + + + CapsLock + CapsLock + + + + NumLock + NumLock + + + + ScrollLock + ScrollLock + + + + Menu + Menu + + + + Help + Help + + + + Back + 后退 + + + + Forward + 前进 + + + + Stop + 停止 + + + + Refresh + 刷新 + + + + Volume Down + 调小音量 + + + + Volume Mute + 静音 + + + + Volume Up + 调大音量 + + + + Bass Boost + 低音增强 + + + + Bass Up + 调大低音 + + + + Bass Down + 调小低音 + + + + Treble Up + 调大高音 + + + + Treble Down + 调小高音 + + + + Media Play + 多媒体播放 + + + + Media Stop + 多媒体停止 + + + + Media Previous + 上一个多媒体 + + + + Media Next + 下一个多媒体 + + + + Media Record + 多媒体记录 + + + + Favorites + 最喜爱的 + + + + Search + 搜索 + + + + Standby + 等待 + + + + Open URL + 打开URL + + + + Launch Mail + 启动邮件 + + + + Launch Media + 启动多媒体 + + + + Launch (0) + 启动 (0) + + + + Launch (1) + 启动 (1) + + + + Launch (2) + 启动 (2) + + + + Launch (3) + 启动 (3) + + + + Launch (4) + 启动 (4) + + + + Launch (5) + 启动 (5) + + + + Launch (6) + 启动 (6) + + + + Launch (7) + 启动 (7) + + + + Launch (8) + 启动 (8) + + + + Launch (9) + 启动 (9) + + + + Launch (A) + 启动 (A) + + + + Launch (B) + 启动 (B) + + + + Launch (C) + 启动 (C) + + + + Launch (D) + 启动 (D) + + + + Launch (E) + 启动 (E) + + + + Launch (F) + 启动 (F) + + + + Print Screen + Print Screen + + + + Page Up + Page Up + + + + Page Down + Page Down + + + + Caps Lock + Caps Lock + + + + Num Lock + Num Lock + + + + Number Lock + Number Lock + + + + Scroll Lock + Scroll Lock + + + + Insert + Insert + + + + Delete + Delete + + + + Escape + Escape + + + + System Request + System Request + + + + Select + 选择 + + + + Yes + + + + + No + + + + + Context1 + 上下文1 + + + + Context2 + 上下文2 + + + + Context3 + 上下文3 + + + + Context4 + 上下文4 + + + + Call + 呼叫 + + + + Hangup + 挂起 + + + + Flip + 翻转 + + + + + Ctrl + Ctrl + + + + + Shift + Shift + + + + + Alt + Alt + + + + + Meta + Meta + + + + + + + + + + + F%1 + F%1 + + + + Home Page + 主页 + + + + QSlider + + + Page left + 左一页 + + + + Page up + 上一页 + + + + Position + 位置 + + + + Page right + 右一页 + + + + Page down + 下一页 + + + + QSocks5SocketEngine + + + Connection to proxy refused + 代理拒绝连接 + + + + Connection to proxy closed prematurely + 代理连接过早关闭 + + + + Proxy host not found + 代理主机未找到 + + + + Connection to proxy timed out + 代理连接超时 + + + + Proxy authentication failed + 代理认证失败 + + + + Proxy authentication failed: %1 + 代理认证失败: %1 + + + + SOCKS version 5 protocol error + SOCKS版本5协议错误 + + + + General SOCKSv5 server failure + 常规服务器失败 + + + + Connection not allowed by SOCKSv5 server + 连接不被SOCKSv5服务器允许 + + + + TTL expired + TTL已过期 + + + + SOCKSv5 command not supported + 不支持的SOCKSv5命令 + + + + Address type not supported + 不支持的地址类型 + + + + Unknown SOCKSv5 proxy error code 0x%1 + 未知SOCKSv5代理,错误代码 0x%1 + + + Socks5 timeout error connecting to socks server + 连接到套接字服务器的时候,Socks5超时错误 + + + + Network operation timed out + 网络操作超时 + + + + QSpinBox + + + More + 更多 + + + + Less + 更少 + + + + QSql + + + Delete + 删除 + + + + Delete this record? + 删除这条记录? + + + + + + Yes + + + + + + + No + + + + + Insert + 插入 + + + + Update + 更新 + + + + Save edits? + 保存编辑? + + + + Cancel + 取消 + + + + Confirm + 确认 + + + + Cancel your edits? + 取消您的编辑? + + + + QSslSocket + + + Unable to write data: %1 + 不能写入数据:%1 + + + + Error while reading: %1 + 读取时错误:%1 + + + + Error during SSL handshake: %1 + SSL握手错误:%1 + + + + Error creating SSL context (%1) + 创建SSL上下文错误(%1) + + + + Invalid or empty cipher list (%1) + 无效或者空白的密码列表(%1) + + + + Error creating SSL session, %1 + 创建SSL会话错误,%1 + + + + Error creating SSL session: %1 + 创建SSL会话错误:%1 + + + + Cannot provide a certificate with no key, %1 + 不能提供没有键的证书,%1 + + + + Error loading local certificate, %1 + 不能载入本地证书,%1 + + + + Error loading private key, %1 + 不能载入私有键,%1 + + + + Private key does not certificate public key, %1 + 私有键不能验证公有键,%1 + + + + QSystemSemaphore + + + + %1: out of resources + %1:资源耗尽了 + + + + + %1: permission denied + %1:权限被拒绝 + + + + %1: already exists + %1:已经存在 + + + + %1: does not exist + %1:不存在 + + + + + %1: unknown error %2 + %1:未知错误 %2 + + + + QTDSDriver + + + Unable to open connection + 不能打开连接 + + + + Unable to use database + 不能使用数据库 + + + + QTabBar + + + Scroll Left + 向左滚动 + + + + Scroll Right + 向右滚动 + + + + QTcpServer + + + Operation on socket is not supported + socket操作不被支持 + + + + QTextControl + + + &Undo + 撤消(&U) + + + + &Redo + 恢复(&R) + + + + Cu&t + 剪切(&T) + + + + &Copy + 复制(&C) + + + + Copy &Link Location + 复制链接位置(&L) + + + + &Paste + 粘贴(&P) + + + + Delete + 删除 + + + + Select All + 选择全部 + + + + QToolButton + + + + Press + 按下 + + + + + Open + 打开 + + + + QUdpSocket + + + This platform does not support IPv6 + 这个平台不支持IPv6 + + + + QUndoGroup + + + Undo + 撤销 + + + + Redo + 恢复 + + + + QUndoModel + + + <empty> + <空白> + + + + QUndoStack + + + Undo + 撤销 + + + + Redo + 恢复 + + + + QUnicodeControlCharacterMenu + + + LRM Left-to-right mark + LRM 从左到右标记 + + + + RLM Right-to-left mark + RLM 从右向左标记 + + + + ZWJ Zero width joiner + ZWJ 零宽度连接器 + + + + ZWNJ Zero width non-joiner + ZWNJ 零宽度非连接器 + + + + ZWSP Zero width space + ZWSP 零宽度空格 + + + + LRE Start of left-to-right embedding + LRE 开始从左到右嵌入 + + + + RLE Start of right-to-left embedding + RLE 开始从右向左嵌入 + + + + LRO Start of left-to-right override + LRO 开始从左向右覆盖 + + + + RLO Start of right-to-left override + RLO 开始从右向左覆盖 + + + + PDF Pop directional formatting + PDF 弹出方向格式 + + + + Insert Unicode control character + 插入Unicode控制字符 + + + + QWebFrame + + + Request cancelled + 请求被取消了 + + + + Request blocked + 请求被阻塞了 + + + + Cannot show URL + 无法显示 URL + + + + Frame load interruped by policy change + 因为策略调整打断了桢的加载 + + + + Cannot show mimetype + 无法显示 MIMETYPE + + + + File does not exist + 文件不存在 + + + + QWebPage + + + Bad HTTP request + 错误的 HTTP 请求 + + + + Submit + default label for Submit buttons in forms on web pages + 提交 + + + + Submit + Submit (input element) alt text for <input> elements with no alt, title, or value + 提交 + + + + Reset + default label for Reset buttons in forms on web pages + 重置 + + + + This is a searchable index. Enter search keywords: + text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index' + 这是一个可以搜索的索引。请输入要搜索的关键字: + + + + Choose File + title for file button used in HTML forms + 选择文件 + + + + No file selected + text to display in file button used in HTML forms when no file is selected + 没有文件被选择 + + + + Open in New Window + Open in New Window context menu item + 在新窗口中打开 + + + + Save Link... + Download Linked File context menu item + 保存链接... + + + + Copy Link + Copy Link context menu item + 复制链接 + + + + Open Image + Open Image in New Window context menu item + 打开图片 + + + + Save Image + Download Image context menu item + 保存图片 + + + + Copy Image + Copy Link context menu item + 复制图片 + + + + Open Frame + Open Frame in New Window context menu item + 打开框架 + + + + Copy + Copy context menu item + 复制 + + + + Go Back + Back context menu item + 后退 + + + + Go Forward + Forward context menu item + 前进 + + + + Stop + Stop context menu item + 停止 + + + + Reload + Reload context menu item + 重新载入 + + + + Cut + Cut context menu item + 剪切 + + + + Paste + Paste context menu item + 粘贴 + + + + No Guesses Found + No Guesses Found context menu item + 没有找到猜测 + + + + Ignore + Ignore Spelling context menu item + 忽略 + + + + Add To Dictionary + Learn Spelling context menu item + 添加到字典 + + + + Search The Web + Search The Web context menu item + 搜索网页 + + + + Look Up In Dictionary + Look Up in Dictionary context menu item + 在字典中查找 + + + + Open Link + Open Link context menu item + 打开链接 + + + + Ignore + Ignore Grammar context menu item + 忽略 + + + + Spelling + Spelling and Grammar context sub-menu item + 拼写 + + + + Show Spelling and Grammar + menu item title + 显示拼写和语法 + + + + Hide Spelling and Grammar + menu item title + 隐藏拼写和语法 + + + + Check Spelling + Check spelling context menu item + 检查拼写 + + + + Check Spelling While Typing + Check spelling while typing context menu item + 在输入时检查拼写 + + + + Check Grammar With Spelling + Check grammar with spelling context menu item + 检查语法和拼写 + + + + Fonts + Font context sub-menu item + 字体 + + + + Bold + Bold context menu item + 粗体 + + + + Italic + Italic context menu item + 意大利体 + + + + Underline + Underline context menu item + 下划线 + + + + Outline + Outline context menu item + 轮廓 + + + + Direction + Writing direction context sub-menu item + 方向 + + + + Text Direction + Text direction context sub-menu item + 文本方向 + + + + Default + Default writing direction context menu item + 默认 + + + + LTR + Left to Right context menu item + LTR + + + + RTL + Right to Left context menu item + RTL + + + + Inspect + Inspect Element context menu item + 检查 + + + + No recent searches + Label for only item in menu that appears when clicking on the search field image, when no searches have been performed + 没有最近的搜索 + + + + Recent searches + label for first item in the menu that appears when clicking on the search field image, used as embedded menu title + 最近的搜索 + + + + Clear recent searches + menu item in Recent Searches menu that empties menu's contents + 清除最近的搜索 + + + + Unknown + Unknown filesize FTP directory listing item + 未知的 + + + + %1 (%2x%3 pixels) + Title string for images + %1 (%2x%3 像素) + + + + Web Inspector - %2 + 网页检查员 - %2 + + + + Scroll here + 滚动到这里 + + + + Left edge + 左边缘 + + + + Top + 顶部 + + + + Right edge + 右边缘 + + + + Bottom + 底部 + + + + Page left + 左一页 + + + + Page up + 上一页 + + + + Page right + 右一页 + + + + Page down + 下一页 + + + + Scroll left + 向左滚动 + + + + Scroll up + 向上滚动 + + + + Scroll right + 向右滚动 + + + + Scroll down + 向下滚动 + + + + %n file(s) + number of chosen file + + %n 个文件 + + + + + JavaScript Alert - %1 + JavaScript警告 - %1 + + + + JavaScript Confirm - %1 + JavaScript确认 - %1 + + + + JavaScript Prompt - %1 + JavaScript提示 - %1 + + + + Move the cursor to the next character + 移动光标到下一个字符 + + + + Move the cursor to the previous character + 移动光标到上一个字符 + + + + Move the cursor to the next word + 移动光标到下一个单词 + + + + Move the cursor to the previous word + 移动光标到上一个单词 + + + + Move the cursor to the next line + 移动光标到下一行 + + + + Move the cursor to the previous line + 移动光标到上一行 + + + + Move the cursor to the start of the line + 移动光标到行首 + + + + Move the cursor to the end of the line + 移动光标到行尾 + + + + Move the cursor to the start of the block + 移动光标到块首 + + + + Move the cursor to the end of the block + 移动光标到块尾 + + + + Move the cursor to the start of the document + 移动光标到文件开头 + + + + Move the cursor to the end of the document + 移动光标到文件末尾 + + + + Select all + + + + + Select to the next character + 选中到下一个字符 + + + + Select to the previous character + 选中到上一个字符 + + + + Select to the next word + 选中到下一个单词 + + + + Select to the previous word + 选中到上一个单词 + + + + Select to the next line + 选中到下一行 + + + + Select to the previous line + 选中到上一行 + + + + Select to the start of the line + 选中到行首 + + + + Select to the end of the line + 选中到行尾 + + + + Select to the start of the block + 选中到块首 + + + + Select to the end of the block + 选中到块尾 + + + + Select to the start of the document + 选中到文件首 + + + + Select to the end of the document + 选中到文件尾 + + + + Delete to the start of the word + 删除到单词首 + + + + Delete to the end of the word + 删除到单词尾 + + + + Insert a new paragraph + + + + + Insert a new line + + + + + QWhatsThisAction + + + What's This? + 这是什么? + + + + QWidget + + + * + * + + + + QWizard + + + Go Back + 返回 + + + + Continue + 继续 + + + + Commit + 提交 + + + + Done + 完成 + + + Quit + 退出 + + + + Help + 帮助 + + + + < &Back + < 上一步(&B) + + + + &Finish + 完成(&F) + + + + Cancel + 取消 + + + + &Help + 帮助(&H) + + + + &Next + 下一步(&N) + + + + &Next > + 下一步(&N) > + + + + QWorkspace + + + &Restore + 恢复(&R) + + + + &Move + 移动(&M) + + + + &Size + 大小(&S) + + + + Mi&nimize + 最小化(&N) + + + + Ma&ximize + 最大化(&X) + + + + &Close + 关闭(&C) + + + + Stay on &Top + 总在最前(&T) + + + + + Sh&ade + 卷起(&A) + + + + + %1 - [%2] + %1 - [%2] + + + + Minimize + 最小化 + + + + Restore Down + 恢复 + + + + Close + 关闭 + + + + &Unshade + 展开(&U) + + + + QXml + + + no error occurred + 没有错误发生 + + + + error triggered by consumer + 由消费者出发的错误 + + + + unexpected end of file + 意外的文件终止 + + + + more than one document type definition + 多于一个的文档类型定义 + + + + error occurred while parsing element + 在解析元素的时候发生错误 + + + + tag mismatch + 标记不匹配 + + + + error occurred while parsing content + 在解析内容的时候发生错误 + + + + unexpected character + 意外的字符 + + + + invalid name for processing instruction + 无效的处理指令名称 + + + + version expected while reading the XML declaration + 在读取XML声明的时候,版本被期待 + + + + wrong value for standalone declaration + 错误的独立声明的值 + + + + encoding declaration or standalone declaration expected while reading the XML declaration + 在读取XML声明的时候,编码声明或者独立声明被期待 + + + + standalone declaration expected while reading the XML declaration + 在读取XML声明的时候,独立声明被期待 + + + + error occurred while parsing document type definition + 在解析文档类型定义的时候发生错误 + + + + letter is expected + 字符被期待 + + + + error occurred while parsing comment + 在解析注释的时候发生错误 + + + + error occurred while parsing reference + 在解析参考的时候发生错误 + + + + internal general entity reference not allowed in DTD + 在DTD中不允许使用内部解析的通用实体参考 + + + + external parsed general entity reference not allowed in attribute value + 在属性值中不允许使用外部解析的通用实体参考 + + + + external parsed general entity reference not allowed in DTD + 在DTD中不允许使用外部解析的通用实体参考 + + + + unparsed entity reference in wrong context + 没有解析的错误上下文中的实体参考 + + + + recursive entities + 嵌套实体 + + + + error in the text declaration of an external entity + 在一个外部实体的文本声明里有错误 + + + + QXmlStream + + + + Extra content at end of document. + 文档末尾有额外内容。 + + + + Invalid entity value. + 无效的实体值。 + + + + Invalid XML character. + 无效的XML字符。 + + + + Sequence ']]>' not allowed in content. + 内容中不允许有“]]>“序列。 + + + + Namespace prefix '%1' not declared + 命名空间的”%1“前缀没有被声明 + + + + Attribute redefined. + 属性重复定义。 + + + + Unexpected character '%1' in public id literal. + 在公有标识文本中有意外的字符”%1“。 + + + + Invalid XML version string. + 无效的XML版本字符串。 + + + + Unsupported XML version. + 不被支持的XML版本。 + + + + %1 is an invalid encoding name. + %1是无效的编码名称。 + + + + Encoding %1 is unsupported + 编码%1不被支持。 + + + + Standalone accepts only yes or no. + 独立运行只允许是或者否。 + + + + Invalid attribute in XML declaration. + 在XML声明中无效的属性。 + + + + Premature end of document. + 文档过早的结束。 + + + + Invalid document. + 无效的文档。 + + + + Expected + 期待的 + + + + , but got ' + ,但是得到的是“ + + + + Unexpected ' + 意外的“ + + + + Expected character data. + 期待的字符数据。 + + + + Recursive entity detected. + 检测到嵌套实体。 + + + + Start tag expected. + 开始期待的标记。 + + + + XML declaration not at start of document. + XML声明没有在文档的开始位置。 + + + + NDATA in parameter entity declaration. + 在参数实体声明中有NDATA。 + + + + %1 is an invalid processing instruction name. + %1 是无效的处理指令名称。 + + + + Invalid processing instruction name. + 无效的处理指令名称。 + + + + + + + Illegal namespace declaration. + 非法的命名空间声明。 + + + + Invalid XML name. + 无效的XML名称。 + + + + Opening and ending tag mismatch. + 开始标记和结束标记不匹配。 + + + + Reference to unparsed entity '%1'. + 未解析实体“%1“的引用。 + + + + + + Entity '%1' not declared. + 实体”%1“没有被声明。 + + + + Reference to external entity '%1' in attribute value. + 在属性值中的外部实体“%1”的引用。 + + + + Invalid character reference. + 无效的字符引用。 + + + + + Encountered incorrectly encoded content. + 遇到不正确的编码内容。 + + + + The standalone pseudo attribute must appear after the encoding. + 独立运行伪属性必须出现在编码之后。 + + + + %1 is an invalid PUBLIC identifier. + %1是一个无效的公有(PUBLIC)标识符。 + + + + QtXmlPatterns + + + An %1-attribute with value %2 has already been declared. + 带有值 %2 的 %1 属性已经声明过了。 + + + + An %1-attribute must have a valid %2 as value, which %3 isn't. + 一个 %1 属性必须带有一个有效的 %2 作为值,但 %3 却不是。 + + + + Network timeout. + 网络超时。 + + + + Element %1 can't be serialized because it appears outside the document element. + 元素 %1 不能被串行化,因为它出现在文档元素之外。 + + + Attribute element %1 can't be serialized because it appears at the top level. + 属性元素 %1 不能被串行化,因为它出现在最顶层。 + + + + Year %1 is invalid because it begins with %2. + %1 年是无效的,因为应该从 %2 开始。 + + + + Day %1 is outside the range %2..%3. + %1 日是在 %2...%3 范围之外的。 + + + + Month %1 is outside the range %2..%3. + %1 月是在 %2...%3 范围之外的。 + + + + Overflow: Can't represent date %1. + 溢出:无法呈现数据 %1。 + + + + Day %1 is invalid for month %2. + %1 日对于 %2 月是无效的。 + + + + Time 24:%1:%2.%3 is invalid. Hour is 24, but minutes, seconds, and milliseconds are not all 0; + 时间 24:%1:%2.%3 是无效的。小时是 24,但是分钟、秒和毫秒不全为 0; + + + + Time %1:%2:%3.%4 is invalid. + 时间 %1:%2:%3.%4 是无效的。 + + + + Overflow: Date can't be represented. + 溢出:数据无法被呈现。 + + + + + At least one component must be present. + 至少有一个组件被呈现。 + + + + At least one time component must appear after the %1-delimiter. + 至少一个时间组件必须出现在这个 %1 界限之后。 + + + + No operand in an integer division, %1, can be %2. + 在整数除法中没有操作数,%1,可以是 %2。 + + + + The first operand in an integer division, %1, cannot be infinity (%2). + 除法中的第一个操作数,%1,不能是无穷(%2)。 + + + + The second operand in a division, %1, cannot be zero (%2). + 除法中的第二个操作数,%1,不能是零(%2)。 + + + + %1 is not a valid value of type %2. + %1 不是类型为 %2 的有效值。 + + + + When casting to %1 from %2, the source value cannot be %3. + 当从 %2 抛出到 %1 时,源值不能是 %3。 + + + + Integer division (%1) by zero (%2) is undefined. + 整数除法(%1)除零(%2)是未定义的。 + + + + Division (%1) by zero (%2) is undefined. + 除法(%1)除零(%2)是未定义的。 + + + + Modulus division (%1) by zero (%2) is undefined. + 求模除法(%1)除零(%2)是未定义的。 + + + + + Dividing a value of type %1 by %2 (not-a-number) is not allowed. + 一个类型为 %1 的值除以 %2(不是一个数值)是不允许的。 + + + + Dividing a value of type %1 by %2 or %3 (plus or minus zero) is not allowed. + 一个类型为 %1 的值除以 %2 或者 %3(正负零)是不允许的。 + + + + Multiplication of a value of type %1 by %2 or %3 (plus or minus infinity) is not allowed. + 一个类型为 %1 的值乘以 %2 或者 %3(正负无穷)是不允许的。 + + + + A value of type %1 cannot have an Effective Boolean Value. + 一个类型为 %1 的值不能是一个有效的布尔值(Effective Boolean Value)。 + + + + Effective Boolean Value cannot be calculated for a sequence containing two or more atomic values. + 有效的布尔值(Effective Boolean Value)不能被用于计算一个包含两个或者更多原子值的序列。 + + + + Value %1 of type %2 exceeds maximum (%3). + 类型为 %2 的值 %1 超过了最大值(%3)。 + + + + Value %1 of type %2 is below minimum (%3). + 类型为 %2 的值 %1 超过了最小值(%3)。 + + + + A value of type %1 must contain an even number of digits. The value %2 does not. + 类型为 %1 的值必须包含偶数个数字。值 %2 不是这样的。 + + + + %1 is not valid as a value of type %2. + %1 不是类型为 %2 的有效值。 + + + + Operator %1 cannot be used on type %2. + 操作符 %1 不能被用于类型 %2。 + + + + Operator %1 cannot be used on atomic values of type %2 and %3. + 操作符 %1 不能被用于类型为 %2 和 %3 的原子值。 + + + + The namespace URI in the name for a computed attribute cannot be %1. + 一个被计算的属性的名称中的命名空间 URI 不能是 %1。 + + + + The name for a computed attribute cannot have the namespace URI %1 with the local name %2. + 一个被计算的属性的名称不能使用带有本地名称 %2 的命名空间 URI %1。 + + + + Type error in cast, expected %1, received %2. + 抛出类型错误,期望的是 %1,收到的是 %2。 + + + + When casting to %1 or types derived from it, the source value must be of the same type, or it must be a string literal. Type %2 is not allowed. + 当抛出到 %1 或者它的派生类时,源类型必须是同一类型,或者它必须是一个字符串类型。类型 %2 是不被允许的。 + + + + No casting is possible with %1 as the target type. + 无法以 %1 为目标类型进行抛出。 + + + + It is not possible to cast from %1 to %2. + 无法从 %1 抛出到 %2。 + + + + Casting to %1 is not possible because it is an abstract type, and can therefore never be instantiated. + 无法抛出到 %1,因为它是一个抽象类型,并且因此无法被实例化。 + + + + It's not possible to cast the value %1 of type %2 to %3 + 无法从类型为 %2 的值 %1 抛出到 %3 + + + + Failure when casting from %1 to %2: %3 + 从 %2 抛出到 %1 失败:%3 + + + + A comment cannot contain %1 + 注释不能包含 %1 + + + + A comment cannot end with a %1. + 注释不能以 %1 结尾。 + + + + No comparisons can be done involving the type %1. + 对于类型 %1 不能进行比较。 + + + + Operator %1 is not available between atomic values of type %2 and %3. + 在类型 %2 和 %3 的原子值之间,操作符 %1 是不可用的。 + + + + An attribute node cannot be a child of a document node. Therefore, the attribute %1 is out of place. + 一个属性节点不能是一个文档节点的子节点。因此,这个属性 %1 所在位置是不合适的。 + + + + A library module cannot be evaluated directly. It must be imported from a main module. + 一个库模块不能被直接评估。它必须从一个主模块中导入。 + + + + No template by name %1 exists. + 没有名为 %1 的模板存在。 + + + + A value of type %1 cannot be a predicate. A predicate must have either a numeric type or an Effective Boolean Value type. + 类型为 %1 的值不能被判断。一个判断必须是数值类型或者一个有效的布尔值(Effective Boolean Value)类型。 + + + + A positional predicate must evaluate to a single numeric value. + 一个定位判断必须评估一个单一数值。 + + + + The target name in a processing instruction cannot be %1 in any combination of upper and lower case. Therefore, is %2 invalid. + 一个处理指令中的目标名称不能是任何大小写混合的 %1。因此,%2 是无效的。 + + + + %1 is not a valid target name in a processing instruction. It must be a %2 value, e.g. %3. + %1 不是处理指令的有效目标名称。它必须是值 %2,例如 %3。 + + + + The last step in a path must contain either nodes or atomic values. It cannot be a mixture between the two. + 一个路径中的最后一步必须包含节点或者原子值。它不能是两者的一个组合。 + + + + The data of a processing instruction cannot contain the string %1 + 处理指令的数据不能包含字符串 %1 + + + + No namespace binding exists for the prefix %1 + 对于前缀 %1,没有存在绑定的命名空间。 + + + + No namespace binding exists for the prefix %1 in %2 + 对于 %2 中的前缀 %1,没有存在绑定的命名空间。 + + + + + %1 is an invalid %2 + %1 是一个无效的 %2。 + + + + %1 takes at most %n argument(s). %2 is therefore invalid. + + %1 最多可以有 %n 个参数。因此 %2 是无效的。 + + + + + %1 requires at least %n argument(s). %2 is therefore invalid. + + %1 需要至少 %n 个参数。因此 %2 是无效的。 + + + + + The first argument to %1 cannot be of type %2. It must be a numeric type, xs:yearMonthDuration or xs:dayTimeDuration. + %1 的第一个参数不能是类型 %2 的。它必须是数字类型的,xs:yearMonthDuration 或者 xs:dayTimeDuration。 + + + + The first argument to %1 cannot be of type %2. It must be of type %3, %4, or %5. + %1 的第一个参数不能是类型 %2 的。它必须是类型 %3、%4 或者 %5 的。 + + + + The second argument to %1 cannot be of type %2. It must be of type %3, %4, or %5. + %1 的第二个参数不能是类型 %2 的。它必须是类型 %3、%4 或者 %5 的。 + + + + %1 is not a valid XML 1.0 character. + %1 不是一个有效的 XML 1.0 字符。 + + + + The first argument to %1 cannot be of type %2. + %1 的第一个参数不能是类型 %2 的。 + + + + If both values have zone offsets, they must have the same zone offset. %1 and %2 are not the same. + 如果两个值都有区偏移(zone offset),它们必须拥有相同的区偏移。%1 和 %2 的区偏移是不同的。 + + + + %1 was called. + %1 被调用了。 + + + + %1 must be followed by %2 or %3, not at the end of the replacement string. + %1 必须被 %2 或者 %3 跟随,不能在替换字符串的末尾。 + + + + In the replacement string, %1 must be followed by at least one digit when not escaped. + 在这个替换字符串中,%1 在没有被转义的时候必须被至少一个数字跟随。 + + + + In the replacement string, %1 can only be used to escape itself or %2, not %3 + 在这个替换字符串中,%1 只能被用于转义它本身或者 %2,而不是 %3 + + + + %1 matches newline characters + %1 匹配了换行符 + + + + %1 and %2 match the start and end of a line. + %1 和 %2 匹配了一行的头和尾。 + + + + Matches are case insensitive + 匹配是大小写不敏感的 + + + + Whitespace characters are removed, except when they appear in character classes + 空白字符被移除了,除非当它们出现在字符类中 + + + + %1 is an invalid regular expression pattern: %2 + %1 是正则表达式中的一个无效模式:%2 + + + + %1 is an invalid flag for regular expressions. Valid flags are: + %1 是正则表达式中的一个无效标记。有效标记为: + + + + If the first argument is the empty sequence or a zero-length string (no namespace), a prefix cannot be specified. Prefix %1 was specified. + 如果第一个参数是空序列或者零长度字符串(无命名空间),那么就不能指定前缀。前缀 %1 被指定了。 + + + + It will not be possible to retrieve %1. + 将不能获取 %1。 + + + + The root node of the second argument to function %1 must be a document node. %2 is not a document node. + 函数 %1 的第二个参数的根节点必须是一个文档节点。%2 不是一个文档节点。 + + + + The default collection is undefined + 默认收集(collection)是未定义的 + + + + %1 cannot be retrieved + 无法获取 %1 + + + + The normalization form %1 is unsupported. The supported forms are %2, %3, %4, and %5, and none, i.e. the empty string (no normalization). + 不支持正规化(normalization)表单 %1。被支持的表单是 %2、%3、%4 和 %5,以及无,例如空字符串(无正规化)。 + + + + A zone offset must be in the range %1..%2 inclusive. %3 is out of range. + 区偏移(zone offset)必须在 %1...%2 范围之内。%3 是在范围之外的。 + + + + %1 is not a whole number of minutes. + %1 不是分钟的整数。 + + + + Required cardinality is %1; got cardinality %2. + 所需要的表间关系是 %1;得到的表间关系却是 %2。 + + + + The item %1 did not match the required type %2. + 项 %1 和所需的类型 %2 不匹配。 + + + + + %1 is an unknown schema type. + %1 是一个未知的方案类型。 + + + + Only one %1 declaration can occur in the query prolog. + 只有一个 %1 的声明可以出现在查询序言中。 + + + + The initialization of variable %1 depends on itself + 变量 %1 的初始化依赖于它本身 + + + + No variable by name %1 exists + 没有名称为 %1 的变量存在。 + + + + The variable %1 is unused + 变量 %1 没有被使用 + + + + Version %1 is not supported. The supported XQuery version is 1.0. + 不支持版本 %1。被支持的 XQuery 版本是 1.0。 + + + + The encoding %1 is invalid. It must contain Latin characters only, must not contain whitespace, and must match the regular expression %2. + 编码方式 %1 是无效的。它必须只包含拉丁字符,必须不包含空白符号,并且必须和正则表达式 %2 匹配。 + + + + No function with signature %1 is available + 没有签名为 %1 的可用函数。 + + + + + A default namespace declaration must occur before function, variable, and option declarations. + 默认命名空间声明必须出现在函数、变量和选项声明之前。 + + + + Namespace declarations must occur before function, variable, and option declarations. + 命名空间声明必须出现在函数、变量和选项声明之前。 + + + + Module imports must occur before function, variable, and option declarations. + 模块导入不能出现在函数、变量和选项声明之前。 + + + + It is not possible to redeclare prefix %1. + 不能重复声明前缀 %1。 + + + Only the prefix %1 can be declared to bind the namespace %2. By default, it is already bound to the prefix %1. + 至于前缀 %1 可以被声明为和命名空间 %2 绑定。默认情况下,它已经被绑定到前缀 %1。 + + + + Prefix %1 is already declared in the prolog. + 前缀 %1 在序言中已经声明过了。 + + + + The name of an option must have a prefix. There is no default namespace for options. + 一个选项的名称必须带有前缀。对于选项没有默认命名空间。 + + + + The Schema Import feature is not supported, and therefore %1 declarations cannot occur. + 不支持方案导入(Schema Import)特性,并且因此 %1 声明不能出现。 + + + + The target namespace of a %1 cannot be empty. + %1 的目标命名空间不能为空。 + + + + The module import feature is not supported + 不支持模块导入特性 + + + A variable by name %1 has already been declared in the prolog. + 名称为 %1 的变量已经在序言中声明过了。 + + + + No value is available for the external variable by name %1. + 名称为 %1 的外部变量并没有可用的值。 + + + The namespace for a user defined function cannot be empty(try the predefined prefix %1 which exists for cases like this) + 用户定义的函数的命名空间不能为空(请试试预定义的前缀 %1,它就是用于这种情况的)。 + + + + A construct was encountered which only is allowed in XQuery. + 遇到了一个只允许在XQuery中出现的构造。 + + + + A template by name %1 has already been declared. + 模板%1已被声明 + + + + The keyword %1 cannot occur with any other mode name. + 任何其他模式名称不能出现关键字%1。 + + + + The value of attribute %1 must of type %2, which %3 isn't. + 属性%1的值必须是类型%2,但%3不是。 + + + + The prefix %1 can not be bound. By default, it is already bound to the namespace %2. + 前缀%1不能被绑定。默认的,它已被绑定到名字空间%2。 + + + + A variable by name %1 has already been declared. + 变量%1已被声明。 + + + + A stylesheet function must have a prefixed name. + 样式表函数必须有一个前缀名。 + + + + The namespace for a user defined function cannot be empty (try the predefined prefix %1 which exists for cases like this) + 用户定义函数的名字空间不能为空(试用为这种情况而存在的预定义前缀%1) + + + + The namespace %1 is reserved; therefore user defined functions may not use it. Try the predefined prefix %2, which exists for these cases. + 命名空间 %1 是保留的;因此用户定义的函数不能使用它。请试试预定义的前缀 %2,它就是用于这种情况的。 + + + + The namespace of a user defined function in a library module must be equivalent to the module namespace. In other words, it should be %1 instead of %2 + 用户在一个库模块中定义的函数的命名空间必须和这个模块的命名空间一致。也就是说,它应该是 %1,而不是 %2 + + + + A function already exists with the signature %1. + 一个带有签名 %1 的函数已经存在。 + + + + No external functions are supported. All supported functions can be used directly, without first declaring them as external + 不支持外部函数。所有支持的函数必须可以被直接使用,不能把它们声明为外部的 + + + + An argument by name %1 has already been declared. Every argument name must be unique. + 名称为 %1 的参数已经被声明了。每个参数名称必须唯一。 + + + + When function %1 is used for matching inside a pattern, the argument must be a variable reference or a string literal. + 当函数%1被用于样式匹配时,参数必须是变量参考或者字符串。 + + + + In an XSL-T pattern, the first argument to function %1 must be a string literal, when used for matching. + 在XSL-T样式中,函数%1的第一个参数必须是字符串,以便用于匹配。 + + + + In an XSL-T pattern, the first argument to function %1 must be a literal or a variable reference, when used for matching. + 在XSL-T样式中,函数%1的第一个参数必须是文字或者变量参考,以便用于匹配。 + + + + In an XSL-T pattern, function %1 cannot have a third argument. + 在XSL-T样式中,函数%1不能有第三个参数。 + + + + In an XSL-T pattern, only function %1 and %2, not %3, can be used for matching. + 在XSL-T样式中,只用函数%1和%2可以用于匹配,%3不可以。 + + + + In an XSL-T pattern, axis %1 cannot be used, only axis %2 or %3 can. + 在XSL-T仰视中,不能使用%1轴,只能使用%2轴或者%3轴。 + + + + %1 is an invalid template mode name. + %1不是一个合法的模板模式名称。 + + + + The name of a variable bound in a for-expression must be different from the positional variable. Hence, the two variables named %1 collide. + 一个在 for 表达式中绑定的变量的名称必须和这个定位变量不同。因此,这两个名称为 %1 的变量冲突。 + + + + The Schema Validation Feature is not supported. Hence, %1-expressions may not be used. + 不支持方案验证特性(Schema Validation Feature)。因此,也许不能使用 %1 表达式。 + + + + None of the pragma expressions are supported. Therefore, a fallback expression must be present + 不支持任何编译指示表达式(pragma expression)。因此,必须呈现一个回调表达式(fallback expression)。 + + + + Each name of a template parameter must be unique; %1 is duplicated. + 每一个模板参数的名称都必须是唯一的;%2是重复的。 + + + + The %1-axis is unsupported in XQuery + 这个 %1 轴在 XQuery 中是不被支持的。 + + + + %1 is not a valid name for a processing-instruction. + %1不是一个处理指令的合法名称。 + + + + %1 is not a valid numeric literal. + %1 不是一个有效的数字语义。 + + + + No function by name %1 is available. + 没有名称为 %1 的可用函数。 + + + + The namespace URI cannot be the empty string when binding to a prefix, %1. + 当这个命名空间 URI 被绑定到一个前缀 %1 时,它不能是空字符串。 + + + + %1 is an invalid namespace URI. + %1 是一个无效的命名空间 URI。 + + + + It is not possible to bind to the prefix %1 + 无法绑定到这个前缀 %1。 + + + + Namespace %1 can only be bound to %2 (and it is, in either case, pre-declared). + 命名空间 %1 只能和 %2 绑定(并且如果是这种情况,需要提前声明)。 + + + + Prefix %1 can only be bound to %2 (and it is, in either case, pre-declared). + 前缀 %1 只能和 %2 绑定(并且如果是这种情况,需要提前声明)。 + + + + Two namespace declaration attributes have the same name: %1. + 两个命名空间声明属性使用了相同的名称:%1。 + + + + The namespace URI must be a constant and cannot use enclosed expressions. + 命名空间 URI 必须是一个常量并且不能使用封闭的表达式。 + + + + An attribute by name %1 has already appeared on this element. + 一个名称为 %1 的属性已经出现在这个元素中了。 + + + + A direct element constructor is not well-formed. %1 is ended with %2. + 一个直接元素构造器没有很好地形成。%1 后面跟着 %2。 + + + + The name %1 does not refer to any schema type. + 名称 %1 没有指向任何方案类型。 + + + + %1 is an complex type. Casting to complex types is not possible. However, casting to atomic types such as %2 works. + %1 是一个复杂类型。无法抛出到复杂类型。因此,抛出到例如 %2 这样的原子类型是可以的。 + + + + %1 is not an atomic type. Casting is only possible to atomic types. + %1 不是原子类型。只能抛出到原子类型。 + + + %1 is not a valid name for a processing-instruction. Therefore this name test will never match. + %1 不是处理指令的有效名称。因此这个名称测试永远不会匹配。 + + + + + %1 is not in the in-scope attribute declarations. Note that the schema import feature is not supported. + %1 不是范围内属性声明。注意方案导入特性是不被支持的。 + + + + The name of an extension expression must be in a namespace. + 一个扩展表达式的名称必须在一个命名空间中。 + + + + empty + 空白 + + + + zero or one + 零或者一 + + + + exactly one + 确切地一 + + + + one or more + 一或者更多 + + + + zero or more + 零或者更多 + + + + Required type is %1, but %2 was found. + 需要的类型是 %1,但是找到的是 %2。 + + + + Promoting %1 to %2 may cause loss of precision. + 把 %1 升级为 %2 会导致精度的损失。 + + + + The focus is undefined. + 焦点未定义。 + + + + It's not possible to add attributes after any other kind of node. + 不能在任何其它类型节点后添加属性。 + + + + An attribute by name %1 has already been created. + 一个名称为 %1 的属性已经被创建。 + + + + Only the Unicode Codepoint Collation is supported(%1). %2 is unsupported. + 只支持 Unicode 代码点校验(Unicode Codepoint Collation)(%1)。%2 是不被支持的。 + + + + Attribute %1 can't be serialized because it appears at the top level. + 属性 %1 不能被串行化,因为它出现在最顶层。 + + + + %1 is an unsupported encoding. + %1 是不被支持的编码。 + + + + %1 contains octets which are disallowed in the requested encoding %2. + %1包含了在请求编码%2中不允许的八进位值。 + + + + The codepoint %1, occurring in %2 using encoding %3, is an invalid XML character. + 在使用编码%3的%2中出现的代码点%1不是一个有效的XML字符。 + + + + Ambiguous rule match. + 含糊规则匹配。 + + + In a namespace constructor, the value for a namespace value cannot be an empty string. + 在一个命名空间构造中,命名空间的值不能为空字符串。 + + + + In a namespace constructor, the value for a namespace cannot be an empty string. + + + + + The prefix must be a valid %1, which %2 is not. + 前缀必须是有效的%1,而%2不是。 + + + + The prefix %1 cannot be bound. + 前缀%1不能被绑定。 + + + + Only the prefix %1 can be bound to %2 and vice versa. + 只有前缀%1可以绑定到%2,反之也一样 + + + + Circularity detected + 检测到环 + + + + The parameter %1 is required, but no corresponding %2 is supplied. + 需要参数%1,但是没有提供对应的%2。 + + + + The parameter %1 is passed, but no corresponding %2 exists. + 参数%1已传递,但没有相应的%2存在。 + + + + The URI cannot have a fragment + URI不能有片段 + + + + Element %1 is not allowed at this location. + 元素%1不能在这个位置。 + + + + Text nodes are not allowed at this location. + 文本节点不能在这个位置。 + + + + Parse error: %1 + 解析错误:%1 + + + + The value of the XSL-T version attribute must be a value of type %1, which %2 isn't. + XSL-T版本属性的值必须是%1类型的值,而%2不是。 + + + + Running an XSL-T 1.0 stylesheet with a 2.0 processor. + 在XSL-T 2.0处理器中运行一个1.0的样式表。 + + + + Unknown XSL-T attribute %1. + 未知的XSL-T属性%1。 + + + + Attribute %1 and %2 are mutually exclusive. + 属性%1和%2彼此互斥。 + + + + In a simplified stylesheet module, attribute %1 must be present. + 在一个简化样式表模块中,属性%1必须存在。 + + + + If element %1 has no attribute %2, it cannot have attribute %3 or %4. + 如果元素%1没有属性%2,那么它也不能有属性%3或者%4。 + + + + Element %1 must have at least one of the attributes %2 or %3. + 元素%1必须至少有属性%2或者%3其中一个。 + + + + At least one mode must be specified in the %1-attribute on element %2. + 在元素%2的%1属性中至少要指定一个模式。 + + + + Attribute %1 cannot appear on the element %2. Only the standard attributes can appear. + 属性%1不能出现在元素%2上。只有标准属性可以出现。 + + + + Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes. + 属性%1不能出现在元素%2上。只有%3和标准属性是允许的。 + + + + Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes. + 属性%1不能出现在元素%2上。只有%3、%4和标准属性是允许的。 + + + + Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes. + 属性%1不能出现在元素%2上。只有%3和标准属性是允许的。 + + + + XSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is. + XSL-T元素中的XSL-T属性必须放在空(null)命名空间中,而不是在XSL-T命名空间中,%1却是这个样子。 + + + + The attribute %1 must appear on element %2. + 属性%1必须出现在元素%2中。 + + + + The element with local name %1 does not exist in XSL-T. + 有本地名称%1的元素在XSL-T中不存在。 + + + + Element %1 must come last. + 元素%1必须最后出现。 + + + + At least one %1-element must occur before %2. + 至少一个元素%1要出现在%2之前。 + + + + Only one %1-element can appear. + 只能出现一个元素%1。 + + + + At least one %1-element must occur inside %2. + 至少一个元素%1要出现在%2之内。 + + + + When attribute %1 is present on %2, a sequence constructor cannot be used. + 当属性%1出现在%2中时,不能使用顺序构造。 + + + + Element %1 must have either a %2-attribute or a sequence constructor. + 元素%1必须有在一个%2属性或者顺序构造。 + + + + When a parameter is required, a default value cannot be supplied through a %1-attribute or a sequence constructor. + 当需要参数时,不能通过属性%1或者顺序构造提供默认值。 + + + + Element %1 cannot have children. + 元素%1不能有子元素。 + + + + Element %1 cannot have a sequence constructor. + 元素%1不能有顺序构造。 + + + + + The attribute %1 cannot appear on %2, when it is a child of %3. + 属性%1不能出现在%2中,因为它是%3的子元素。 + + + + A parameter in a function cannot be declared to be a tunnel. + 函数内的参数不能被声明为通道(tunnel)。 + + + + This processor is not Schema-aware and therefore %1 cannot be used. + 这个处理器不能感知Schema,因此%1不能被使用。 + + + + Top level stylesheet elements must be in a non-null namespace, which %1 isn't. + 顶级样式表元素必须是在非空命名空间中的,而%1不是。 + + + + The value for attribute %1 on element %2 must either be %3 or %4, not %5. + 元素%2中属性%1的值必须是%3或者%4,而不是%5。 + + + + Attribute %1 cannot have the value %2. + 属性%1的值不能是%2。 + + + + The attribute %1 can only appear on the first %2 element. + 属性%1只能出现在前%2个元素中。 + + + + At least one %1 element must appear as child of %2. + %2必须至少又一个子元素%1。 + + + + VolumeSlider + + + Muted + 已静音 + + + + + Volume: %1% + 音量:%1% + + + + WebCore::PlatformScrollbar + + Scroll here + 滚动到这里 + + + Left edge + 左边缘 + + + Top + 顶部 + + + Right edge + 右边缘 + + + Bottom + 底部 + + + Page left + 左一页 + + + Page up + 上一页 + + + Page right + 右一页 + + + Page down + 下一页 + + + Scroll left + 向左滚动 + + + Scroll up + 向上滚动 + + + Scroll right + 向右滚动 + + + Scroll down + 向下滚动 + + + diff --git a/release/ts/qt_windows_zh_TW.qm b/release/ts/qt_windows_zh_TW.qm new file mode 100644 index 0000000..a9a25b2 Binary files /dev/null and b/release/ts/qt_windows_zh_TW.qm differ diff --git a/release/ts/qt_windows_zh_TW.ts b/release/ts/qt_windows_zh_TW.ts new file mode 100644 index 0000000..de0f888 --- /dev/null +++ b/release/ts/qt_windows_zh_TW.ts @@ -0,0 +1,8129 @@ + + + + + MAC_APPLICATION_MENU + + + Services + 服務 + + + + Hide %1 + 隱藏%1 + + + + Hide Others + 隱藏其他 + + + + Show All + 顯示全部 + + + + Preferences... + 偏好設定⋯ + + + + Quit %1 + 結束 %1 + + + + About %1 + 關於 %1 + + + + AudioOutput + + + <html>The audio playback device <b>%1</b> does not work.<br/>Falling back to <b>%2</b>.</html> + <html>音效播放裝置 <b>%1</b> 未能運作。<br/>改用預設裝置 <b>%2</b>。</html> + + + + <html>Switching to the audio playback device <b>%1</b><br/>which just became available and has higher preference.</html> + <html>音效播放裝置 <b>%1</b> 已可使用,因為有較高優先權,因此將切換到該裝置。</html> + + + + Revert back to device '%1' + 回復到裝置 %1 + + + + CloseButton + + + Close Tab + 關閉分頁 + + + + PPDOptionsModel + + Name + 名稱 + + + Value + + + + + Phonon:: + + + Notifications + 通知 + + + + Music + 音樂 + + + + Video + 影像 + + + + Communication + 通訊 + + + + Games + 遊戲 + + + + Accessibility + 輔助裝置 + + + + Phonon::Gstreamer::Backend + + + Warning: You do not seem to have the package gstreamer0.10-plugins-good installed. + Some video features have been disabled. + 警告:您可能沒有安裝 gstreamer0.10-plugins-good。 + 有些影像的功能將被關閉。 + + + + Warning: You do not seem to have the base GStreamer plugins installed. + All audio and video support has been disabled + 警告:您可能沒有安裝 GStreamer 外掛程式。 所有音效與影像支援將被關閉。 + + + + Phonon::Gstreamer::MediaObject + + + Cannot start playback. + +Check your Gstreamer installation and make sure you +have libgstreamer-plugins-base installed. + 無法開始播放。 + +請檢查您的 Gstreamer 安裝,並確定您有安裝 +libgstreamer-plugins-base 套件。 + + + + A required codec is missing. You need to install the following codec(s) to play this content: %0 + 找不到需要的編解碼器。您需要安裝以下的套件來播放此內容:%0 + + + + + + + + + + + Could not open media source. + 無法開啟媒體來源。 + + + + Invalid source type. + 不合法的來源型態。 + + + + Could not locate media source. + 無法定位媒體來源。 + + + + Could not open audio device. The device is already in use. + 無法開啟音效裝置。裝置已在使用中。 + + + + Could not decode media source. + 無法解碼媒體來源。 + + + + Phonon::VolumeSlider + + + + Volume: %1% + 音量:%1% + + + + + + Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1% + 使用此滑動器來調整音量。最左邊的位置為 0%,最右邊的為 %1%。 + + + + Q3Accel + + + %1, %2 not defined + %1,%2 未定義 + + + + Ambiguous %1 not handled + 不明確的 %1 尚未處理 + + + + Q3DataTable + + + True + + + + + False + + + + + Insert + 插入 + + + + Update + 更新 + + + + Delete + 刪除 + + + + Q3FileDialog + + + Copy or Move a File + 複製或移動檔案 + + + + Read: %1 + 讀取:%1 + + + + + Write: %1 + 寫入:%1 + + + + + Cancel + 取消 + + + + + + + All Files (*) + 所有檔案 (*) + + + + Name + 名稱 + + + + Size + 大小 + + + + Type + 型態 + + + + Date + 日期 + + + + Attributes + 屬性 + + + + + &OK + 確定(&O) + + + + Look &in: + 尋找於(&I): + + + + + + File &name: + 檔名(&N): + + + + File &type: + 檔案型態(&T): + + + + Back + 返回 + + + + One directory up + 往上一層目錄 + + + + Create New Folder + 建立新資料夾 + + + + List View + 列表檢視 + + + + Detail View + 詳細檢視 + + + + Preview File Info + 預覽檔案資訊 + + + + Preview File Contents + 預覽檔案內容 + + + + Read-write + 可讀寫 + + + + Read-only + 唯讀 + + + + Write-only + 唯寫 + + + + Inaccessible + 無法存取 + + + + Symlink to File + 到檔案的符號連結 + + + + Symlink to Directory + 到目錄的符號連結 + + + + Symlink to Special + 到特殊節點的符號連結 + + + + File + 檔案 + + + + Dir + 目錄 + + + + Special + 特殊節點 + + + + + + Open + 開啟 + + + + + Save As + 另存新檔 + + + + + + &Open + 開啟(&O) + + + + + &Save + 儲存(&S) + + + + &Rename + 重新命名(&R) + + + + &Delete + 刪除(&D) + + + + R&eload + 重新載入(&E) + + + + Sort by &Name + 依名稱排序(&N) + + + + Sort by &Size + 依大小排序(&S) + + + + Sort by &Date + 依日期排序(&D) + + + + &Unsorted + 未排序(&U) + + + + Sort + 排序 + + + + Show &hidden files + 顯示隱藏檔(&H) + + + + the file + 此檔案 + + + + the directory + 此目錄 + + + + the symlink + 此符號連結 + + + + Delete %1 + 刪除 %1 + + + + <qt>Are you sure you wish to delete %1 "%2"?</qt> + <qt>您確定要刪除 %1 "%2" 嗎?</qt> + + + + &Yes + 是(&Y) + + + + &No + 否(&N) + + + + New Folder 1 + 新資料夾 1 + + + + New Folder + 新資料夾 + + + + New Folder %1 + 新資料夾 %1 + + + + Find Directory + 尋找目錄 + + + + + Directories + 目錄 + + + + Directory: + 目錄: + + + + + Error + 錯誤 + + + + %1 +File not found. +Check path and filename. + %1 +找不到檔案。 +請檢查路徑與檔名。 + + + + All Files (*.*) + 所有檔案 (*.*) + + + + Open + 開啟 + + + + Select a Directory + 請選擇一個目錄 + + + + Q3LocalFs + + + + Could not read directory +%1 + 無法讀取目錄 +%1 + + + + Could not create directory +%1 + 無法建立目錄 +%1 + + + + Could not remove file or directory +%1 + 無法移除目錄 +%1 + + + + Could not rename +%1 +to +%2 + 無法將 +%1 +重新命名為 +%2 + + + + Could not open +%1 + 無法開啟 +%1 + + + + Could not write +%1 + 無法寫入 +%1 + + + + Q3MainWindow + + + Line up + 排列 + + + + Customize... + 自訂... + + + + Q3NetworkProtocol + + + Operation stopped by the user + 使用者已中止操作 + + + + Q3ProgressDialog + + + + Cancel + 取消 + + + + Q3TabDialog + + + + OK + 確定 + + + + Apply + 套用 + + + + Help + 說明 + + + + Defaults + 預設 + + + + Cancel + 取消 + + + + Q3TextEdit + + + &Undo + 復原(&U) + + + + &Redo + 重做(&R) + + + + Cu&t + 剪下(&T) + + + + &Copy + 複製(&C) + + + + &Paste + 貼上(&P) + + + + Clear + 清除 + + + + + Select All + 全部選擇 + + + + Q3TitleBar + + + System + 系統 + + + + Restore up + 向上恢復 + + + + Minimize + 最小化 + + + + Restore down + 向下恢復 + + + + Maximize + 最大化 + + + + Close + 關閉 + + + + Contains commands to manipulate the window + 包含要操作此視窗的指令 + + + + Puts a minimized back to normal + 將最小化視窗放回原大小 + + + + Moves the window out of the way + 把視窗移開 + + + + Puts a maximized window back to normal + 將最大化視窗放回原大小 + + + + Makes the window full screen + 將視窗放大到全畫面 + + + + Closes the window + 關閉視窗 + + + + Displays the name of the window and contains controls to manipulate it + 顯示視窗名稱,並包含操作它的控制元件 + + + + Q3ToolBar + + + More... + 更多... + + + + Q3UrlOperator + + + + + The protocol `%1' is not supported + 協定 %1 未支援 + + + + The protocol `%1' does not support listing directories + 協定 %1 未支援列出目錄 + + + + The protocol `%1' does not support creating new directories + 協定 %1 未支援建立新目錄 + + + + The protocol `%1' does not support removing files or directories + 協定 %1 未支援移除檔案或目錄 + + + + The protocol `%1' does not support renaming files or directories + 協定 %1 未支援重新命名檔案或目錄 + + + + The protocol `%1' does not support getting files + 協定 %1 未支援取得檔案 + + + + The protocol `%1' does not support putting files + 協定 %1 未支援寫入檔案 + + + + + The protocol `%1' does not support copying or moving files or directories + 協定 %1 未支援複製或移動檔案或目錄 + + + + + (unknown) + (未知) + + + + Q3Wizard + + + &Cancel + 取消(&C) + + + + < &Back + <返回(&B) + + + + &Next > + 下一個(&N)> + + + + &Finish + 完成(&F) + + + + &Help + 說明(&H) + + + + QAbstractSocket + + + + + + Host not found + 找不到主機 + + + + + + Connection refused + 連線被拒 + + + + Connection timed out + 連線逾時 + + + + + + Operation on socket is not supported + Socket 的操作未被支援 + + + + Socket operation timed out + Socket 操作逾時 + + + + Socket is not connected + Socket 未連線 + + + + Network unreachable + 無法使用網路 + + + + QAbstractSpinBox + + + &Step up + 單步向上(&S) + + + + Step &down + 單步向下(&D) + + + + &Select All + 全部選擇(&S) + + + + QApplication + + + Activate + 啟動 + + + + Executable '%1' requires Qt %2, found Qt %3. + 執行檔 %1 需要 Qt %2,但只找到 Qt %3。 + + + + Incompatible Qt Library Error + Qt 函式庫不相容的錯誤 + + + + QT_LAYOUT_DIRECTION + Translate this string to the string 'LTR' in left-to-right languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to get proper widget layout. + LTR + + + + Activates the program's main window + 啟動程式的主視窗 + + + + QAxSelect + + + Select ActiveX Control + 選擇 ActiveX 控制 + + + + OK + 確定 + + + + &Cancel + 取消(&C) + + + + COM &Object: + COM 物件(&O) + + + + QCheckBox + + + Uncheck + 取消勾選 + + + + Check + 勾選 + + + + Toggle + 切換 + + + + QColorDialog + + + Hu&e: + 色調(&E): + + + + &Sat: + 飽和度(&S): + + + + &Val: + 亮度(&V): + + + + &Red: + 紅(&R): + + + + &Green: + 綠(&G): + + + + Bl&ue: + 藍(&U): + + + + A&lpha channel: + Alpha 色頻(&L): + + + + Select Color + 選擇顏色 + + + + &Basic colors + 基本顏色(&B) + + + + &Custom colors + 自訂顏色(&C) + + + &Define Custom Colors >> + 定義自訂顏色(&D)>> + + + OK + 確定 + + + Cancel + 取消 + + + + &Add to Custom Colors + 新增到自訂顏色(&A) + + + Select color + 選擇顏色 + + + + QComboBox + + + + Open + 開啟 + + + + False + + + + + True + + + + + Close + 關閉 + + + + QCoreApplication + + %1: permission denied + QSystemSemaphore + %1:存取被拒 + + + %1: already exists + QSystemSemaphore + %1:已存在 + + + %1: doesn't exists + QSystemSemaphore + %1:不存在 + + + %1: out of resources + QSystemSemaphore + %1:資源不足 + + + %1: unknown error %2 + QSystemSemaphore + %1:未知的錯誤 %2 + + + + %1: key is empty + QSystemSemaphore + %1:鍵值是空的 + + + + %1: unable to make key + QSystemSemaphore + %1:無法產生鍵值 + + + + %1: ftok failed + QSystemSemaphore + %1:ftok 失敗 + + + + QDB2Driver + + + Unable to connect + 無法連接 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + Unable to set autocommit + 無法設定自動提交 + + + + QDB2Result + + + + Unable to execute statement + 無法執行敘述 + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to bind variable + 無法結合變數 + + + + Unable to fetch record %1 + 無法抓取紀錄 %1 + + + + Unable to fetch next + 無法抓取下一筆 + + + + Unable to fetch first + 無法抓取第一筆 + + + + QDateTimeEdit + + + AM + AM + + + + am + am + + + + PM + PM + + + + pm + pm + + + + QDial + + + QDial + QDial + + + + SpeedoMeter + SpeedoMeter + + + + SliderHandle + SliderHandle + + + + QDialog + + + What's This? + 這是什麼? + + + + Done + 完成 + + + + QDialogButtonBox + + + + + OK + 確定 + + + + Save + 儲存 + + + + &Save + 儲存(&S) + + + + Open + 開啟 + + + + Cancel + 取消 + + + + &Cancel + 取消(&C) + + + + Close + 關閉 + + + + &Close + 關閉(&C) + + + + Apply + 套用 + + + + Reset + 重置 + + + + Help + 說明 + + + + Don't Save + 不要儲存 + + + + Discard + 丟棄 + + + + &Yes + 是(&Y) + + + + Yes to &All + 全部回答是(&A) + + + + &No + 否(&N) + + + + N&o to All + 全部回答否(&O) + + + + Save All + 全部儲存 + + + + Abort + 中止 + + + + Retry + 重試 + + + + Ignore + 忽略 + + + + Restore Defaults + 回復預設值 + + + + Close without Saving + 關閉而不儲存 + + + + &OK + 確定(&O) + + + + QDirModel + + + Name + 名稱 + + + + Size + 大小 + + + + Kind + Match OS X Finder + 種類 + + + + Type + All other platforms + 型態 + + + + Date Modified + 變更日期 + + + + QDockWidget + + + Close + 關閉 + + + + Dock + 嵌入 + + + + Float + 飄浮 + + + + QDoubleSpinBox + + + More + 更多 + + + + Less + 較少 + + + + QErrorMessage + + + Debug Message: + 除錯訊息: + + + + Warning: + 警告: + + + + Fatal Error: + 嚴重錯誤: + + + + &Show this message again + 再度顯示此訊息(&S) + + + + &OK + 確定(&O) + + + + QFile + + + + Destination file exists + 目標檔已存在 + + + + Cannot remove source file + + + + + Cannot open %1 for input + 無法開啟 %1 以輸入 + + + + Cannot open for output + 無法開啟 %1 以輸出 + + + + Failure to write block + 寫入區塊時失敗 + + + + Cannot create %1 for output + 無法建立 %1 以輸出 + + + + QFileDialog + + + + All Files (*) + 所有檔案 (*) + + + + Directories + 目錄 + + + + + + + &Open + 開啟(&O) + + + + + &Save + 儲存(&S) + + + + Open + 開啟 + + + + %1 already exists. +Do you want to replace it? + %1 已存在 +您要取代它嗎? + + + + %1 +File not found. +Please verify the correct file name was given. + %1 +找不到檔案。 +請檢查檔名是否正確。 + + + + My Computer + 我的電腦 + + + + &Rename + 重新命名(&R) + + + + &Delete + 刪除(&D) + + + + Show &hidden files + 顯示隱藏檔(&H) + + + + + Back + 返回 + + + + + Parent Directory + 父目錄 + + + + + List View + 列表檢視 + + + + + Detail View + 詳細檢視 + + + + + Files of type: + 檔案型態: + + + + + Directory: + 目錄: + + + +File not found. +Please verify the correct file name was given + +檔案找不到。 +請檢查檔名是否正確。 + + + + + %1 +Directory not found. +Please verify the correct directory name was given. + %1 +找不到目錄。 +請檢查目錄名稱是否正確。 + + + + '%1' is write protected. +Do you want to delete it anyway? + %1 有寫入保護。 +您確定要刪除它嗎? + + + + Are sure you want to delete '%1'? + 您確定要刪除 %1 嗎? + + + + Could not delete directory. + 無法刪除目錄。 + + + + Recent Places + 最近的地方 + + + + All Files (*.*) + 所有檔案 (*.*) + + + + Save As + 另存新檔 + + + + Drive + 磁碟 + + + + + File + 檔案 + + + + Unknown + 未知 + + + + Find Directory + 尋找目錄 + + + + Show + 顯示 + + + + + Forward + 往前 + + + + New Folder + 新資料夾 + + + + &New Folder + 新增資料夾(&N) + + + + + &Choose + 選擇(&C) + + + + Remove + 移除 + + + + + File &name: + 檔名(&N): + + + + + Look in: + 尋找於: + + + + + Create New Folder + 建立新資料夾 + + + + QFileSystemModel + + + Invalid filename + 不合法的檔名 + + + + <b>The name "%1" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks. + <b>無法使用名稱 "%1"。</b><p>請使用其它名稱,字元數少一點,或是不要有標點符號。 + + + + Name + 名稱 + + + + Size + 大小 + + + + Kind + Match OS X Finder + 種類 + + + + Type + All other platforms + 型態 + + + + Date Modified + 變更日期 + + + + My Computer + 我的電腦 + + + + Computer + 電腦 + + + + %1 TB + %1 TB + + + + %1 GB + %1 GB + + + + %1 MB + %1 MB + + + + %1 KB + %1 KB + + + + %1 bytes + %1 位元組 + + + + QFontDatabase + + + + Normal + 正常 + + + + + + Bold + 粗體 + + + + + Demi Bold + 半粗體 + + + + + + Black + 黑體 + + + + Demi + 半體 + + + + + Light + 輕體 + + + + + Italic + 斜體 + + + + + Oblique + 傾斜體 + + + + Any + 任何 + + + + Latin + 拉丁 + + + + Greek + 希臘 + + + + Cyrillic + 斯拉夫 + + + + Armenian + 亞美尼亞 + + + + Hebrew + 希伯來 + + + + Arabic + 阿拉伯 + + + + Syriac + 敘利亞 + + + + Thaana + Thaana + + + + Devanagari + Devanagari + + + + Bengali + 孟加拉 + + + + Gurmukhi + Gurmukhi + + + + Gujarati + Gujarati + + + + Oriya + Oriya + + + + Tamil + 坦米爾 + + + + Telugu + Telugu + + + + Kannada + 坎達那 + + + + Malayalam + 馬來語 + + + + Sinhala + 錫蘭 + + + + Thai + 泰語 + + + + Lao + 寮國 + + + + Tibetan + 西藏 + + + + Myanmar + 緬甸 + + + + Georgian + 喬治亞 + + + + Khmer + 高棉 + + + + Simplified Chinese + 簡體中文 + + + + Traditional Chinese + 繁體中文 + + + + Japanese + 日語 + + + + Korean + 韓語 + + + + Vietnamese + 越南 + + + + Symbol + 符號 + + + + Ogham + 歐甘 + + + + Runic + 盧恩 + + + + QFontDialog + + + &Font + 字型(&F) + + + + Font st&yle + 字型樣式(&Y) + + + + &Size + 大小(&S) + + + + Effects + 效果 + + + + Stri&keout + 刪除線(&K) + + + + &Underline + 底線(&U) + + + + Sample + 範例 + + + + Wr&iting System + 寫入系統(&I) + + + + + Select Font + 選擇字型 + + + + QFtp + + + + Not connected + 未連線 + + + + + Host %1 not found + 找不到主機 %1 + + + + + Connection refused to host %1 + 連線到主機 %1 被拒 + + + + Connection timed out to host %1 + 連線到主機 %1 逾時 + + + + + + Connected to host %1 + 已連接到主機 %1 + + + + + Connection refused for data connection + 資料連線被拒 + + + + + + + Unknown error + 未知的錯誤 + + + + + Connecting to host failed: +%1 + 連線到主機失敗: +%1 + + + + + Login failed: +%1 + 登入失敗: +%1 + + + + + Listing directory failed: +%1 + 列出目錄時失敗: +%1 + + + + + Changing directory failed: +%1 + 變更目錄時失敗: +%1 + + + + + Downloading file failed: +%1 + 下載檔案時失敗: +%1 + + + + + Uploading file failed: +%1 + 上傳檔案時失敗: +%1 + + + + + Removing file failed: +%1 + 移除檔案時失敗: +%1 + + + + + Creating directory failed: +%1 + 建立目錄時失敗: +%1 + + + + + Removing directory failed: +%1 + 移除目錄時失敗: +%1 + + + + + + Connection closed + 連線已關閉 + + + + Host %1 found + 找到主機 %1 + + + + Connection to %1 closed + 到 %1 的連線已關閉 + + + + Host found + 找到主機 + + + + Connected to host + 已連線到主機 + + + + QHostInfo + + + Unknown error + 未知的錯誤 + + + + QHostInfoAgent + + + + + + + + + + Host not found + 找不到主機 + + + + + + + Unknown address type + 未知的位址型態 + + + + + + Unknown error + 未知的錯誤 + + + + QHttp + + + + + + Unknown error + 未知的錯誤 + + + + + Request aborted + 要求中止 + + + + + No server set to connect to + 沒有設定要連線到哪個伺服器 + + + + + Wrong content length + 錯誤的內容長度 + + + + + Server closed connection unexpectedly + 伺服器無預警關閉連線 + + + + Unknown authentication method + + + + + Error writing response to device + 寫入回應到裝置時發生錯誤 + + + + + Connection refused + 連線被拒 + + + + + + Host %1 not found + 找不到主機 %1 + + + + + + + HTTP request failed + HTTP 要求失敗 + + + + + Invalid HTTP response header + 不合法的 HTTP 回覆標頭 + + + + + + + Invalid HTTP chunked body + 不合法的 HTTP 區塊主體 + + + + Host %1 found + 找到主機 %1 + + + + Connected to host %1 + 已連接到主機 %1 + + + + Connection to %1 closed + 到 %1 的連線已關閉 + + + + Host found + 找到主機 + + + + Connected to host + 已連線到主機 + + + + + Connection closed + 連線已關閉 + + + + Proxy authentication required + 代理伺服器需要認證 + + + + Authentication required + 需要認證 + + + + Connection refused (or timed out) + 連線被拒(或連線逾時) + + + + Proxy requires authentication + 代理伺服器需要認證 + + + + Host requires authentication + 主機需要認證 + + + + Data corrupted + 資料已損毀 + + + + Unknown protocol specified + 指定了未知的協定 + + + + SSL handshake failed + SSL 溝通失敗 + + + + HTTPS connection requested but SSL support not compiled in + HTTPS 連線需要的 SSL 支援並未編譯進來 + + + + QHttpSocketEngine + + + Did not receive HTTP response from proxy + 未從代理伺服器接收到 HTTP 回應 + + + + Error parsing authentication request from proxy + 剖析從代理伺服器傳來的認證要求時發生錯誤 + + + + Authentication required + 需要認證 + + + + Proxy denied connection + 代理伺服器拒絕連線 + + + + Error communicating with HTTP proxy + 與 HTTP 代理伺服器聯繫時發生錯誤 + + + + Proxy server not found + 找不到代理伺服器 + + + + Proxy connection refused + 代理伺服器連線被拒 + + + + Proxy server connection timed out + 代理伺服器連線逾時 + + + + Proxy connection closed prematurely + 代理伺服器連線已不正常關閉 + + + + QIBaseDriver + + + Error opening database + 開啟資料庫發生錯誤 + + + + Could not start transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QIBaseResult + + + Unable to create BLOB + 無法建立 BLOB + + + + Unable to write BLOB + 無法寫入 BLOB + + + + Unable to open BLOB + 無法開啟 BLOB + + + + Unable to read BLOB + 無法讀取 BLOB + + + + + Could not find array + 找不到陣列 + + + + Could not get array data + 無法取得陣列資料 + + + + Could not get query info + 無法取得查詢資訊 + + + + Could not start transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Could not allocate statement + 無法配置敘述 + + + + Could not prepare statement + 無法準備敘述 + + + + + Could not describe input statement + 無法描述輸入敘述 + + + + Could not describe statement + 無法描述敘述 + + + + Unable to close statement + 無法關閉敘述 + + + + Unable to execute query + 無法執行查詢 + + + + Could not fetch next item + 無法抓取下一個項目 + + + + Could not get statement info + 無法取得敘述資訊 + + + + QIODevice + + + Permission denied + 權限不足 + + + + Too many open files + 開啟過多檔案 + + + + No such file or directory + 找不到該檔案或目錄 + + + + No space left on device + 裝置上已無空間 + + + + Unknown error + 未知的錯誤 + + + + QInputContext + + + XIM + XIM + + + + XIM input method + XIM 輸入法 + + + + Windows input method + Windows 輸入法 + + + + Mac OS X input method + Mac OS X 輸入法 + + + + QInputDialog + + + Enter a value: + 請輸入值: + + + + QLibrary + + QLibrary::load_sys: Cannot load %1 (%2) + QLibrary::load_sys: 無法載入 %1 (%2) + + + QLibrary::unload_sys: Cannot unload %1 (%2) + QLibrary::unload_sys: 無法卸載 %1 (%2) + + + QLibrary::resolve_sys: Symbol "%1" undefined in %2 (%3) + QLibrary::resolve_sys: 符號 "%1" 未定義於 %2 (%3) + + + + Could not mmap '%1': %2 + 無法 mmap '%1':%2 + + + + Plugin verification data mismatch in '%1' + 在 %1 中的外掛程式確認資料不符合 + + + + Could not unmap '%1': %2 + 無法 unmap '%1':%2 + + + + The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5] + 外掛程式 %1 使用不相容的 Qt 函式庫(%2.%3.%4)【%5】 + + + + The plugin '%1' uses incompatible Qt library. Expected build key "%2", got "%3" + 外掛程式 %1 使用不相容的 Qt 函式庫。預期建構鑰 %2,卻得到 %3 + + + + Unknown error + 未知的錯誤 + + + + + The shared library was not found. + 找不到分享函式庫 + + + + The file '%1' is not a valid Qt plugin. + 檔案 %1 不是合法的 Qt 外掛程式。 + + + + The plugin '%1' uses incompatible Qt library. (Cannot mix debug and release libraries.) + 外掛程式 %1 使用不相容的 Qt 函式庫。(不能將除錯與釋出版的函式庫混在一起。) + + + + + Cannot load library %1: %2 + 無法載入函式庫 %1:%2 + + + + + Cannot unload library %1: %2 + 無法卸載函式庫 %1:%2 + + + + + Cannot resolve symbol "%1" in %2: %3 + 無法反解 %2 內的符號 %1:%3 + + + + QLineEdit + + + &Undo + 復原(&U) + + + + &Redo + 重做(&R) + + + + Cu&t + 剪下(&T) + + + + &Copy + 複製(&C) + + + + &Paste + 貼上(&P) + + + + Delete + 刪除 + + + + Select All + 全部選擇 + + + + QLocalServer + + + + %1: Name error + %1:名稱錯誤 + + + + %1: Permission denied + %1:存取被拒 + + + + %1: Address in use + %1:位址使用中 + + + + + %1: Unknown error %2 + %1:未知的錯誤 %2 + + + + QLocalSocket + + + + %1: Connection refused + %1:連線被拒 + + + + + %1: Remote closed + %1:遠端已關閉 + + + + + + + %1: Invalid name + %1:不合法的名稱 + + + + + %1: Socket access error + %1:Socket 位址錯誤 + + + + + %1: Socket resource error + %1:Socket 資源錯誤 + + + + + %1: Socket operation timed out + %1:Socket 操作逾時 + + + + + %1: Datagram too large + %1:資料包過大 + + + + + + %1: Connection error + %1:連線錯誤 + + + + + %1: The socket operation is not supported + %1:socket 操作未支援 + + + + %1: Unknown error + %1:未知的錯誤 + + + + + %1: Unknown error %2 + %1:未知的錯誤 %2 + + + + QMYSQLDriver + + + Unable to open database ' + 無法開啟資料庫 + + + + Unable to connect + 無法連線 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QMYSQLResult + + + Unable to fetch data + 無法抓取資料 + + + + Unable to execute query + 無法執行查詢 + + + + Unable to store result + 無法儲存結果 + + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to reset statement + 無法重置敘述 + + + + Unable to bind value + 無法結合數值 + + + + Unable to execute statement + 無法執行敘述 + + + + + Unable to bind outvalues + 無法結合輸出值 + + + + Unable to store statement results + 無法儲存敘述結果 + + + + Unable to execute next query + 無法執行下一個查詢 + + + + Unable to store next result + 無法儲存下一個結果 + + + + QMdiArea + + + (Untitled) + (未命名) + + + + QMdiSubWindow + + + %1 - [%2] + %1 - [%2] + + + + Close + 關閉 + + + + Minimize + 最小化 + + + + Restore Down + 向下恢復 + + + + &Restore + 回復(&R) + + + + &Move + 移動(&M) + + + + &Size + 大小(&S) + + + + Mi&nimize + 最小化(&N) + + + + Ma&ximize + 最大化(&X) + + + + Stay on &Top + 留在頂端(&T) + + + + &Close + 關閉(&C) + + + + - [%1] + - [%1] + + + + Maximize + 最大化 + + + + Unshade + 取消遮蔽 + + + + Shade + 遮蔽 + + + + Restore + 回復 + + + + Help + 說明 + + + + Menu + 選單 + + + + QMenu + + + + Close + 關閉 + + + + + Open + 開啟 + + + + + + Execute + 執行 + + + + QMenuBar + + About + 關於 + + + Config + 設定 + + + Preference + 喜好設定 + + + Options + 選項 + + + Setting + 設定 + + + Setup + 設定 + + + Quit + 離開 + + + Exit + 離開 + + + About %1 + 關於 %1 + + + About Qt + 關於 Qt + + + Preferences + 喜好設定 + + + Quit %1 + 離開 %1 + + + + QMessageBox + + + Help + 說明 + + + + + + + OK + 確定 + + + + About Qt + 關於 Qt + + + <p>This program uses Qt version %1.</p> + <p> 這個程式使用 Qt 版本 %1</p> + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qtopia Core.</p><p>Qt is a Trolltech product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + <h3>關於 Qt</h3>%1<p>Qt 為一個跨平台的 C++ 開發工具。</p><p>Qt 提供各平台相容機制,只要寫一份程式碼,就可以在 MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux 與各主要的商業 Unix 平台上編譯。Qt 也可以用 Qtopia Core 用於嵌入式系統。</p><p>Qt 為 Trolltech 的產品。詳情請參考 <a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + + Show Details... + 顯示詳情... + + + + Hide Details... + 隱藏詳情... + + + + <h3>About Qt</h3><p>This program uses Qt version %1.</p><p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is available under three different licensing options designed to accommodate the needs of our various users.</p>Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of the GNU LGPL version 2.1 or GNU GPL version 3.0.</p><p>Qt licensed under the GNU LGPL version 2.1 is appropriate for the development of Qt applications (proprietary or open source) provided you can comply with the terms and conditions of the GNU LGPL version 2.1.</p><p>Qt licensed under the GNU General Public License version 3.0 is appropriate for the development of Qt applications where you wish to use such applications in combination with software subject to the terms of the GNU GPL version 3.0 or where you are otherwise willing to comply with the terms of the GNU GPL version 3.0.</p><p>Please see <a href="http://qt.nokia.com/products/licensing">qt.nokia.com/products/licensing</a> for an overview of Qt licensing.</p><p>Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).</p><p>Qt is a Nokia product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is a Nokia product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + <h3>關於 Qt</h3>%1<p>Qt 為一個跨平台的 C++ 開發工具。</p><p>Qt 提供各平台相容機制,只要寫一份程式碼,就可以在 MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux 與各主要的商業 Unix 平台上編譯。Qt 也有用於嵌入式 Linux 與 Windows CE 的版本。</p><p>Qt 為 Nokia 的產品。詳情請參考 <a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + <p>This program uses Qt Open Source Edition version %1.</p><p>Qt Open Source Edition is intended for the development of Open Source applications. You need a commercial Qt license for development of proprietary (closed source) applications.</p><p>Please see <a href="http://qt.nokia.com/company/model/">qt.nokia.com/company/model/</a> for an overview of Qt licensing.</p> + <p>這個程式使用了 Qt 開放源碼版本 %1。</p><p>Qt 開放源碼版本是專門為了開發開放源碼應用程式使用的版本。若是您要開發專利私有(封閉)軟體,您需要 Qt 的商業授權。</p><p>Qt 的授權概要請參考 <a href="http://qt.nokia.com/company/model/">qt.nokia.com/company/model/</a>。</p> + + + <h3>About Qt</h3>%1<p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt Embedded.</p><p>Qt is a Trolltech product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p> + <h3>關於 Qt</h3>%1<p>Qt 為一個跨平台的 C++ 開發工具。</p><p>Qt 提供各平台相容機制,只要寫一份程式碼,就可以在 MS&nbsp;Windows、Mac&nbsp;OS&nbsp;X、Linux 與各主要的商業 Unix 平台上編譯。Qt 也可以用 Qtopia Core 用於嵌入式系統。</p><p>Qt 為 Trolltech 的產品。詳情請參考 <a href="http://qt.nokia.com/">qt.nokia.com</a>。</p> + + + + QMultiInputContext + + + Select IM + 選擇輸入法 + + + + QMultiInputContextPlugin + + + Multiple input method switcher + 多重輸入法切換器 + + + + Multiple input method switcher that uses the context menu of the text widgets + 使用文字元件中的內文選單的多重輸入法切換器 + + + + QNativeSocketEngine + + + The remote host closed the connection + 遠端主機關閉了連線 + + + + Network operation timed out + 網路操作逾時 + + + + Out of resources + 資源不足 + + + + Unsupported socket operation + 未支援的 socket 操作 + + + + Protocol type not supported + 協定型態未支援 + + + + Invalid socket descriptor + 不合法的 socket 描述子 + + + + Network unreachable + 無法使用網路 + + + + Permission denied + 權限不足 + + + + Connection timed out + 連線逾時 + + + + Connection refused + 連線被拒 + + + + The bound address is already in use + 結合的位址已經在使用中 + + + + The address is not available + 無法取得位址 + + + + The address is protected + 此位址已被保護 + + + + Unable to send a message + 無法送出訊息 + + + + Unable to receive a message + 無法接收訊息 + + + + Unable to write + 無法寫入 + + + + Network error + 網路錯誤 + + + + Another socket is already listening on the same port + 另一個 socket 已經在監聽同一個連接埠 + + + + Unable to initialize non-blocking socket + 無法初始化非阻擋性 socket + + + + Unable to initialize broadcast socket + 無法初始化廣播 socket + + + + Attempt to use IPv6 socket on a platform with no IPv6 support + 試圖在沒有 IPv6 支援的平台上使用 IPv6 socket + + + + Host unreachable + 無法連線到主機 + + + + Datagram was too large to send + 資料過大無法送出 + + + + Operation on non-socket + 對非 socket 操作 + + + + Unknown error + 未知的錯誤 + + + + The proxy type is invalid for this operation + 代理伺服器型態無法支援此操作 + + + + QNetworkAccessCacheBackend + + + Error opening %1 + 開啟 %1 發生錯誤 + + + + QNetworkAccessFileBackend + + + Request for opening non-local file %1 + 要求開啟非本地端檔案 %1 + + + + Error opening %1: %2 + 開啟 %1 發生錯誤:%2 + + + + Write error writing to %1: %2 + 寫入 %1 時發生錯誤:%2 + + + + Cannot open %1: Path is a directory + 無法開啟 %1:此路徑是一個目錄 + + + + Read error reading from %1: %2 + 從 %1 讀取錯誤:%2 + + + + QNetworkAccessFtpBackend + + + No suitable proxy found + 找不到合適的代理伺服器 + + + + Cannot open %1: is a directory + 無法開啟 %1:是一個目錄 + + + + Logging in to %1 failed: authentication required + 登入 %1 失敗:需要認證 + + + + Error while downloading %1: %2 + 下載 %1 時發生錯誤:%2 + + + + Error while uploading %1: %2 + 上傳 %1 時發生錯誤:%2 + + + + QNetworkAccessHttpBackend + + + No suitable proxy found + 找不到合適的代理伺服器 + + + + QNetworkReply + + + Error downloading %1 - server replied: %2 + 下載 %1 時發生錯誤─伺服器回應:%2 + + + + Protocol "%1" is unknown + 未知的協定 %1 + + + + QNetworkReplyImpl + + + + Operation canceled + 取消操作 + + + + QOCIDriver + + + Unable to logon + 無法登入 + + + + Unable to initialize + QOCIDriver + 無法初始化 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QOCIResult + + + + + Unable to bind column for batch execute + 無法結合欄位以做批次執行 + + + + Unable to execute batch statement + 無法執行批次敘述 + + + + Unable to goto next + 無法跳到下一個 + + + + Unable to alloc statement + 無法配置敘述 + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to bind value + 無法結合數值 + + + Unable to execute select statement + 無法執行選取的敘述 + + + + Unable to execute statement + 無法執行敘述 + + + + QODBCDriver + + + Unable to connect + 無法連接 + + + + Unable to connect - Driver doesn't support all needed functionality + 無法連接─驅動程式無法支援所有需要的功能 + + + + Unable to disable autocommit + 無法關閉自動提交功能 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + Unable to enable autocommit + 無法開啟自動提交功能 + + + + QODBCResult + + + + QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration + QODBCResult::reset: 無法設定 SQL_CURSOR_STATIC 做為敘述屬性。請檢查您的 ODBC 驅動程式的設定 + + + + + Unable to execute statement + 無法執行敘述 + + + + Unable to fetch next + 無法抓取下一筆 + + + + Unable to prepare statement + 無法準備敘述 + + + + Unable to bind variable + 無法結合變數 + + + + + + Unable to fetch last + 無法抓取最後一筆 + + + + Unable to fetch + 無法抓取 + + + + Unable to fetch first + 無法抓取第一筆 + + + + Unable to fetch previous + 無法抓取前一筆 + + + + QObject + + + Home + 首頁 + + + + Operation not supported on %1 + 在 %1 上不支援此操作 + + + + Invalid URI: %1 + 不合法的網址:%1 + + + + Write error writing to %1: %2 + 寫入 %1 時發生錯誤:%2 + + + + Read error reading from %1: %2 + 從 %1 讀取錯誤:%2 + + + + Socket error on %1: %2 + %1 上發生 socket 錯誤:%2 + + + + Remote host closed the connection prematurely on %1 + 於 %1 上遠端主機關閉了不正常的連線 + + + + Protocol error: packet of size 0 received + 協定錯誤:接收到大小為 0 的封包 + + + + + No host name given + 未指定主機 + + + + QPPDOptionsModel + + + Name + 名稱 + + + + Value + + + + + QPSQLDriver + + + Unable to connect + 無法連線 + + + + Could not begin transaction + 無法開始事務 + + + + Could not commit transaction + 無法提交事務 + + + + Could not rollback transaction + 無法反轉事務 + + + + Unable to subscribe + 無法訂閱 + + + + Unable to unsubscribe + 無法取消訂閱 + + + + QPSQLResult + + + Unable to create query + 無法建立查詢 + + + + Unable to prepare statement + 無法準備敘述 + + + + QPageSetupWidget + + + Centimeters (cm) + 公分 + + + + Millimeters (mm) + 公厘 + + + + Inches (in) + 英吋 + + + + Points (pt) + + + + + Form + 表單 + + + + Paper + 紙張 + + + + Page size: + 紙張大小: + + + + Width: + 寬度: + + + + Height: + 高度: + + + + Paper source: + 紙張來源: + + + + Orientation + 方向 + + + + Portrait + 縱向 + + + + Landscape + 橫向 + + + + Reverse landscape + 反序橫向 + + + + Reverse portrait + 反序縱向 + + + + Margins + 邊緣 + + + + top margin + 上緣 + + + + left margin + 左緣 + + + + right margin + 右緣 + + + + bottom margin + 下緣 + + + + QPluginLoader + + + Unknown error + 未知的錯誤 + + + + The plugin was not loaded. + 外掛程式未載入。 + + + + QPrintDialog + + + locally connected + 本地連接 + + + + + Aliases: %1 + 別名:%1 + + + + + unknown + 未知 + + + Portrait + 縱向 + + + Landscape + 橫向 + + + + A0 (841 x 1189 mm) + A0 (841 x 1189 mm) + + + + A1 (594 x 841 mm) + A1 (594 x 841 mm) + + + + A2 (420 x 594 mm) + A2 (420 x 594 mm) + + + + A3 (297 x 420 mm) + A3 (297 x 420 mm) + + + + A4 (210 x 297 mm, 8.26 x 11.7 inches) + A4 (210 x 297 mm, 8.26 x 11.7 英吋) + + + + A5 (148 x 210 mm) + A5 (148 x 210 mm) + + + + A6 (105 x 148 mm) + A6 (105 x 148 mm) + + + + A7 (74 x 105 mm) + A7 (74 x 105 mm) + + + + A8 (52 x 74 mm) + A8 (52 x 74 mm) + + + + A9 (37 x 52 mm) + A9 (37 x 52 mm) + + + + B0 (1000 x 1414 mm) + B0 (1000 x 1414 mm) + + + + B1 (707 x 1000 mm) + B1 (707 x 1000 mm) + + + + B2 (500 x 707 mm) + B2 (500 x 707 mm) + + + + B3 (353 x 500 mm) + B3 (353 x 500 mm) + + + + B4 (250 x 353 mm) + B4 (250 x 353 mm) + + + + B5 (176 x 250 mm, 6.93 x 9.84 inches) + B5 (176 x 250 mm, 6.93 x 9.84 英吋) + + + + B6 (125 x 176 mm) + B6 (125 x 176 mm) + + + + B7 (88 x 125 mm) + B7 (88 x 125 mm) + + + + B8 (62 x 88 mm) + B8 (62 x 88 mm) + + + + B9 (44 x 62 mm) + B9 (44 x 62 mm) + + + + B10 (31 x 44 mm) + B10 (31 x 44 mm) + + + + C5E (163 x 229 mm) + C5E (163 x 229 mm) + + + + DLE (110 x 220 mm) + DLE (110 x 220 mm) + + + + Executive (7.5 x 10 inches, 191 x 254 mm) + Executive (7.5 x 10 英吋, 191 x 254 mm) + + + + Folio (210 x 330 mm) + 對開 (210 x 330 mm) + + + + Ledger (432 x 279 mm) + Ledger (432 x 279 mm) + + + + Legal (8.5 x 14 inches, 216 x 356 mm) + Legal (8.5 x 14 英吋, 216 x 356 mm) + + + + Letter (8.5 x 11 inches, 216 x 279 mm) + Letter (8.5 x 11 英吋, 216 x 279 mm) + + + + Tabloid (279 x 432 mm) + Tabloid (279 x 432 mm) + + + + US Common #10 Envelope (105 x 241 mm) + US 常用 10 號信封 (105x241 mm) + + + + OK + 確定 + + + Cancel + 取消 + + + Page size: + 紙張大小: + + + Orientation: + 方向: + + + Paper source: + 紙張來源: + + + + + + Print + 列印 + + + File + 檔案 + + + Printer + 印表機 + + + + Print To File ... + 列印到檔案... + + + Print dialog + 列印對話框 + + + Paper format + 紙張格式 + + + Size: + 大小: + + + Properties + 內容 + + + Printer info: + 印表機資訊: + + + Browse + 瀏覽 + + + Print to file + 列印到檔案 + + + + Print range + 列印範圍 + + + + Print all + 全部列印 + + + Pages from + 指定頁面:從 + + + to + + + + Selection + 選擇區 + + + Copies + 份數 + + + Number of copies: + 列印份數: + + + Collate + 校對 + + + Print last page first + 從最後一頁印起 + + + Other + 其他 + + + Print in color if available + 可以的話用彩色列印 + + + Double side printing + 雙面列印 + + + + File %1 is not writable. +Please choose a different file name. + 檔案 %1 無法寫入。 +請選擇其它檔名。 + + + + %1 already exists. +Do you want to overwrite it? + %1 已存在。 +您要覆寫它嗎? + + + + File exists + 檔案已存在 + + + + <qt>Do you want to overwrite it?</qt> + <qt>您要覆寫它嗎?</qt> + + + + Print selection + 列印選擇區 + + + + %1 is a directory. +Please choose a different file name. + %1 是一個目錄。 +請選擇其他檔名。 + + + + A0 + A0 + + + + A1 + A1 + + + + A2 + A2 + + + + A3 + A3 + + + + A4 + A4 + + + + A5 + A5 + + + + A6 + A6 + + + + A7 + A7 + + + + A8 + A8 + + + + A9 + A9 + + + + B0 + B0 + + + + B1 + B1 + + + + B2 + B2 + + + + B3 + B3 + + + + B4 + B4 + + + + B5 + B5 + + + + B6 + B6 + + + + B7 + B7 + + + + B8 + B8 + + + + B9 + B9 + + + + B10 + B10 + + + + C5E + C5E + + + + DLE + DLE + + + + Executive + Executive + + + + Folio + Folio + + + + Ledger + Ledger + + + + Legal + Legal + + + + Letter + Letter + + + + Tabloid + Tabloid + + + + US Common #10 Envelope + US Common #10 Envelope + + + + Custom + 自訂 + + + + + &Options >> + 操作 (&O) >> + + + + &Print + 列印(&P) + + + + &Options << + 操作 (&O) << + + + + Print to File (PDF) + 列印到檔案(PDF) + + + + Print to File (Postscript) + 列印到檔案(Postscript) + + + + Local file + 本地端檔案 + + + + Write %1 file + 寫入 %1 檔案 + + + + The 'From' value cannot be greater than the 'To' value. + 起始數值不能大於結束數值 + + + + QPrintPreviewDialog + + + + Page Setup + 頁面設定 + + + + %1% + %1% + + + + Print Preview + 列印預覽 + + + + Next page + 下一頁 + + + + Previous page + 前一頁 + + + + First page + 第一頁 + + + + Last page + 最後一頁 + + + + Fit width + 符合寬度 + + + + Fit page + 符合頁面 + + + + Zoom in + 放大 + + + + Zoom out + 縮小 + + + + Portrait + 縱向 + + + + Landscape + 橫向 + + + + Show single page + 顯示單一頁面 + + + + Show facing pages + 顯示封面 + + + + Show overview of all pages + 顯示所有頁面預覽 + + + + Print + 列印 + + + + Page setup + 列印設定 + + + + Close + 關閉 + + + + Export to PDF + 匯出到 PDF 檔 + + + + Export to PostScript + 匯出到 PostScript 檔 + + + + QPrintPropertiesDialog + + PPD Properties + PPD 內容 + + + Save + 儲存 + + + OK + 確定 + + + + QPrintPropertiesWidget + + + Form + 表單 + + + + Page + 頁面 + + + + Advanced + 進階 + + + + QPrintSettingsOutput + + + Form + 表單 + + + + Copies + 份數 + + + + Print range + 列印範圍 + + + + Print all + 全部列印 + + + + Pages from + 指定頁面:從 + + + + to + + + + + Selection + 選擇區 + + + + Output Settings + 輸出設定 + + + + Copies: + 份數: + + + + Collate + 校對 + + + + Reverse + 反向 + + + + Options + 選項 + + + + Color Mode + 顏色模式 + + + + Color + 顏色 + + + + Grayscale + 灰階 + + + + Duplex Printing + 雙工列印 + + + + None + + + + + Long side + 長邊 + + + + Short side + 短邊 + + + + QPrintWidget + + + Form + 表單 + + + + Printer + 印表機 + + + + &Name: + 名稱(&N): + + + + P&roperties + 屬性(&R) + + + + Location: + 位置: + + + + Preview + 預覽 + + + + Type: + 型態: + + + + Output &file: + 輸出檔案(&F): + + + + ... + ... + + + + QProcess + + + + Could not open input redirection for reading + 無法開啟輸入導向以讀取 + + + + + Could not open output redirection for writing + 無法開啟輸出導向以寫入 + + + + Resource error (fork failure): %1 + 資源錯誤(fork 失敗):%1 + + + + + + + + + + + + Process operation timed out + 行程操作逾時 + + + + + + + Error reading from process + 從行程讀取時發生錯誤 + + + + + + Error writing to process + 寫入行程時發生錯誤 + + + + Process crashed + 行程已崩潰 + + + + No program defined + + + + + Process failed to start + 啟動行程失敗 + + + + QProgressDialog + + + Cancel + 取消 + + + + QPushButton + + + Open + 開啟 + + + + QRadioButton + + + Check + 勾選 + + + + QRegExp + + + no error occurred + 沒有發生錯誤 + + + + disabled feature used + 使用已關閉的功能 + + + + bad char class syntax + 錯誤的字元類別語法 + + + + bad lookahead syntax + 錯誤的 lookahead 語法 + + + + bad repetition syntax + 錯誤的重覆語法 + + + + invalid octal value + 不合法的八進位值 + + + + missing left delim + 少了左方的區隔符 + + + + unexpected end + 未預期遇到結尾 + + + + met internal limit + 遇到內部限制 + + + + QSQLite2Driver + + + Error to open database + 開啟資料庫時發生錯誤 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + + Unable to rollback Transaction + 無法反轉事務 + + + + QSQLite2Result + + + Unable to fetch results + 無法抓取結果 + + + + Unable to execute statement + 無法執行敘述 + + + + QSQLiteDriver + + + Error opening database + 開啟資料庫發生錯誤 + + + + Error closing database + 關閉資料庫發生錯誤 + + + + Unable to begin transaction + 無法開始事務 + + + + Unable to commit transaction + 無法提交事務 + + + Unable to roll back transaction + 無法反轉事務 + + + + Unable to rollback transaction + 無法反轉事務 + + + + QSQLiteResult + + + + + Unable to fetch row + 無法抓取列 + + + + Unable to execute statement + 無法執行敘述 + + + + Unable to reset statement + 無法重置敘述 + + + + Unable to bind parameters + 無法結合參數 + + + + Parameter count mismatch + 參數數量不符合 + + + + No query + 沒有查詢 + + + + QScrollBar + + + Scroll here + 在此捲軸 + + + + Left edge + 左邊緣 + + + + Top + 頂端 + + + + Right edge + 右邊緣 + + + + Bottom + 底端 + + + + Page left + 頁面左方 + + + + + Page up + 頁面上方 + + + + Page right + 頁面右方 + + + + + Page down + 頁面下方 + + + + Scroll left + 往左捲軸 + + + + Scroll up + 往上捲軸 + + + + Scroll right + 往右捲軸 + + + + Scroll down + 往下捲軸 + + + + Line up + 對上排列 + + + + Position + 位置 + + + + Line down + 對下排列 + + + + QSharedMemory + + + %1: unable to set key on lock + %1:無法設定鍵值 + + + + %1: create size is less then 0 + %1:建立大小小於 0 + + + + + %1: unable to lock + %1:無法鎖定 + + + + %1: unable to unlock + %1:無法解除鎖定 + + + + + %1: permission denied + %1:存取被拒 + + + + + %1: already exists + %1:已存在 + + + + + %1: doesn't exists + %1:不存在 + + + + + %1: out of resources + %1:資源不足 + + + + + %1: unknown error %2 + %1:未知的錯誤 %2 + + + + %1: key is empty + %1:鍵值是空的 + + + + %1: unix key file doesn't exists + %1:unix 鍵值檔不存在 + + + + %1: ftok failed + %1:ftok 失敗 + + + + + %1: unable to make key + %1:無法產生鍵值 + + + + %1: system-imposed size restrictions + %1:系統大小限制 + + + + %1: not attached + %1:未附加 + + + + %1: invalid size + %1:不合法的大小 + + + + %1: key error + %1:鍵值錯誤 + + + + %1: size query failed + %1:大小查詢失敗 + + + + QShortcut + + + Space + 空白鍵 + + + + Esc + Esc + + + + Tab + Tab + + + + Backtab + Backtab + + + + Backspace + Backspace + + + + Return + Return + + + + Enter + Enter + + + + Ins + Ins + + + + Del + Del + + + + Pause + Pause + + + + Print + Print + + + + SysReq + SysReq + + + + Home + Home + + + + End + End + + + + Left + 左鍵 + + + + Up + 上鍵 + + + + Right + 右鍵 + + + + Down + 下鍵 + + + + PgUp + PgUp + + + + PgDown + PgDown + + + + CapsLock + 大寫鎖定 + + + + NumLock + 數字鎖定 + + + + ScrollLock + 捲軸鎖定 + + + + Menu + 選單 + + + + Help + 說明 + + + + Back + 返回 + + + + Forward + 往前 + + + + Stop + 停止 + + + + Refresh + 刷新 + + + + Volume Down + 音量降低 + + + + Volume Mute + 靜音 + + + + Volume Up + 音量提高 + + + + Bass Boost + 重低音 + + + + Bass Up + Bass Up + + + + Bass Down + Bass Down + + + + Treble Up + Treble Up + + + + Treble Down + Treble Down + + + + Media Play + 媒體播放 + + + + Media Stop + 媒體停止 + + + + Media Previous + 媒體前一首 + + + + Media Next + 媒體下一首 + + + + Media Record + 媒體錄音 + + + + Favorites + 我的最愛 + + + + Search + 搜尋 + + + + Standby + 待命 + + + + Open URL + 開啟網址 + + + + Launch Mail + 啟動郵件程式 + + + + Launch Media + 啟動媒體程式 + + + + Launch (0) + 啟動(0) + + + + Launch (1) + 啟動(1) + + + + Launch (2) + 啟動(2) + + + + Launch (3) + 啟動(3) + + + + Launch (4) + 啟動(4) + + + + Launch (5) + 啟動(5) + + + + Launch (6) + 啟動(6) + + + + Launch (7) + 啟動(7) + + + + Launch (8) + 啟動(8) + + + + Launch (9) + 啟動(9) + + + + Launch (A) + 啟動(A) + + + + Launch (B) + 啟動(B) + + + + Launch (C) + 啟動(C) + + + + Launch (D) + 啟動(D) + + + + Launch (E) + 啟動(E) + + + + Launch (F) + 啟動(F) + + + + Print Screen + 列印螢幕 + + + + Page Up + 往上一頁 + + + + Page Down + 往下一頁 + + + + Caps Lock + 大寫鎖定 + + + + Num Lock + 數字鎖定 + + + + Number Lock + 數字鎖定 + + + + Scroll Lock + 捲軸鎖定 + + + + Insert + 插入 + + + + Delete + 刪除 + + + + Escape + Escape + + + + System Request + 系統要求 SysRq + + + + Select + 選擇 + + + + Yes + + + + + No + + + + + Context1 + 內文1 + + + + Context2 + 內文2 + + + + Context3 + 內文3 + + + + Context4 + 內文4 + + + + Call + 呼叫 + + + + Hangup + 掛斷 + + + + Flip + 反轉 + + + + + Ctrl + Ctrl + + + + + Shift + Shift + + + + + Alt + Alt + + + + + Meta + Meta + + + + + + + + + + + F%1 + F%1 + + + + Home Page + 首頁 + + + + QSlider + + + Page left + 頁面左方 + + + + Page up + 頁面上方 + + + + Position + 位置 + + + + Page right + 頁面右方 + + + + Page down + 頁面下方 + + + + QSocks5SocketEngine + + + Connection to proxy refused + 代理伺服器連線被拒 + + + + Connection to proxy closed prematurely + 代理伺服器連線已不正常關閉 + + + + Proxy host not found + 找不到代理伺服器 + + + + Connection to proxy timed out + 代理伺服器連線逾時 + + + + Proxy authentication failed + 代理伺服器認證失敗 + + + + Proxy authentication failed: %1 + 代理伺服器認證失敗:%1 + + + + SOCKS version 5 protocol error + SOCKS 5 的協定錯誤 + + + + General SOCKSv5 server failure + 一般的 SOCKSv5 伺服器錯誤 + + + + Connection not allowed by SOCKSv5 server + 連線未被 SOCKSv5 伺服器允許 + + + + TTL expired + TTL 逾時 + + + + SOCKSv5 command not supported + SOCKSv5 指令未被支援 + + + + Address type not supported + 位址型態未被支援 + + + + Unknown SOCKSv5 proxy error code 0x%1 + 未知的 SOCKSv5 代理伺服器錯誤代碼 0x%1 + + + Socks5 timeout error connecting to socks server + 連接到 socks 伺服器時發生 socks5 逾時錯誤 + + + + Network operation timed out + 網路操作逾時 + + + + QSpinBox + + + More + 更多 + + + + Less + 較少 + + + + QSql + + + Delete + 刪除 + + + + Delete this record? + 要刪除這筆紀錄嗎? + + + + + + Yes + + + + + + + No + + + + + Insert + 插入 + + + + Update + 更新 + + + + Save edits? + 要儲存編輯過的內容嗎? + + + + Cancel + 取消 + + + + Confirm + 確認 + + + + Cancel your edits? + 要取消編輯嗎? + + + + QSslSocket + + + Unable to write data: %1 + 無法寫入資料:%1 + + + + Error while reading: %1 + 讀取時發生錯誤:%1 + + + + Error during SSL handshake: %1 + SSL 同步時發生錯誤:%1 + + + + Error creating SSL context (%1) + 建立 SSL 內文時發生錯誤(%1) + + + + Invalid or empty cipher list (%1) + 不合法或空白的加密清單(%1) + + + + Error creating SSL session, %1 + 建立 SSL 工作階段時發生錯誤:%1 + + + + Error creating SSL session: %1 + 建立 SSL 工作階段時發生錯誤:%1 + + + + Cannot provide a certificate with no key, %1 + 沒有金鑰無法提供憑證:%1 + + + + Error loading local certificate, %1 + 載入本地憑證時發生錯誤:%1 + + + + Error loading private key, %1 + 載入私鑰時發生錯誤:%1 + + + Private key do not certificate public key, %1 + 私鑰與公鑰不符:%1 + + + + Private key does not certificate public key, %1 + 私密金鑰無法認證公開金鑰,%1 + + + + QSystemSemaphore + + + + %1: out of resources + %1:資源不足 + + + + + %1: permission denied + %1:存取被拒 + + + + %1: already exists + %1:已存在 + + + + %1: does not exist + %1:不存在 + + + + + %1: unknown error %2 + %1:未知的錯誤 %2 + + + + QTDSDriver + + + Unable to open connection + 無法開啟連線 + + + + Unable to use database + 無法使用資料庫 + + + + QTabBar + + + Scroll Left + 往左捲軸 + + + + Scroll Right + 往右捲軸 + + + + QTcpServer + + Socket operation unsupported + 未支援的 socket 操作 + + + + Operation on socket is not supported + Socket 的操作未被支援 + + + + QTextControl + + + &Undo + 復原(&U) + + + + &Redo + 重做(&R) + + + + Cu&t + 剪下(&T) + + + + &Copy + 複製(&C) + + + + Copy &Link Location + 複製連結位址(&L) + + + + &Paste + 貼上(&P) + + + + Delete + 刪除 + + + + Select All + 全部選擇 + + + + QToolButton + + + + Press + 按下 + + + + + Open + 開啟 + + + + QUdpSocket + + + This platform does not support IPv6 + 此平台不支援 IPv6 + + + + QUndoGroup + + + Undo + 復原 + + + + Redo + 重做 + + + + QUndoModel + + + <empty> + <空白> + + + + QUndoStack + + + Undo + 復原 + + + + Redo + 重做 + + + + QUnicodeControlCharacterMenu + + + LRM Left-to-right mark + LRM 左到右標記 + + + + RLM Right-to-left mark + RLM 右到左標記 + + + + ZWJ Zero width joiner + ZWJ 零寬度連接器 + + + + ZWNJ Zero width non-joiner + ZWNJ 零寬度非連接器 + + + + ZWSP Zero width space + ZWSP 零寬度空白 + + + + LRE Start of left-to-right embedding + LRE 左到右嵌入起點 + + + + RLE Start of right-to-left embedding + RLE 右到左嵌入起點 + + + + LRO Start of left-to-right override + LRO 左到右覆寫起點 + + + + RLO Start of right-to-left override + RLO 右到左覆寫起點 + + + + PDF Pop directional formatting + PDF 彈出方向格式 + + + + Insert Unicode control character + 插入萬國碼控制字元 + + + + QWebFrame + + + Request cancelled + 請求已取消 + + + + Request blocked + 請求已被阻擋 + + + + Cannot show URL + 無法顯示網址 + + + + Frame load interruped by policy change + 影像載入因政策變更而中斷 + + + + Cannot show mimetype + 無法顯示 MIME 型態 + + + + File does not exist + 檔案不存在 + + + + QWebPage + + + Bad HTTP request + 不良的 HTTP 請求 + + + + Submit + default label for Submit buttons in forms on web pages + 提交 + + + + Submit + Submit (input element) alt text for <input> elements with no alt, title, or value + 提交 + + + + Reset + default label for Reset buttons in forms on web pages + 重置 + + + + This is a searchable index. Enter search keywords: + text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index' + 這是可搜尋的索引。請輸入關鍵字:  + + + + Choose File + title for file button used in HTML forms + 選擇檔案 + + + + No file selected + text to display in file button used in HTML forms when no file is selected + 未選取任何檔案 + + + + Open in New Window + Open in New Window context menu item + 在新視窗開啟 + + + + Save Link... + Download Linked File context menu item + 儲存連結... + + + + Copy Link + Copy Link context menu item + 複製連結 + + + + Open Image + Open Image in New Window context menu item + 開啟影像 + + + + Save Image + Download Image context menu item + 儲存影像 + + + + Copy Image + Copy Link context menu item + 複製影像 + + + + Open Frame + Open Frame in New Window context menu item + 開啟框架 + + + + Copy + Copy context menu item + 複製 + + + + Go Back + Back context menu item + 往回 + + + + Go Forward + Forward context menu item + 往前 + + + + Stop + Stop context menu item + 停止 + + + + Reload + Reload context menu item + 重新載入 + + + + Cut + Cut context menu item + 剪下 + + + + Paste + Paste context menu item + 貼上 + + + + No Guesses Found + No Guesses Found context menu item + 找不到可能的內容 + + + + Ignore + Ignore Spelling context menu item + 忽略 + + + + Add To Dictionary + Learn Spelling context menu item + 新增到字典 + + + + Search The Web + Search The Web context menu item + 搜尋站台 + + + + Look Up In Dictionary + Look Up in Dictionary context menu item + 在字典裡搜尋 + + + + Open Link + Open Link context menu item + 開啟連結 + + + + Ignore + Ignore Grammar context menu item + 忽略 + + + + Spelling + Spelling and Grammar context sub-menu item + 拼字 + + + + Show Spelling and Grammar + menu item title + 顯示拼字與文法 + + + + Hide Spelling and Grammar + menu item title + 隱藏拼字與文法 + + + + Check Spelling + Check spelling context menu item + 檢查拼字 + + + + Check Spelling While Typing + Check spelling while typing context menu item + 打字時立即檢查拼字 + + + + Check Grammar With Spelling + Check grammar with spelling context menu item + 檢查拼字與文法 + + + + Fonts + Font context sub-menu item + 字型 + + + + Bold + Bold context menu item + 粗體 + + + + Italic + Italic context menu item + 斜體 + + + + Underline + Underline context menu item + 底線 + + + + Outline + Outline context menu item + 外框線 + + + + Direction + Writing direction context sub-menu item + 方向 + + + + Text Direction + Text direction context sub-menu item + 文字方向 + + + + Default + Default writing direction context menu item + 預設 + + + + LTR + Left to Right context menu item + 左到右 + + + + RTL + Right to Left context menu item + 右到左 + + + + Inspect + Inspect Element context menu item + 查驗 + + + + No recent searches + Label for only item in menu that appears when clicking on the search field image, when no searches have been performed + 沒有最近的搜尋 + + + + Recent searches + label for first item in the menu that appears when clicking on the search field image, used as embedded menu title + 最近的搜尋 + + + + Clear recent searches + menu item in Recent Searches menu that empties menu's contents + 清除最近的搜尋 + + + + Unknown + Unknown filesize FTP directory listing item + 未知 + + + + %1 (%2x%3 pixels) + Title string for images + %1(%2x%3 像素) + + + + Web Inspector - %2 + 網站查驗器─%2 + + + + Scroll here + 在此捲軸 + + + + Left edge + 左邊緣 + + + + Top + 頂端 + + + + Right edge + 右邊緣 + + + + Bottom + 底端 + + + + Page left + 頁面左方 + + + + Page up + 頁面上方 + + + + Page right + 頁面右方 + + + + Page down + 頁面下方 + + + + Scroll left + 往左捲軸 + + + + Scroll up + 往上捲軸 + + + + Scroll right + 往右捲軸 + + + + Scroll down + 往下捲軸 + + + + %n file(s) + number of chosen file + + %n 個檔案 + + + + + JavaScript Alert - %1 + JavaScript 警告 ─ %1 + + + + JavaScript Confirm - %1 + JavaScript 確認 ─ %1 + + + + JavaScript Prompt - %1 + JavaScript 提示 ─ %1 + + + + Move the cursor to the next character + 移動游標到下一個字元 + + + + Move the cursor to the previous character + 移動游標到前一個字元 + + + + Move the cursor to the next word + 移動游標到下一個單字 + + + + Move the cursor to the previous word + 移動游標到前一個單字 + + + + Move the cursor to the next line + 移動游標到下一行 + + + + Move the cursor to the previous line + 移動游標到前一行 + + + + Move the cursor to the start of the line + 移動游標到這一行的起頭 + + + + Move the cursor to the end of the line + 移動游標到這一行的結尾 + + + + Move the cursor to the start of the block + 移動游標到這一個區塊的起頭 + + + + Move the cursor to the end of the block + 移動游標到這一個區塊的結尾 + + + + Move the cursor to the start of the document + 移動游標到這一個文件的起頭 + + + + Move the cursor to the end of the document + 移動游標到這一個文件的結尾 + + + + Select all + + + + + Select to the next character + 選擇到下一個字元 + + + + Select to the previous character + 選擇到前一個字元 + + + + Select to the next word + 選擇到下一個單字 + + + + Select to the previous word + 選擇到前一個單字 + + + + Select to the next line + 選擇到下一行 + + + + Select to the previous line + 選擇到前一行 + + + + Select to the start of the line + 選擇到這一行的起頭 + + + + Select to the end of the line + 選擇到這一行的結尾 + + + + Select to the start of the block + 選擇到這一個區塊的起頭 + + + + Select to the end of the block + 選擇到這一個區塊的結尾 + + + + Select to the start of the document + 選擇到這一個文件的起頭 + + + + Select to the end of the document + 選擇到這一個文件的結尾 + + + + Delete to the start of the word + 刪除到此單字的起頭 + + + + Delete to the end of the word + 刪除到此單字的結尾 + + + + Insert a new paragraph + + + + + Insert a new line + + + + + QWhatsThisAction + + + What's This? + 這是什麼? + + + + QWidget + + + * + + + + + + QWizard + + + Go Back + 往回 + + + + Continue + 繼續 + + + + Commit + 提交 + + + + Done + 完成 + + + Quit + 離開 + + + + Help + 說明 + + + + < &Back + <返回(&B) + + + + &Finish + 完成(&F) + + + + Cancel + 取消 + + + + &Help + 說明(&H) + + + + &Next + 下一個(&N) + + + + &Next > + 下一個(&N)> + + + + QWorkspace + + + &Restore + 回復(&R) + + + + &Move + 移動(&M) + + + + &Size + 大小(&S) + + + + Mi&nimize + 最小化(&N) + + + + Ma&ximize + 最大化(&X) + + + + &Close + 關閉(&C) + + + + Stay on &Top + 留在頂端(&T) + + + + + Sh&ade + 遮蔽(&A) + + + + + %1 - [%2] + %1 - [%2] + + + + Minimize + 最小化 + + + + Restore Down + 向下恢復 + + + + Close + 關閉 + + + + &Unshade + 取消遮蔽(&U) + + + + QXml + + + no error occurred + 沒有發生錯誤 + + + + error triggered by consumer + 用戶觸發的錯誤 + + + + unexpected end of file + 未預期遇到檔案結尾 + + + + more than one document type definition + 定義了一個以上的文件型態 + + + + error occurred while parsing element + 剖析元素時發生錯誤 + + + + tag mismatch + 標籤不對稱 + + + + error occurred while parsing content + 剖析內容時發生錯誤 + + + + unexpected character + 非預期的字元 + + + + invalid name for processing instruction + 處理指令時的不合法名稱 + + + + version expected while reading the XML declaration + 讀取 XML 宣告時應有版本號 + + + + wrong value for standalone declaration + 獨立宣告時的值錯誤 + + + + encoding declaration or standalone declaration expected while reading the XML declaration + 讀取 XML 宣告時應有編碼宣告或獨立宣告 + + + + standalone declaration expected while reading the XML declaration + 讀取 XML 宣告時應有讀立宣告 + + + + error occurred while parsing document type definition + 剖析文件型態定義時發生錯誤 + + + + letter is expected + 預期應為字母 + + + + error occurred while parsing comment + 剖析註解時發生錯誤 + + + + error occurred while parsing reference + 剖析參考時發生錯誤 + + + + internal general entity reference not allowed in DTD + 在 DTD 中不允許內部產生的實體參考 + + + + external parsed general entity reference not allowed in attribute value + 在屬性值中不允許使用外部剖析的實體參考 + + + + external parsed general entity reference not allowed in DTD + 在 DTD 中不允許使用外部剖析的實體參考 + + + + unparsed entity reference in wrong context + 在錯誤的內文中有未剖析的實體參考 + + + + recursive entities + 遞迴的實體 + + + + error in the text declaration of an external entity + 在外部實體中的文字宣告有錯誤 + + + + QXmlStream + + + + Extra content at end of document. + 文件尾端有多餘的內容。 + + + + Invalid entity value. + 不合法的實體值 + + + + Invalid XML character. + 不合法的 XML 字元。 + + + + Sequence ']]>' not allowed in content. + 在內文中不允許有序列 "]]>"。 + + + + Namespace prefix '%1' not declared + 命名空間的前置字串 %1 未宣告 + + + + Attribute redefined. + 屬性重定義。 + + + + Unexpected character '%1' in public id literal. + 在公開代碼字元中遇到非預期的字元 %1。 + + + + Invalid XML version string. + 不合法的 XML 版本字串。 + + + + Unsupported XML version. + 未支援的 XML 版本。 + + + + %1 is an invalid encoding name. + %1 為不合法的編碼名稱。 + + + + Encoding %1 is unsupported + 編碼 %1 不支援。 + + + Invalid XML encoding name. + 不合法的 XML 編碼名稱。 + + + + Standalone accepts only yes or no. + 獨立實體只接受 yes 或 no。 + + + + Invalid attribute in XML declaration. + XML 宣告中有不合法的屬性。 + + + + Premature end of document. + 文件結尾不正確。 + + + + Invalid document. + 不合法的文件。 + + + + Expected + 預期應為 + + + + , but got ' + ,但是看到的是 + + + + Unexpected ' + 非預期 + + + + Expected character data. + 預期的字元資料。 + + + + Recursive entity detected. + 偵測到遞迴實體。 + + + + Start tag expected. + 預期應有開始標籤。 + + + + XML declaration not at start of document. + XML 宣告沒有在文件開始處。 + + + + NDATA in parameter entity declaration. + 在參數實體宣告有 NDATA。 + + + + %1 is an invalid processing instruction name. + %1 是不合法的處理指令名稱。 + + + + Invalid processing instruction name. + 不合法的處理指令名稱。 + + + + + + + Illegal namespace declaration. + 不合法的命名空間宣告。 + + + + Invalid XML name. + 不合法的 XML 名稱。 + + + + Opening and ending tag mismatch. + 開啟與結束的標籤不對稱。 + + + + Reference to unparsed entity '%1'. + 參考到未剖析的實體 %1。 + + + + + + Entity '%1' not declared. + 實體 %1 未宣告。 + + + + Reference to external entity '%1' in attribute value. + 在屬性值中參考到外部實體 %1。 + + + + Invalid character reference. + 不合法的字元參考。 + + + + + Encountered incorrectly encoded content. + 遇到不正確的編碼內容。 + + + + The standalone pseudo attribute must appear after the encoding. + 獨立的虛擬屬性必須在編碼之後出現。 + + + + %1 is an invalid PUBLIC identifier. + %1 為不合法的 PUBLIC 識別子。 + + + + QtXmlPatterns + + + An %1-attribute with value %2 has already been declared. + 已宣告屬性 %1 的值為 %2。 + + + + An %1-attribute must have a valid %2 as value, which %3 isn't. + 屬性 %1 必須以合法的 %2 為值,而 %3 是不合法的。 + + + + Network timeout. + 網路逾時。 + + + + Element %1 can't be serialized because it appears outside the document element. + 元素 %1 無法序列化,因為似乎是在文件元素之外。 + + + Attribute element %1 can't be serialized because it appears at the top level. + 屬性元素 %1 無法序列化,因為似乎是在頂層。 + + + + Year %1 is invalid because it begins with %2. + 年份 %1 不合法,因為是從 %2 開始的。 + + + + Day %1 is outside the range %2..%3. + 日期 %1 已超出 %2 到 %3 的範圍。 + + + + Month %1 is outside the range %2..%3. + 月份 %1 已超出 %2 到 %3 的範圍。 + + + + Overflow: Can't represent date %1. + 溢位:無法表示日期 %1。 + + + + Day %1 is invalid for month %2. + 月份 %2 中沒有日期 %1。 + + + + Time 24:%1:%2.%3 is invalid. Hour is 24, but minutes, seconds, and milliseconds are not all 0; + 時間 24:%1:%2.%3 不合法。小時為 24 則分、秒與毫秒都必須是 0。 + + + + + Time %1:%2:%3.%4 is invalid. + 時間 %1:%2:%3.%4 不合法。 + + + + Overflow: Date can't be represented. + 溢位:無法表示日期。 + + + + + At least one component must be present. + 必須表達至少一個組件。 + + + + At least one time component must appear after the %1-delimiter. + 在分隔符 %1 後必須至少有一個時間組件。 + + + + No operand in an integer division, %1, can be %2. + 整數除法沒有運作對象,%1,可以是 %2 + + + + The first operand in an integer division, %1, cannot be infinity (%2). + 整數除法的第一個運算對象 %1 不能是無限大(%2)。 + + + + The second operand in a division, %1, cannot be zero (%2). + 整數除法的第二個運算對象 %1 不能是零(%2)。 + + + + %1 is not a valid value of type %2. + %1 不是合法的 %2 型態的值。 + + + + When casting to %1 from %2, the source value cannot be %3. + 從 %2 轉換型態為 %1 的時候,來源數值不能是 %3。 + + + + Integer division (%1) by zero (%2) is undefined. + 整數除法 %1 除以零(%2)的行為未定義。 + + + + Division (%1) by zero (%2) is undefined. + 除法 %1 除以零(%2)的行為未定義。 + + + + Modulus division (%1) by zero (%2) is undefined. + 餘數除法 %1 除以零(%2)的行為未定義。 + + + + + Dividing a value of type %1 by %2 (not-a-number) is not allowed. + 將型態 %1 除以 %2(非數值)是不允許的。 + + + + Dividing a value of type %1 by %2 or %3 (plus or minus zero) is not allowed. + 將型態 %1 除以 %2 或 %3(正或負零)是不允許的。 + + + + Multiplication of a value of type %1 by %2 or %3 (plus or minus infinity) is not allowed. + 將型態 %1 乘以 %2 或 %3(正或負無限大)是不允許的。 + + + + A value of type %1 cannot have an Effective Boolean Value. + 型態 %1 不能有實際布林值。 + + + + Effective Boolean Value cannot be calculated for a sequence containing two or more atomic values. + 實際布林值(Effective Boolean)無法用在兩個或兩個以上的原數值(atomic value)的計算。 + + + + Value %1 of type %2 exceeds maximum (%3). + 型態 %2 的數值 %1 已超過最大值(%3)。 + + + + Value %1 of type %2 is below minimum (%3). + 型態 %2 的數值 %1 已低過最小值(%3)。 + + + + A value of type %1 must contain an even number of digits. The value %2 does not. + 型態 %1 的值必須包含偶數個數字。數值 %2 未符合此條件。 + + + + %1 is not valid as a value of type %2. + %1 不是合法的 %2 型態的值。 + + + + Operator %1 cannot be used on type %2. + 操作元 %1 不能用於型態 %2。 + + + + Operator %1 cannot be used on atomic values of type %2 and %3. + 操作元 %1 不能用於型態 %2 與 %3 的原數值。 + + + + The namespace URI in the name for a computed attribute cannot be %1. + 在已計算屬性的名稱的命名空間網址不能是 %1。 + + + + The name for a computed attribute cannot have the namespace URI %1 with the local name %2. + 在已計算屬性的名稱不能同時有命名空間網址 %1 與本地端名稱 %2。 + + + + Type error in cast, expected %1, received %2. + 轉換型態錯誤,應為 %1 但接收到 %2。 + + + + When casting to %1 or types derived from it, the source value must be of the same type, or it must be a string literal. Type %2 is not allowed. + 轉換為型態 %1 或其衍生型態時,來源數值必須是相同型態,或者是字串。型態 %2 是不被允許的。 + + + + No casting is possible with %1 as the target type. + 不能轉換到 %1 型態。 + + + + It is not possible to cast from %1 to %2. + 不能從 %1 轉換到 %2。 + + + + Casting to %1 is not possible because it is an abstract type, and can therefore never be instantiated. + 無法轉換到 %1 因為它是一個抽象型態,不能被實體化。 + + + + It's not possible to cast the value %1 of type %2 to %3 + 無法轉換型態 %2 的數值 %1 到 %3 + + + + Failure when casting from %1 to %2: %3 + 從 %1 轉換到 %2 時失敗:%3 + + + + A comment cannot contain %1 + 註解不能包含 %1 + + + + A comment cannot end with a %1. + 註解不能以 %1 做結尾 + + + + No comparisons can be done involving the type %1. + 包含型態 %1 時不能做比較。 + + + + Operator %1 is not available between atomic values of type %2 and %3. + 操作元 %1 不能用於型態 %2 與 %3 的原數值。 + + + + An attribute node cannot be a child of a document node. Therefore, the attribute %1 is out of place. + 屬性點不能做為文件點的子節點。因此,屬性 %1 的位置不合適。 + + + + A library module cannot be evaluated directly. It must be imported from a main module. + 不能直接計算函式模組。必須要從主模組匯入。 + + + + No template by name %1 exists. + 沒有名為 %1 的樣本存在。 + + + + A value of type %1 cannot be a predicate. A predicate must have either a numeric type or an Effective Boolean Value type. + 型態 %1 的值不能是謂詞(predicate)。謂詞必須是數值型態,或是實際布林值。 + + + + A positional predicate must evaluate to a single numeric value. + 位置謂詞必須能計算出單一的數值。 + + + + The target name in a processing instruction cannot be %1 in any combination of upper and lower case. Therefore, is %2 invalid. + 處理指令的目標名稱不能是任何大小寫組合的 %1。因此,%2 是不合法的值。 + + + + %1 is not a valid target name in a processing instruction. It must be a %2 value, e.g. %3. + %1 不是一個合法的處理指令的目標名稱。必須是 %2 的值,例如 %3。 + + + + The last step in a path must contain either nodes or atomic values. It cannot be a mixture between the two. + 路徑的最後一步必須是節點或原值,而不能在兩者之間。 + + + + The data of a processing instruction cannot contain the string %1 + 處理指令的資料不能包含字串 %1 + + + + No namespace binding exists for the prefix %1 + 前置字串 %1 沒有結合命名空間 + + + + No namespace binding exists for the prefix %1 in %2 + 在 %2 的前置字串 %1 沒有結合命名空間 + + + + + %1 is an invalid %2 + %1 是不合法的 %2 + + + + %1 takes at most %n argument(s). %2 is therefore invalid. + + %1 最多只能有 %n 個參數,因此 %2 是不合法的。 + + + + + %1 requires at least %n argument(s). %2 is therefore invalid. + + %1 至少需要 %n 個參數,因此 %2 是不合法的。 + + + + + The first argument to %1 cannot be of type %2. It must be a numeric type, xs:yearMonthDuration or xs:dayTimeDuration. + 呼叫 %1 的第一個參數不能是 %2 型態。必須是數值型態,xs.yearMonthDuration 或 xs.dayTimeDuration。 + + + + The first argument to %1 cannot be of type %2. It must be of type %3, %4, or %5. + 呼叫 %1 的第一個參數不能是 %2 型態。必須是 %3、%4 或 %5 型態。 + + + + The second argument to %1 cannot be of type %2. It must be of type %3, %4, or %5. + 呼叫 %1 的第二個參數不能是 %2 型態。必須是 %3、%4 或 %5 型態。 + + + + %1 is not a valid XML 1.0 character. + %1 不是合法的 XML 1.0 字元。 + + + + The first argument to %1 cannot be of type %2. + 呼叫 %1 的第一個參數不能是 %2 型態。 + + + + If both values have zone offsets, they must have the same zone offset. %1 and %2 are not the same. + 如果兩個值都有區域位移,則必須是相同的區域位移。%1 與 %2 並不相同。 + + + + %1 was called. + %1 已被呼叫。 + + + + %1 must be followed by %2 or %3, not at the end of the replacement string. + %1 後面必須跟著 %2 或 %3,而非取代字串的結尾。 + + + + In the replacement string, %1 must be followed by at least one digit when not escaped. + 在取代字串中,在未脫逸的情形下 %1 必須至少跟著一位數字。 + + + + In the replacement string, %1 can only be used to escape itself or %2, not %3 + 在取代字串中,%1 只能用於自身或 %2 的脫逸,而非 %3。 + + + + %1 matches newline characters + %1 符合了換行字元 + + + + %1 and %2 match the start and end of a line. + %1 與 %2 符合了一行的開始與結尾。 + + + + Matches are case insensitive + 比對為區分大小寫 + + + + Whitespace characters are removed, except when they appear in character classes + 空白字元已移除,除非它們出現在字元類別 + + + + %1 is an invalid regular expression pattern: %2 + %1 是不合法的正規表示式樣式:%2 + + + + %1 is an invalid flag for regular expressions. Valid flags are: + %1 是正規表示式中不合法的旗標。合法的旗標有: + + + + If the first argument is the empty sequence or a zero-length string (no namespace), a prefix cannot be specified. Prefix %1 was specified. + 如果第一個參數是空序列,或是長度為 0 的字串(沒有命名空間),則無法指定前置字串。但是您指定了 %1。 + + + + It will not be possible to retrieve %1. + 無法取得 %1。 + + + + The root node of the second argument to function %1 must be a document node. %2 is not a document node. + 函式 %1 的第二個參數的根節點必須是文件節點。%2 不是文件節點。 + + + + The default collection is undefined + 預設的收藏未定義 + + + + %1 cannot be retrieved + %1 無法取得 + + + + The normalization form %1 is unsupported. The supported forms are %2, %3, %4, and %5, and none, i.e. the empty string (no normalization). + 未支援常態化表單 %1。支援的表單有 %2、%3、%4、%5,以及無(也就是空字串,未常態化)。 + + + + A zone offset must be in the range %1..%2 inclusive. %3 is out of range. + 區域位移必須是在 %1 到 %2 範圍之內。%3 已超出範圍。 + + + + %1 is not a whole number of minutes. + %1 不是分鐘的數值。 + + + + Required cardinality is %1; got cardinality %2. + 需要的基數為 %1;得到的是 %2。 + + + + The item %1 did not match the required type %2. + 項目 %1 未符合需要的型態 %2。 + + + + + %1 is an unknown schema type. + %1 是未知的機制型態。 + + + + Only one %1 declaration can occur in the query prolog. + 只有一個 %1 宣告可以在查詢中。 + + + + The initialization of variable %1 depends on itself + 變數 %1 的初始化與自身相依。 + + + + No variable by name %1 exists + 沒有名為 %1 的變數存在 + + + + The variable %1 is unused + 變數 %1 未使用 + + + + Version %1 is not supported. The supported XQuery version is 1.0. + 版本 %1 未支援。支援的 XQuery 版本為 1.0。 + + + + The encoding %1 is invalid. It must contain Latin characters only, must not contain whitespace, and must match the regular expression %2. + 編碼 %1 不合法。必須只能包含拉丁字元,不含空白,並且要符合正規表示式 %2。 + + + + No function with signature %1 is available + 沒有簽章為 %1 的函式可使用 + + + + + A default namespace declaration must occur before function, variable, and option declarations. + 預設的命名空間宣告必須在函式、變數與選項宣告之前。 + + + + Namespace declarations must occur before function, variable, and option declarations. + 命名空間宣告必須在函式、變數與選項宣告之前。 + + + + Module imports must occur before function, variable, and option declarations. + 模組匯入必須在函式、變數與選項宣告之前。 + + + + It is not possible to redeclare prefix %1. + 無法重宣告前置字串 %1。 + + + Only the prefix %1 can be declared to bind the namespace %2. By default, it is already bound to the prefix %1. + 只有前置字串 %1 可以被宣告與命名空間 %2 結合。它預設已經與前置字串 %1 結合。 + + + + Prefix %1 is already declared in the prolog. + 前置字串 %1 已在 prolog 中宣告。 + + + + The name of an option must have a prefix. There is no default namespace for options. + 選項名稱必須有前置字串。沒有選項的預設命名空間。 + + + + The Schema Import feature is not supported, and therefore %1 declarations cannot occur. + 機制匯入功能未支援,因此有 %1 個宣告無法達成。 + + + + The target namespace of a %1 cannot be empty. + %1 的目標命名空間不能是空的。 + + + + The module import feature is not supported + 模組匯入功能未支援。 + + + A variable by name %1 has already been declared in the prolog. + 名稱為 %1 的變數已經在 prolog 中宣告。 + + + + No value is available for the external variable by name %1. + 名為 %1 的外部變數沒有可用的值。 + + + The namespace for a user defined function cannot be empty(try the predefined prefix %1 which exists for cases like this) + 使用者定義的函式的命名空間不能是空的(請試試使用預定義前置字串 %1) + + + + A construct was encountered which only is allowed in XQuery. + 遇到了建構,實際上只能允許在 XQuery 內。 + + + + A template by name %1 has already been declared. + 名為 %1 的屬性已被宣告。 + + + + The keyword %1 cannot occur with any other mode name. + 關鍵字 %1 不能與任何其它模式名稱一起存在。 + + + + The value of attribute %1 must of type %2, which %3 isn't. + 屬性 %1 的值必須為型態 %2,但 %3 不是。 + + + + The prefix %1 can not be bound. By default, it is already bound to the namespace %2. + 前置字串 %1 不能被結合。預設它已與命名空間 %2 結合。 + + + + A variable by name %1 has already been declared. + 名為 %1 的變數已被宣告。 + + + + A stylesheet function must have a prefixed name. + 樣式表函式必須有前置名稱。 + + + + The namespace for a user defined function cannot be empty (try the predefined prefix %1 which exists for cases like this) + 使用者定義函式的命名空間不能為空白(請試著用預先定義的前置字串 %1) + + + + The namespace %1 is reserved; therefore user defined functions may not use it. Try the predefined prefix %2, which exists for these cases. + 命名空間 %1 已被保留,因此使用者定義函式不能使用它。請試試預定義前置字串 %2。 + + + + The namespace of a user defined function in a library module must be equivalent to the module namespace. In other words, it should be %1 instead of %2 + 在函式模組中的使用者定義函式的命名空間必須與模組的命名空間相同。也就是,應該為 %1 而不是 %2。 + + + + A function already exists with the signature %1. + 已經有簽章為 %1 的函式存在。 + + + + No external functions are supported. All supported functions can be used directly, without first declaring them as external + 未支援外部函式。所有支援的含式可以直接使用而不需要先宣告為外部函式。 + + + + An argument by name %1 has already been declared. Every argument name must be unique. + 名稱為 %1 的參數已被宣告。每個參數名稱必須唯一。 + + + + When function %1 is used for matching inside a pattern, the argument must be a variable reference or a string literal. + 當函式 %1 用於樣式比對時,參數必須是變數參考或字串。 + + + + In an XSL-T pattern, the first argument to function %1 must be a string literal, when used for matching. + 在 XSL-T 樣式內,函式 %1 的第一個參數必須是字串,以便用於比對。 + + + + In an XSL-T pattern, the first argument to function %1 must be a literal or a variable reference, when used for matching. + 在 XSL-T 樣式內,函式 %1 的第一個參數必須是文字或變數參考,以便用於比對。 + + + + In an XSL-T pattern, function %1 cannot have a third argument. + 在 XSL-T 樣式內,函式 %1 的不能有第三個參數。 + + + + In an XSL-T pattern, only function %1 and %2, not %3, can be used for matching. + 在 XSL-T 樣式內,只有函式 %1,%2 可以用於比對。%3 不行。 + + + + In an XSL-T pattern, axis %1 cannot be used, only axis %2 or %3 can. + 在 XSL-T 樣式內,不能用 %1 軸,只能用 %2 或 %3。 + + + + %1 is an invalid template mode name. + %1 不是合法的樣本模式名稱。 + + + + The name of a variable bound in a for-expression must be different from the positional variable. Hence, the two variables named %1 collide. + 與 for 敘述結合的變數名稱必須與位置變數不同。因此,有兩個名為 %1 的變數衝突了。 + + + + The Schema Validation Feature is not supported. Hence, %1-expressions may not be used. + 未支援機制確認功能。%1 敘述無法使用。 + + + + None of the pragma expressions are supported. Therefore, a fallback expression must be present + 未支援 pragma 敘述。因次,必須有預設的敘述。 + + + + Each name of a template parameter must be unique; %1 is duplicated. + 每個樣本參數的名稱必須唯一;%1 已經被使用。 + + + + The %1-axis is unsupported in XQuery + XQuery 中未支援 %1 軸 + + + + %1 is not a valid name for a processing-instruction. + %1 不是處理指令的合法名稱。 + + + + %1 is not a valid numeric literal. + %1 不是合法的數值。 + + + + No function by name %1 is available. + 沒有名為 %1 的函式。 + + + + The namespace URI cannot be the empty string when binding to a prefix, %1. + 要與前置字串 %1 結合的命名空間網址不能是空字串。 + + + + %1 is an invalid namespace URI. + %1 是不合法的命名空間網址。 + + + + It is not possible to bind to the prefix %1 + 無法與前置字串 %1 結合。 + + + + Namespace %1 can only be bound to %2 (and it is, in either case, pre-declared). + 命名空間 %1 只能與 %2 結合(也就是說,要預先定義)。 + + + + Prefix %1 can only be bound to %2 (and it is, in either case, pre-declared). + 前置字串 %1 只能與 %2 結合(也就是說,要預先定義)。 + + + + Two namespace declaration attributes have the same name: %1. + 有兩個命名空間宣告的屬性有相同的名稱:%1 + + + + The namespace URI must be a constant and cannot use enclosed expressions. + 命名空間網址必須是常數,並且不能使用封閉敘述。 + + + + An attribute by name %1 has already appeared on this element. + 名為 %1 的屬性已出現在此元素。 + + + + A direct element constructor is not well-formed. %1 is ended with %2. + 直接元素建構器沒有完整產生。%1 以 %2 結束。 + + + + The name %1 does not refer to any schema type. + 名稱 %1 未指向任何機制型態。 + + + + %1 is an complex type. Casting to complex types is not possible. However, casting to atomic types such as %2 works. + %1 是複數型態,無法轉換成複數型態。然而,轉換為原型態,如 %2 是可行的。 + + + + %1 is not an atomic type. Casting is only possible to atomic types. + %1 不是一個原型態。只能轉換為原型態。 + + + %1 is not a valid name for a processing-instruction. Therefore this name test will never match. + %1 不是一個合法的處理指令的名稱。因此名稱測試永遠不會成功。 + + + + + %1 is not in the in-scope attribute declarations. Note that the schema import feature is not supported. + %1 不是範圍內屬性宣告。注意機制匯入功能未支援。 + + + + The name of an extension expression must be in a namespace. + 延伸敘述的名稱必須在命名空間內。 + + + + empty + 空白 + + + + zero or one + 0 或 1 個 + + + + exactly one + 剛好一個 + + + + one or more + 一個以上 + + + + zero or more + 0 個以上 + + + + Required type is %1, but %2 was found. + 需要的型態為 %1,但找到 %2。 + + + + Promoting %1 to %2 may cause loss of precision. + 將 %1 抬升為 %2 可能會失去精確度。 + + + + The focus is undefined. + 焦點未定義。 + + + + It's not possible to add attributes after any other kind of node. + 不能在任何其它種類的節點後面加入屬性。 + + + + An attribute by name %1 has already been created. + 名為 %1 的屬性已被建立。 + + + + Only the Unicode Codepoint Collation is supported(%1). %2 is unsupported. + 只支援 Unicode Codepoint Collation(%1)。%2 未支援。; + + + + Attribute %1 can't be serialized because it appears at the top level. + 屬性元素 %1 無法序列化,因為似乎是在頂層。 + + + + %1 is an unsupported encoding. + %1 是個未被支援的編碼。 + + + + %1 contains octets which are disallowed in the requested encoding %2. + %1 包含了在要求的編碼 %2 內不允許的八進位值。 + + + + The codepoint %1, occurring in %2 using encoding %3, is an invalid XML character. + 在 %2 內的代碼點 %1(編碼 %3)是一個不合法的 XML 字元。 + + + + Ambiguous rule match. + 不明確的規則符合。 + + + In a namespace constructor, the value for a namespace value cannot be an empty string. + 在命名空間建構子中,命名空間的值不能是空字串。 + + + + In a namespace constructor, the value for a namespace cannot be an empty string. + + + + + The prefix must be a valid %1, which %2 is not. + 前置字串必須是合法的 %1,但 %2 不是。 + + + + The prefix %1 cannot be bound. + 前置字串 %1 不能被結合。 + + + + Only the prefix %1 can be bound to %2 and vice versa. + 只有前置字串 %1 能與 %2 結合。反之亦然。 + + + + Circularity detected + 偵測到環狀 + + + + The parameter %1 is required, but no corresponding %2 is supplied. + 需要參數 %1,但是沒有提供相關的 %2。 + + + + The parameter %1 is passed, but no corresponding %2 exists. + 參數 %1 已傳送,但找不到相關的 %2。 + + + + The URI cannot have a fragment + URI 不能有片段。 + + + + Element %1 is not allowed at this location. + 元素 %1 不能在此位置。 + + + + Text nodes are not allowed at this location. + 文字節點不能在此位置。 + + + + Parse error: %1 + 剖析錯誤:%1 + + + + The value of the XSL-T version attribute must be a value of type %1, which %2 isn't. + XLS-T 版本屬性的值必須是型態 %1 的值,而 %2 不是。 + + + + Running an XSL-T 1.0 stylesheet with a 2.0 processor. + 使用 2.0 處理器執行 XSL-T 1.0 樣式表中。 + + + + Unknown XSL-T attribute %1. + 未知的 XSL-T 屬性 %1。 + + + + Attribute %1 and %2 are mutually exclusive. + 屬性 %1 與 %2 彼此互斥。 + + + + In a simplified stylesheet module, attribute %1 must be present. + 在簡化的樣式表模組中,屬性 %1 必須存在。 + + + + If element %1 has no attribute %2, it cannot have attribute %3 or %4. + 若元素 %1 沒有屬性 %2,則也不能有屬性 %3 或 %4。 + + + + Element %1 must have at least one of the attributes %2 or %3. + 元素 %1 必須至少有屬性 %2 或 %3 其中一個。 + + + + At least one mode must be specified in the %1-attribute on element %2. + 在元素 %2 的 %1 屬性中至少要指定一個模式。 + + + + Attribute %1 cannot appear on the element %2. Only the standard attributes can appear. + 屬性 %1 不能出現在元素 %2。只能有標準屬性。 + + + + Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes. + 屬性 %1 不能出現在元素 %2。只能有 %3 以及標準屬性。 + + + + Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes. + 屬性 %1 不能出現在元素 %2。只能有 %3,%4 以及標準屬性。 + + + + Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes. + 屬性 %1 不能出現在元素 %2。只能有 %3 以及標準屬性。 + + + + XSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is. + XSL-T 元素內的 XSL-T 屬性必須放在空(null)的命名空間,而不是像 %1 在 XSL-T 命名空間。 + + + + The attribute %1 must appear on element %2. + 屬性 %1 必須在元素 %2 內出現。 + + + + The element with local name %1 does not exist in XSL-T. + 有本地名稱 %1 的元素在 XSL-T 內不存在。 + + + + Element %1 must come last. + 元素 %1 必須最後出現。 + + + + At least one %1-element must occur before %2. + 至少一個元素 %1 要出現在 %2 之前。 + + + + Only one %1-element can appear. + 只能出現一個元素 %1。 + + + + At least one %1-element must occur inside %2. + 至少一個元素 %1 要出現在 %2 之內。 + + + + When attribute %1 is present on %2, a sequence constructor cannot be used. + 當屬性 %1 出現在 %2 內時,不能使用序列建構子。 + + + + Element %1 must have either a %2-attribute or a sequence constructor. + 元素 %1 必須至少有一個屬性 %2 或一個序列建構子。 + + + + When a parameter is required, a default value cannot be supplied through a %1-attribute or a sequence constructor. + 當需要參數時,不能透過屬性 %1 或序列建構子提供預設值。 + + + + Element %1 cannot have children. + 元素 %1 不能有子元素。 + + + + Element %1 cannot have a sequence constructor. + 元素 %1不能有序列建構子。 + + + + + The attribute %1 cannot appear on %2, when it is a child of %3. + 屬性 %1 不能出現在 %2,因為它是 %3 的子元素。 + + + + A parameter in a function cannot be declared to be a tunnel. + 函式內的參數不能被宣告為通道(tunnel)。 + + + + This processor is not Schema-aware and therefore %1 cannot be used. + 此處理器不是 Schema-aware,因此不能使用 %1。 + + + + Top level stylesheet elements must be in a non-null namespace, which %1 isn't. + 頂層樣式表元素必須是非空白的命名空間,而 %1 不是。 + + + + The value for attribute %1 on element %2 must either be %3 or %4, not %5. + 元素 %2 內屬性 %1 的值必須是 %3 或 %4,而不是 %5。 + + + + Attribute %1 cannot have the value %2. + 屬性 %1 的值不能為 %2。 + + + + The attribute %1 can only appear on the first %2 element. + 屬性 %1 只能出現在前 %2 個元素內。 + + + + At least one %1 element must appear as child of %2. + %2 必須至少有一個子元素 %1。 + + + + VolumeSlider + + + Muted + 靜音 + + + + + Volume: %1% + 音量:%1% + + + + WebCore::PlatformScrollbar + + Scroll here + 在此捲軸 + + + Left edge + 左邊緣 + + + Top + 頂端 + + + Right edge + 右邊緣 + + + Bottom + 底端 + + + Page left + 頁面左方 + + + Page up + 頁面上方 + + + Page right + 頁面右方 + + + Page down + 頁面下方 + + + Scroll left + 往左捲軸 + + + Scroll up + 往上捲軸 + + + Scroll right + 往右捲軸 + + + Scroll down + 往下捲軸 + + + diff --git a/verifydetailsdialog.cpp b/verifydetailsdialog.cpp index 55fb567..102dec2 100644 --- a/verifydetailsdialog.cpp +++ b/verifydetailsdialog.cpp @@ -59,9 +59,11 @@ void VerifyDetailsDialog::refresh() //mCtx->preventNoDataErr(&text); gpgme_signature_t sign; if(mInputSignature != 0) { - sign = mCtx->verify(mInputData, mInputSignature); + // TODO: kgpg + //sign = mCtx->verify(mInputData, mInputSignature); } else { - sign = mCtx->verify(mInputData); + //TODO kgpg + //sign = mCtx->verify(mInputData); } if(sign==0) { diff --git a/verifynotification.cpp b/verifynotification.cpp index 1230534..9aa061f 100644 --- a/verifynotification.cpp +++ b/verifynotification.cpp @@ -100,8 +100,14 @@ bool VerifyNotification::refresh() mCtx->preventNoDataErr(&text); int textIsSigned = mCtx->textIsSigned(text); - gpgme_signature_t sign = mCtx->verify(&text); + //gpgme_signature_t sign = mCtx->verify(text); + //KGpgVerify *verify = new KGpgVerify(this, message.mid(posstart, posend - posstart)); + KGpgVerify *verify = new KGpgVerify(this, text); + connect(verify, SIGNAL(done(int)), SLOT(slotVerifyDone(int))); + verify->start(); + + /* if (sign == NULL) { return false; } @@ -180,6 +186,156 @@ bool VerifyNotification::refresh() verifyLabelText.remove(verifyLabelText.length()-1,1); this->setVerifyLabel(verifyLabelText,verifyStatus); - + */ return true; } + +void VerifyNotification::slotVerifyDone(int result) +{ + const KGpgVerify * const verify = qobject_cast(sender()); + sender()->deleteLater(); + Q_ASSERT(verify != NULL); + + if (result == KGpgVerify::TS_MISSING_KEY) { + qDebug() << "missing keys" << verify->missingId(); + this->keysNotInList->append(verify->missingId()); + this->showImportAction(true); + } + + const QStringList messages = verify->getMessages(); + foreach(QString mess, messages) { + qDebug() << "vm: " << mess; + } + + getReport(messages); + /*emit verifyFinished(); + + if (result == KGpgVerify::TS_MISSING_KEY) { + verifyKeyNeeded(verify->missingId()); + return; + } + + const QStringList messages = verify->getMessages(); + + if (messages.isEmpty()) + return; + + QStringList msglist; + foreach (QString rawmsg, messages) + msglist << rawmsg.replace(QLatin1Char('<'), QLatin1String("<")); + + (void) new KgpgDetailedInfo(this, KGpgVerify::getReport(messages, m_model), + msglist.join(QLatin1String("
")), + QStringList(), i18nc("Caption of message box", "Verification Finished")); + */ +} + +QString VerifyNotification::getReport(const QStringList &log) +{ + QString verifyLabelText; + verify_label_status verifyStatus=VERIFY_ERROR_OK; + + QString result; + // newer versions of GnuPG emit both VALIDSIG and GOODSIG + // for a good signature. Since VALIDSIG has more information + // we use that. + const QRegExp validsig(QLatin1String("^\\[GNUPG:\\] VALIDSIG([ ]+[^ ]+){10,}.*$")); + + +// const bool useGoodSig = (model != NULL) && (log.indexOf(validsig) == -1); + const bool useGoodSig = false; + + QString sigtime; // timestamp of signature creation + + foreach (const QString &line, log) { + if (!line.startsWith(QLatin1String("[GNUPG:] "))) + continue; + + const QString msg = line.mid(9); + + if (msg.startsWith(QLatin1String("VALIDSIG ")) && !useGoodSig) { + // from GnuPG source, doc/DETAILS: + // VALIDSIG + // + // + const QStringList vsig = msg.mid(9).split(QLatin1Char(' '), QString::SkipEmptyParts); + Q_ASSERT(vsig.count() >= 10); + + qDebug() << "sig: " << vsig[9]; + + verifyStatus=VERIFY_ERROR_WARN; + verifyLabelText.append(tr("Error for key with fingerprint ")+mCtx->beautifyFingerprint(QString(vsig[9]))); + + + } + } + + this->setVerifyLabel(verifyLabelText,verifyStatus); + /*const KGpgKeyNode *node = model->findKeyNode(vsig[9]); + + if (node != NULL) { + // ignore for now if this is signed with the primary id (vsig[0] == vsig[9]) or not + if (node->getEmail().isEmpty()) + result += tr("Good signature from:
%1
Key ID: %2
") + .arg(node->getName()).arg(vsig[9]); + else + result += tr("Good signature from: NAME , Key ID: HEXID", + "Good signature from:
%1 <%2>
Key ID: %3
") + .arg(node->getName()).arg(node->getEmail()).arg(vsig[9]); + + result += sigTimeMessage(vsig[2]); + } else { + // this should normally never happen, but one could delete + // the key just after the verification. Brute force solution: + // do the whole report generation again, but this time make + // sure GOODSIG is used. + return getReport(log, NULL); + } + } else if (msg.startsWith(QLatin1String("UNEXPECTED")) || + msg.startsWith(QLatin1String("NODATA"))) { + result += tr("No signature found.") + QLatin1Char('\n'); + } else if (useGoodSig && msg.startsWith(QLatin1String("GOODSIG "))) { + int sigpos = msg.indexOf( ' ' , 8); + const QString keyid = msg.mid(8, sigpos - 8); + + // split the name/email pair to give translators more power to handle this + QString email; + QString name = msg.mid(sigpos + 1); + + int oPos = name.indexOf(QLatin1Char('<')); + int cPos = name.indexOf(QLatin1Char('>')); + if ((oPos >= 0) && (cPos >= 0)) { + email = name.mid(oPos + 1, cPos - oPos - 1); + name = name.left(oPos).simplified(); + } + + if (email.isEmpty()) + result += tr("Good signature from:
%1
Key ID: %2
") + .arg(name).arg(keyid); + else + result += tr("Good signature from: NAME , Key ID: HEXID", + "Good signature from:
%1 <%2>
Key ID: %3
") + .arg(name).arg(email).arg(keyid); + if (!sigtime.isEmpty()) { + result += sigTimeMessage(sigtime); + sigtime.clear(); + } + } else if (msg.startsWith(QLatin1String("SIG_ID "))) { + const QStringList parts = msg.simplified().split(QLatin1Char(' ')); + if (parts.count() > 2) + sigtime = parts[2]; + } else if (msg.startsWith(QLatin1String("BADSIG"))) { + int sigpos = msg.indexOf( ' ', 7); + result += tr("BAD signature from:
%1
Key id: %2

The file is corrupted
") + .arg(msg.mid(sigpos + 1).replace(QLatin1Char('<'), QLatin1String("<"))) + .arg(msg.mid(7, sigpos - 7)); + } else if (msg.startsWith(QLatin1String("TRUST_UNDEFINED"))) { + result += tr("The signature is valid, but the key is untrusted
"); + } else if (msg.startsWith(QLatin1String("TRUST_ULTIMATE"))) { + result += tr("The signature is valid, and the key is ultimately trusted
"); + } + } + */ + return result; +} + diff --git a/verifynotification.h b/verifynotification.h index e1b4f1b..6f34f47 100644 --- a/verifynotification.h +++ b/verifynotification.h @@ -24,6 +24,7 @@ #include "editorpage.h" #include "verifydetailsdialog.h" +#include "kgpg/transactions/kgpgverify.h" #include #include @@ -75,6 +76,8 @@ public: QStringList *keysNotInList; /** List with keys, which are in signature but not in keylist */ + QString getReport(const QStringList &log); + public slots: /** @@ -93,6 +96,8 @@ public slots: */ bool refresh(); + void slotVerifyDone(int result); + private: QMenu *detailMenu; /** Menu for te Button in verfiyNotification */ QAction *importFromKeyserverAct; /** Action for importing keys from keyserver which are notin keylist */ -- cgit v1.2.3