00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kgpgview.h"
00019
00020 #include <QDragEnterEvent>
00021 #include <QVBoxLayout>
00022 #include <QTextStream>
00023 #include <QDropEvent>
00024 #include <QMimeData>
00025 #include <QFile>
00026
00027 #include <KDialogButtonBox>
00028 #include <kio/netaccess.h>
00029 #include <KMessageBox>
00030 #include <KLocale>
00031 #include <KAction>
00032
00033 #include "selectsecretkey.h"
00034 #include "kgpgsettings.h"
00035 #include "kgpginterface.h"
00036 #include "keyservers.h"
00037 #include "kgpgeditor.h"
00038 #include "selectpublickeydialog.h"
00039 #include "detailedconsole.h"
00040
00041 #define ENCODEDMESSAGE_BEGIN "-----BEGIN PGP MESSAGE-----"
00042 #define ENCODEDMESSAGE_END "-----END PGP MESSAGE-----"
00043 #define SIGNEDMESSAGE_BEGIN "-----BEGIN PGP SIGNED MESSAGE-----"
00044 #define SIGNEDMESSAGE_END "-----END PGP SIGNATURE-----"
00045 #define PUBLICKEY_BEGIN "-----BEGIN PGP PUBLIC KEY BLOCK-----"
00046 #define PUBLICKEY_END "-----END PGP PUBLIC KEY BLOCK-----"
00047 #define PRIVATEKEY_BEGIN "-----BEGIN PGP PRIVATE KEY BLOCK-----"
00048 #define PRIVATEKEY_END "-----END PGP PRIVATE KEY BLOCK-----"
00049
00050 KgpgTextEdit::KgpgTextEdit(QWidget *parent)
00051 : KTextEdit(parent)
00052 {
00053 setCheckSpellingEnabled(true);
00054 setAcceptDrops(true);
00055 }
00056
00057 KgpgTextEdit::~KgpgTextEdit()
00058 {
00059 deleteFile();
00060 }
00061
00062 void KgpgTextEdit::dragEnterEvent(QDragEnterEvent *e)
00063 {
00064
00065 if (KUrl::List::canDecode(e->mimeData()) || e->mimeData()->hasText())
00066 e->acceptProposedAction();
00067 }
00068
00069 void KgpgTextEdit::dropEvent(QDropEvent *e)
00070 {
00071
00072 KUrl::List uriList = KUrl::List::fromMimeData(e->mimeData());
00073 if (!uriList.isEmpty())
00074 slotDroppedFile(uriList.first());
00075 else
00076 if (e->mimeData()->hasText())
00077 insertPlainText(e->mimeData()->text());
00078 }
00079
00080 void KgpgTextEdit::slotDroppedFile(const KUrl &url)
00081 {
00082 deleteFile();
00083
00084 if (url.isLocalFile())
00085 m_tempfile = url.path();
00086 else
00087 {
00088 if (KMessageBox::warningContinueCancel(this, i18n("<qt><b>Remote file dropped</b>.<br />The remote file will now be copied to a temporary file to process requested operation. This temporary file will be deleted after operation.</qt>"), QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "RemoteFileWarning") != KMessageBox::Continue)
00089 return;
00090
00091 if (!KIO::NetAccess::download(url, m_tempfile, this))
00092 {
00093 KMessageBox::sorry(this, i18n("Could not download file."));
00094 return;
00095 }
00096 }
00097
00098
00099 if (m_tempfile.endsWith(".gpg") || m_tempfile.endsWith(".asc") || m_tempfile.endsWith(".pgp"))
00100 slotDecodeFile();
00101 else
00102 slotCheckFile();
00103 }
00104
00105 void KgpgTextEdit::slotEncode()
00106 {
00107
00108 KgpgSelectPublicKeyDlg *dialog = new KgpgSelectPublicKeyDlg(this, 0, false, KShortcut(QKeySequence(Qt::CTRL + Qt::Key_Home)), true);
00109 if (dialog->exec() == KDialog::Accepted)
00110 {
00111 QStringList options;
00112 if (dialog->getArmor()) options << "--armor";
00113 if (dialog->getUntrusted()) options << "--always-trust";
00114 if (dialog->getHideId()) options << "--throw-keyid";
00115
00116 QString customoptions = dialog->getCustomOptions();
00117 if (!customoptions.isEmpty())
00118 if (KGpgSettings::allowCustomEncryptionOptions())
00119 options << customoptions.split(" ", QString::SkipEmptyParts);
00120
00121 if (KGpgSettings::pgpCompatibility())
00122 options << "--pgp6";
00123
00124 QStringList listkeys;
00125 if (!dialog->getSymmetric())
00126 listkeys = dialog->selectedKeys();
00127
00128 KgpgInterface *interface = new KgpgInterface();
00129 connect(interface, SIGNAL(txtEncryptionFinished(QString, KgpgInterface*)), this, SLOT(slotEncodeUpdate(QString, KgpgInterface*)));
00130 interface->encryptText(toPlainText(), listkeys, options);
00131 }
00132 delete dialog;
00133 }
00134
00135 void KgpgTextEdit::slotDecode()
00136 {
00137 QString startmsg = ENCODEDMESSAGE_BEGIN;
00138 QString endmsg = ENCODEDMESSAGE_END;
00139
00140 QString fullcontent = toPlainText();
00141
00142 m_posstart = fullcontent.indexOf(startmsg);
00143 if (m_posstart == -1)
00144 return;
00145
00146 m_posend = fullcontent.indexOf(endmsg, m_posstart);
00147 if (m_posend == -1)
00148 return;
00149 m_posend += endmsg.length();
00150
00151 KgpgInterface *interface = new KgpgInterface();
00152 connect(interface, SIGNAL(txtDecryptionFinished(QString, KgpgInterface*)), this, SLOT(slotDecodeUpdateSuccess(QString, KgpgInterface*)));
00153 connect(interface, SIGNAL(txtDecryptionFailed(QString, KgpgInterface*)), this, SLOT(slotDecodeUpdateFailed(QString, KgpgInterface*)));
00154 interface->decryptText(fullcontent.mid(m_posstart, m_posend - m_posstart), KGpgSettings::customDecrypt().simplified().split(" ", QString::SkipEmptyParts));
00155 }
00156
00157 void KgpgTextEdit::slotSign()
00158 {
00159 QString signkeyid;
00160
00161 KgpgSelectSecretKey *opts = new KgpgSelectSecretKey(this);
00162 if (opts->exec() == QDialog::Accepted)
00163 signkeyid = opts->getKeyID();
00164 else
00165 {
00166 delete opts;
00167 return;
00168 }
00169
00170 delete opts;
00171
00172 QStringList options = QStringList();
00173 if (KGpgSettings::pgpCompatibility())
00174 options << "--pgp6";
00175
00176 KgpgInterface *interface = new KgpgInterface();
00177 connect(interface, SIGNAL(txtSigningFinished(QString, KgpgInterface*)), this, SLOT(slotSignUpdate(QString, KgpgInterface*)));
00178 interface->signText(toPlainText(), signkeyid, options);
00179 }
00180
00181 void KgpgTextEdit::slotVerify()
00182 {
00183 QString startmsg = QString(SIGNEDMESSAGE_BEGIN);
00184 QString endmsg = QString(SIGNEDMESSAGE_END);
00185
00186 QString fullcontent = toPlainText();
00187
00188 int posstart = fullcontent.indexOf(startmsg);
00189 if (posstart == -1)
00190 return;
00191
00192 int posend = fullcontent.indexOf(endmsg, posstart);
00193 if (posend == -1)
00194 return;
00195 posend += endmsg.length();
00196
00197 KgpgInterface *interface = new KgpgInterface();
00198 connect(interface, SIGNAL(txtVerifyMissingSignature(QString, KgpgInterface*)), this, SLOT(slotVerifyKeyNeeded(QString, KgpgInterface*)));
00199 connect(interface, SIGNAL(txtVerifyFinished(QString, QString, KgpgInterface*)), this, SLOT(slotVerifySuccess(QString, QString, KgpgInterface*)));
00200 interface->verifyText(fullcontent.mid(posstart, posend - posstart));
00201 }
00202
00203 void KgpgTextEdit::deleteFile()
00204 {
00205 if (!m_tempfile.isEmpty())
00206 {
00207 KIO::NetAccess::removeTempFile(m_tempfile);
00208 m_tempfile.clear();
00209 }
00210 }
00211
00212 bool KgpgTextEdit::checkForUtf8(const QString &text)
00213 {
00214
00215 QTextCodec *codec = QTextCodec::codecForLocale();
00216 if (!codec->canEncode(text))
00217 return true;
00218 return false;
00219 }
00220
00221 void KgpgTextEdit::slotDecodeFile()
00222 {
00223
00224 QFile qfile(QFile::encodeName(m_tempfile));
00225 if (!qfile.open(QIODevice::ReadOnly))
00226 {
00227 KMessageBox::sorry(this, i18n("Unable to read file."));
00228 return;
00229 }
00230 qfile.close();
00231
00232 KgpgInterface *interface = new KgpgInterface();
00233 connect(interface, SIGNAL(txtDecryptionFinished(QString, KgpgInterface*)), this, SLOT(slotDecodeFileSuccess(QString, KgpgInterface*)));
00234 connect(interface, SIGNAL(txtDecryptionFailed(QString, KgpgInterface*)), this, SLOT(slotDecodeFileFailed(QString, KgpgInterface*)));
00235 interface->KgpgDecryptFileToText(KUrl(m_tempfile), KGpgSettings::customDecrypt().simplified().split(" ", QString::SkipEmptyParts));
00236 }
00237
00238 bool KgpgTextEdit::slotCheckFile(const bool &checkforpgpmessage)
00239 {
00240 QString result;
00241
00242 QFile qfile(m_tempfile);
00243 if (qfile.open(QIODevice::ReadOnly))
00244 {
00245 QTextStream t(&qfile);
00246 result = t.readAll();
00247 qfile.close();
00248 }
00249
00250 if (result.isEmpty())
00251 return false;
00252
00253 if (checkforpgpmessage && result.startsWith(ENCODEDMESSAGE_BEGIN))
00254 {
00255
00256 slotDecodeFile();
00257 return true;
00258 }
00259
00260 if (result.startsWith(PUBLICKEY_BEGIN) || result.startsWith(PRIVATEKEY_BEGIN))
00261 {
00262
00263 bool ispublickey = false;
00264 QString tmpinfo;
00265 if (result.startsWith(PUBLICKEY_BEGIN))
00266 {
00267 ispublickey = true;
00268 tmpinfo = i18n("<qt>This file is a <b>public</b> key.\nPlease use kgpg key management to import it.</qt>");
00269 }
00270
00271 if (result.startsWith(PRIVATEKEY_BEGIN))
00272 {
00273 ispublickey = false;
00274 tmpinfo = i18n("<qt>This file is a <b>private</b> key.\nPlease use kgpg key management to import it.</qt>");
00275 }
00276
00277 KMessageBox::information(this, tmpinfo);
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 deleteFile();
00293 return true;
00294 }
00295
00296 setPlainText(result);
00297 deleteFile();
00298 emit newText();
00299 return false;
00300 }
00301
00302 void KgpgTextEdit::slotDecodeFileSuccess(const QString &content, KgpgInterface *interface)
00303 {
00304 delete interface;
00305 setPlainText(content);
00306 emit newText();
00307 }
00308
00309 void KgpgTextEdit::slotDecodeFileFailed(const QString &content, KgpgInterface *interface)
00310 {
00311 delete interface;
00312 if (!slotCheckFile(false))
00313 KMessageBox::detailedSorry(this, i18n("Decryption failed."), content);
00314 }
00315
00316 void KgpgTextEdit::slotEncodeUpdate(const QString &content, KgpgInterface *interface)
00317 {
00318 delete interface;
00319 if (!content.isEmpty())
00320 {
00321 setPlainText(content);
00322 emit newText();
00323 }
00324 else
00325 KMessageBox::sorry(this, i18n("Encryption failed."));
00326 }
00327
00328 void KgpgTextEdit::slotDecodeUpdateSuccess(const QString &content, KgpgInterface *interface)
00329 {
00330 delete interface;
00331
00332 QString decryptedcontent;
00333 if (checkForUtf8(content))
00334 {
00335 decryptedcontent = QString::fromUtf8(content.toAscii());
00336 emit resetEncoding(true);
00337 }
00338 else
00339 {
00340 decryptedcontent = content;
00341 emit resetEncoding(false);
00342 }
00343
00344 QString fullcontent = toPlainText();
00345 fullcontent.replace(m_posstart, m_posend - m_posstart, decryptedcontent);
00346 setPlainText(fullcontent);
00347
00348 emit newText();
00349 }
00350
00351 void KgpgTextEdit::slotDecodeUpdateFailed(const QString &content, KgpgInterface *interface)
00352 {
00353 delete interface;
00354 KMessageBox::detailedSorry(this, i18n("Decryption failed."), content);
00355 }
00356
00357 void KgpgTextEdit::slotSignUpdate(const QString &content, KgpgInterface *interface)
00358 {
00359 delete interface;
00360 if (content.isEmpty())
00361 {
00362 KMessageBox::sorry(this, i18n("Signing not possible: bad passphrase or missing key"));
00363 return;
00364 }
00365
00366 if (checkForUtf8(content))
00367 {
00368 setPlainText(QString::fromUtf8(content.toAscii()));
00369 emit resetEncoding(true);
00370 }
00371 else
00372 {
00373 setPlainText(content);
00374 emit resetEncoding(false);
00375 }
00376
00377 emit newText();
00378 }
00379
00380 void KgpgTextEdit::slotVerifySuccess(const QString &content, const QString &log, KgpgInterface *interface)
00381 {
00382 delete interface;
00383 emit verifyFinished();
00384 (void) new KgpgDetailedInfo(this, content, log);
00385 }
00386
00387 void KgpgTextEdit::slotVerifyKeyNeeded(const QString &id, KgpgInterface *interface)
00388 {
00389 delete interface;
00390
00391 KGuiItem importitem = KStandardGuiItem::yes();
00392 importitem.setText(i18n("&Import"));
00393 importitem.setToolTip(i18n("Import key in your list"));
00394
00395 KGuiItem noimportitem = KStandardGuiItem::no();
00396 noimportitem.setText(i18n("Do &Not Import"));
00397 noimportitem.setToolTip(i18n("Will not import this key in your list"));
00398
00399 if (KMessageBox::questionYesNo(this, i18n("<qt><b>Missing signature:</b><br />Key id: %1<br /><br />Do you want to import this key from a keyserver?</qt>", id), i18n("Missing Key"), importitem, noimportitem) == KMessageBox::Yes)
00400 {
00401 KeyServer *kser = new KeyServer(0, false, true);
00402 kser->slotSetText(id);
00403 kser->slotImport();
00404 }
00405 else
00406 emit verifyFinished();
00407 }
00408
00409
00410
00411
00412
00413
00414 KgpgView::KgpgView(QWidget *parent)
00415 : QWidget(parent)
00416 {
00417 editor = new KgpgTextEdit(this);
00418 editor->setReadOnly(false);
00419 editor->setUndoRedoEnabled(true);
00420
00421 setAcceptDrops(true);
00422
00423 KDialogButtonBox *buttonbox = new KDialogButtonBox(this, Qt::Horizontal);
00424 buttonbox->addButton(i18n("S&ign/Verify"), KDialogButtonBox::ActionRole, this, SLOT(slotSignVerify()));
00425 buttonbox->addButton(i18n("En&crypt"), KDialogButtonBox::ActionRole, this, SLOT(slotEncode()));
00426 buttonbox->addButton(i18n("&Decrypt"), KDialogButtonBox::ActionRole, this, SLOT(slotDecode()));
00427
00428 connect(editor, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
00429 connect(editor, SIGNAL(newText()), this, SIGNAL(newText()));
00430 connect(editor, SIGNAL(resetEncoding(bool)), this, SIGNAL(resetEncoding(bool)));
00431 connect(editor, SIGNAL(verifyFinished()), this, SIGNAL(verifyFinished()));
00432
00433 editor->resize(editor->maximumSize());
00434
00435 QVBoxLayout *vbox = new QVBoxLayout(this);
00436 vbox->setSpacing(3);
00437 vbox->addWidget(editor);
00438 vbox->addWidget(buttonbox);
00439 }
00440
00441 KgpgView::~KgpgView()
00442 {
00443 delete editor;
00444 }
00445
00446 void KgpgView::slotSignVerify()
00447 {
00448 QString mess = editor->toPlainText();
00449 if (mess.contains(SIGNEDMESSAGE_BEGIN))
00450 editor->slotVerify();
00451 else
00452 editor->slotSign();
00453 }
00454
00455 void KgpgView::slotEncode()
00456 {
00457 editor->slotEncode();
00458 }
00459
00460 void KgpgView::slotDecode()
00461 {
00462 editor->slotDecode();
00463 }
00464
00465 void KgpgView::slotHighlightText(const QString &, const int &matchingindex, const int &matchedlength)
00466 {
00467 editor->highlightWord(matchedlength, matchingindex);
00468 }
00469
00470 #include "kgpgview.moc"