Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit e93d5bda authored by Albert Astals Cid's avatar Albert Astals Cid

Move KWallet code from pdf backend to ui

This helps with the widget dependency removal in the core/backends
parent 56c10183
......@@ -55,6 +55,7 @@ DocumentItem::~DocumentItem()
void DocumentItem::setPath(const QString &path)
{
//TODO: remote urls
//TODO: password
m_document->openDocument(path, KUrl(path), KMimeType::findByUrl(KUrl(path)));
m_tocModel->fill(m_document->documentSynopsis());
......
This diff is collapsed.
......@@ -96,10 +96,22 @@ class OKULAR_EXPORT Document : public QObject
*/
~Document();
/**
* Describes the result of an open document operation.
* @since 0.20 (KDE 4.14)
*/
enum OpenResult
{
OpenSuccess, //< The document was opened successfully
OpenError, //< The document failed to open
OpenNeedsPassword //< The document needs a password to be opened or the one provided is not the correct
};
/**
* Opens the document.
* @since 0.20 (KDE 4.14)
*/
bool openDocument( const QString & docFile, const KUrl & url, const KMimeType::Ptr &mime );
OpenResult openDocument( const QString & docFile, const KUrl & url, const KMimeType::Ptr &mime, const QString &password = QString() );
/**
* Closes the document.
......@@ -121,11 +133,6 @@ class OKULAR_EXPORT Document : public QObject
*/
void reparseConfig();
/**
* Returns the widget to be used for relaying GUI things (messageboxes, ...)
*/
QWidget *widget() const;
/**
* Returns whether the document is currently opened.
*/
......@@ -680,9 +687,9 @@ class OKULAR_EXPORT Document : public QObject
/**
* Opens a document archive.
*
* @since 0.8 (KDE 4.2)
* @since 0.20 (KDE 4.14)
*/
bool openDocumentArchive( const QString & docFile, const KUrl & url );
OpenResult openDocumentArchive( const QString & docFile, const KUrl & url, const QString &password = QString() );
/**
* Saves a document archive.
......
......@@ -135,7 +135,7 @@ class DocumentPrivate
void setRotationInternal( int r, bool notify );
ConfigInterface* generatorConfig( GeneratorInfo& info );
SaveInterface* generatorSave( GeneratorInfo& info );
bool openDocumentInternal( const KService::Ptr& offer, bool isstdin, const QString& docFile, const QByteArray& filedata );
Document::OpenResult openDocumentInternal( const KService::Ptr& offer, bool isstdin, const QString& docFile, const QByteArray& filedata, const QString& password );
bool savePageDocumentInfo( KTemporaryFile *infoFile, int what ) const;
DocumentViewport nextDocumentViewport() const;
void notifyAnnotationChanges( int page );
......
......@@ -175,11 +175,26 @@ Generator::~Generator()
delete d_ptr;
}
bool Generator::loadDocument( const QString & fileName, QVector< Page * > & pagesVector )
{
return false;
}
bool Generator::loadDocumentFromData( const QByteArray &, QVector< Page * > & )
{
return false;
}
Document::OpenResult Generator::loadDocumentWithPassword( const QString & fileName, QVector< Page * > & pagesVector, const QString & )
{
return loadDocument( fileName, pagesVector ) ? Document::OpenSuccess : Document::OpenError;
}
Document::OpenResult Generator::loadDocumentFromDataWithPassword( const QByteArray & fileData, QVector< Page * > & pagesVector, const QString & )
{
return loadDocumentFromData( fileData, pagesVector ) ? Document::OpenSuccess : Document::OpenError;
}
bool Generator::closeDocument()
{
Q_D( Generator );
......
......@@ -13,6 +13,7 @@
#define _OKULAR_GENERATOR_H_
#include "okular_export.h"
#include "document.h"
#include "fontinfo.h"
#include "global.h"
#include "pagesize.h"
......@@ -40,7 +41,6 @@ class KIcon;
namespace Okular {
class Document;
class DocumentFonts;
class DocumentInfo;
class DocumentObserver;
......@@ -224,20 +224,47 @@ class OKULAR_EXPORT Generator : public QObject
* Loads the document with the given @p fileName and fills the
* @p pagesVector with the parsed pages.
*
* @note If you implement the WithPassword variants you don't need to implement this one
*
* @returns true on success, false otherwise.
*/
virtual bool loadDocument( const QString & fileName, QVector< Page * > & pagesVector ) = 0;
virtual bool loadDocument( const QString & fileName, QVector< Page * > & pagesVector );
/**
* Loads the document from the raw data @p fileData and fills the
* @p pagesVector with the parsed pages.
*
* @note If you implement the WithPassword variants you don't need to implement this one
*
* @note the Generator has to have the feature @ref ReadRawData enabled
*
* @returns true on success, false otherwise.
*/
virtual bool loadDocumentFromData( const QByteArray & fileData, QVector< Page * > & pagesVector );
/**
* Loads the document with the given @p fileName and @p password and fills the
* @p pagesVector with the parsed pages.
*
* @note Do not implement this if your format doesn't support passwords, it'll cleanly call loadDocument()
*
* @returns a LoadResult defining the result of the operation
*/
virtual Document::OpenResult loadDocumentWithPassword( const QString & fileName, QVector< Page * > & pagesVector, const QString &password );
/**
* Loads the document from the raw data @p fileData and @p password and fills the
* @p pagesVector with the parsed pages.
*
* @note Do not implement this if your format doesn't support passwords, it'll cleanly call loadDocumentFromData()
*
* @note the Generator has to have the feature @ref ReadRawData enabled
*
* @returns a LoadResult defining the result of the operation
*/
virtual Document::OpenResult loadDocumentFromDataWithPassword( const QByteArray & fileData, QVector< Page * > & pagesVector, const QString &password );
/**
* This method is called when the document is closed and not used
* any longer.
......
......@@ -121,7 +121,7 @@ static KJSObject docGetDataObjects( KJSContext *ctx, void *object )
static KJSObject docGetExternal( KJSContext *, void *object )
{
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
QWidget *widget = doc->m_parent->widget();
QWidget *widget = doc->m_widget;
const bool isShell = ( widget
&& widget->parentWidget()
......
......@@ -28,8 +28,6 @@
#include <kconfigdialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpassworddialog.h>
#include <kwallet.h>
#include <ktemporaryfile.h>
#include <kdebug.h>
#include <kglobal.h>
......@@ -453,19 +451,19 @@ PDFGenerator::~PDFGenerator()
}
//BEGIN Generator inherited functions
bool PDFGenerator::loadDocument( const QString & filePath, QVector<Okular::Page*> & pagesVector )
Okular::Document::OpenResult PDFGenerator::loadDocumentWithPassword( const QString & filePath, QVector<Okular::Page*> & pagesVector, const QString &password )
{
#ifndef NDEBUG
if ( pdfdoc )
{
kDebug(PDFDebug) << "PDFGenerator: multiple calls to loadDocument. Check it.";
return false;
return Okular::Document::OpenError;
}
#endif
// create PDFDoc for the given file
pdfdoc = Poppler::Document::load( filePath, 0, 0 );
bool success = init(pagesVector, filePath.section('/', -1, -1));
if (success)
Okular::Document::OpenResult success = init(pagesVector, password);
if (success == Okular::Document::OpenSuccess)
{
// no need to check for the existence of a synctex file, no parser will be
// created if none exists
......@@ -478,97 +476,42 @@ bool PDFGenerator::loadDocument( const QString & filePath, QVector<Okular::Page*
return success;
}
bool PDFGenerator::loadDocumentFromData( const QByteArray & fileData, QVector<Okular::Page*> & pagesVector )
Okular::Document::OpenResult PDFGenerator::loadDocumentFromDataWithPassword( const QByteArray & fileData, QVector<Okular::Page*> & pagesVector, const QString &password )
{
#ifndef NDEBUG
if ( pdfdoc )
{
kDebug(PDFDebug) << "PDFGenerator: multiple calls to loadDocument. Check it.";
return false;
return Okular::Document::OpenError;
}
#endif
// create PDFDoc for the given file
pdfdoc = Poppler::Document::loadFromData( fileData, 0, 0 );
return init(pagesVector, QString());
return init(pagesVector, password);
}
bool PDFGenerator::init(QVector<Okular::Page*> & pagesVector, const QString &walletKey)
Okular::Document::OpenResult PDFGenerator::init(QVector<Okular::Page*> & pagesVector, const QString &password)
{
// if the file didn't open correctly it might be encrypted, so ask for a pass
bool firstInput = true;
bool triedWallet = false;
KWallet::Wallet * wallet = 0;
bool keep = true;
while ( pdfdoc && pdfdoc->isLocked() )
{
QString password;
// 1.A. try to retrieve the first password from the kde wallet system
if ( !triedWallet && !walletKey.isNull() )
{
QString walletName = KWallet::Wallet::NetworkWallet();
WId parentwid = 0;
if ( document() && document()->widget() )
parentwid = document()->widget()->effectiveWinId();
wallet = KWallet::Wallet::openWallet( walletName, parentwid );
if ( wallet )
{
// use the KPdf folder (and create if missing)
if ( !wallet->hasFolder( "KPdf" ) )
wallet->createFolder( "KPdf" );
wallet->setFolder( "KPdf" );
// look for the pass in that folder
QString retrievedPass;
if ( !wallet->readPassword( walletKey, retrievedPass ) )
password = retrievedPass;
}
triedWallet = true;
}
// 1.B. if not retrieved, ask the password using the kde password dialog
if ( password.isNull() )
{
QString prompt;
if ( firstInput )
prompt = i18n( "Please enter the password to read the document:" );
else
prompt = i18n( "Incorrect password. Try again:" );
firstInput = false;
// if the user presses cancel, abort opening
KPasswordDialog dlg( document()->widget(), wallet ? KPasswordDialog::ShowKeepPassword : KPasswordDialog::KPasswordDialogFlags() );
dlg.setCaption( i18n( "Document Password" ) );
dlg.setPrompt( prompt );
if( !dlg.exec() )
break;
password = dlg.password();
if ( wallet )
keep = dlg.keepPassword();
}
if ( !pdfdoc )
return Okular::Document::OpenError;
// 2. reopen the document using the password
if ( pdfdoc->isLocked() )
{
pdfdoc->unlock( password.toLatin1(), password.toLatin1() );
// 3. if the password is correct and the user chose to remember it, store it to the wallet
if ( !pdfdoc->isLocked() && wallet && /*safety check*/ wallet->isOpen() && keep )
{
wallet->writePassword( walletKey, password );
if ( pdfdoc->isLocked() ) {
delete pdfdoc;
pdfdoc = 0;
return Okular::Document::OpenNeedsPassword;
}
}
if ( !pdfdoc || pdfdoc->isLocked() )
{
delete pdfdoc;
pdfdoc = 0;
return false;
}
// build Pages (currentPage was set -1 by deletePages)
int pageCount = pdfdoc->numPages();
if (pageCount < 0) {
delete pdfdoc;
pdfdoc = 0;
return false;
return Okular::Document::OpenError;
}
pagesVector.resize(pageCount);
rectsGenerated.fill(false, pageCount);
......@@ -584,7 +527,7 @@ bool PDFGenerator::init(QVector<Okular::Page*> & pagesVector, const QString &wal
annotProxy = new PopplerAnnotationProxy( pdfdoc, userMutex() );
// the file has been loaded correctly
return true;
return Okular::Document::OpenSuccess;
}
bool PDFGenerator::doCloseDocument()
......
......@@ -60,8 +60,8 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
static const int PDFDebug = 4710;
// [INHERITED] load a document and fill up the pagesVector
bool loadDocument( const QString & fileName, QVector<Okular::Page*> & pagesVector );
bool loadDocumentFromData( const QByteArray & fileData, QVector<Okular::Page*> & pagesVector );
Okular::Document::OpenResult loadDocumentWithPassword( const QString & fileName, QVector<Okular::Page*> & pagesVector, const QString & password );
Okular::Document::OpenResult loadDocumentFromDataWithPassword( const QByteArray & fileData, QVector<Okular::Page*> & pagesVector, const QString & password );
void loadPages(QVector<Okular::Page*> &pagesVector, int rotation=-1, bool clear=false);
// [INHERITED] document information
const Okular::DocumentInfo * generateDocumentInfo();
......@@ -108,7 +108,7 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
Okular::Generator::PrintError printError() const;
private:
bool init(QVector<Okular::Page*> & pagesVector, const QString &walletKey);
Okular::Document::OpenResult init(QVector<Okular::Page*> & pagesVector, const QString &password);
// create the document synopsis hieracy
void addSynopsisChildren( QDomNode * parentSource, QDomNode * parentDestination );
......
......@@ -65,6 +65,8 @@
#include <kdeprintdialog.h>
#include <kprintpreview.h>
#include <kbookmarkmenu.h>
#include <kpassworddialog.h>
#include <kwallet.h>
// local includes
#include "aboutdata.h"
......@@ -1236,25 +1238,96 @@ bool Part::openFile()
uncompressOk = handleCompressed( fileNameToOpen, localFilePath(), compressedMime );
mime = KMimeType::findByPath( fileNameToOpen );
}
bool ok = false;
Document::OpenResult openResult = Document::OpenError;
isDocumentArchive = false;
if ( uncompressOk )
{
if ( mime->is( "application/vnd.kde.okular-archive" ) )
{
ok = m_document->openDocumentArchive( fileNameToOpen, url() );
openResult = m_document->openDocumentArchive( fileNameToOpen, url() );
isDocumentArchive = true;
}
else
{
ok = m_document->openDocument( fileNameToOpen, url(), mime );
openResult = m_document->openDocument( fileNameToOpen, url(), mime );
}
// if the file didn't open correctly it might be encrypted, so ask for a pass
const QString walletKey = fileNameToOpen.section('/', -1, -1);
bool firstInput = true;
bool triedWallet = false;
KWallet::Wallet * wallet = 0;
bool keep = true;
while ( openResult == Document::OpenNeedsPassword )
{
QString password;
// 1.A. try to retrieve the first password from the kde wallet system
if ( !triedWallet && !walletKey.isNull() )
{
QString walletName = KWallet::Wallet::NetworkWallet();
const WId parentwid = widget()->effectiveWinId();
wallet = KWallet::Wallet::openWallet( walletName, parentwid );
if ( wallet )
{
// use the KPdf folder (and create if missing)
if ( !wallet->hasFolder( "KPdf" ) )
wallet->createFolder( "KPdf" );
wallet->setFolder( "KPdf" );
// look for the pass in that folder
QString retrievedPass;
if ( !wallet->readPassword( walletKey, retrievedPass ) )
password = retrievedPass;
}
triedWallet = true;
}
// 1.B. if not retrieved, ask the password using the kde password dialog
if ( password.isNull() )
{
QString prompt;
if ( firstInput )
prompt = i18n( "Please enter the password to read the document:" );
else
prompt = i18n( "Incorrect password. Try again:" );
firstInput = false;
// if the user presses cancel, abort opening
KPasswordDialog dlg( widget(), wallet ? KPasswordDialog::ShowKeepPassword : KPasswordDialog::KPasswordDialogFlags() );
dlg.setCaption( i18n( "Document Password" ) );
dlg.setPrompt( prompt );
if( !dlg.exec() )
break;
password = dlg.password();
if ( wallet )
keep = dlg.keepPassword();
}
// 2. reopen the document using the password
if ( mime->is( "application/vnd.kde.okular-archive" ) )
{
openResult = m_document->openDocumentArchive( fileNameToOpen, url(), password );
isDocumentArchive = true;
}
else
{
openResult = m_document->openDocument( fileNameToOpen, url(), mime, password );
}
// 3. if the password is correct and the user chose to remember it, store it to the wallet
if ( openResult == Document::OpenSuccess && wallet && /*safety check*/ wallet->isOpen() && keep )
{
wallet->writePassword( walletKey, password );
}
}
}
bool canSearch = m_document->supportsSearching();
bool canSearch = m_document->supportsSearching();
emit mimeTypeChanged( mime );
// update one-time actions
const bool ok = openResult == Document::OpenSuccess;
emit enableCloseAction( ok );
m_find->setEnabled( ok && canSearch );
m_findNext->setEnabled( ok && canSearch );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment