mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
325 lines
9.3 KiB
C++
325 lines
9.3 KiB
C++
/*
|
|
Copyright (c) 2010 Klarlvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
|
|
Author: Allen Winter <allen.winter@kdab.com>
|
|
Copyright (C) 2014 Sergio Martins <iamsergio@gmail.com>
|
|
|
|
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.
|
|
*/
|
|
/**
|
|
@file
|
|
This file is part of the API for handling calendar data and provides
|
|
static functions for dealing with calendar incidence attachments.
|
|
|
|
@brief
|
|
vCalendar/iCalendar attachment handling.
|
|
|
|
@author Allen Winter \<winter@kde.org\>
|
|
*/
|
|
#include "attachmenthandler.h"
|
|
#include "calendarsupport/utils.h"
|
|
|
|
#include <Akonadi/ItemFetchJob>
|
|
#include <KFileDialog>
|
|
#include <KLocalizedString>
|
|
#include <KMessageBox>
|
|
#include <KMimeType>
|
|
#include <KRun>
|
|
#include <KTemporaryFile>
|
|
#include <KToolInvocation>
|
|
#include <KIO/NetAccess>
|
|
#include <KJob>
|
|
|
|
#include <QFile>
|
|
#include <QPointer>
|
|
|
|
using namespace KCalCore;
|
|
using namespace Akonadi;
|
|
|
|
namespace CalendarSupport {
|
|
|
|
struct ReceivedInfo {
|
|
QString uid;
|
|
QString attachmentName;
|
|
};
|
|
|
|
class AttachmentHandler::Private
|
|
{
|
|
public:
|
|
Private( QWidget *parent )
|
|
{
|
|
mParent = parent;
|
|
}
|
|
QMap<KJob *,ReceivedInfo> mJobToReceivedInfo;
|
|
QPointer<QWidget> mParent;
|
|
};
|
|
|
|
AttachmentHandler::AttachmentHandler( QWidget *parent ) : QObject( parent ), d( new Private( parent ) )
|
|
{
|
|
|
|
}
|
|
|
|
AttachmentHandler::~AttachmentHandler()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
Attachment::Ptr AttachmentHandler::find( const QString &attachmentName,
|
|
const Incidence::Ptr &incidence )
|
|
{
|
|
if ( !incidence ) {
|
|
return Attachment::Ptr();
|
|
}
|
|
|
|
// get the attachment by name from the incidence
|
|
const Attachment::List as = incidence->attachments();
|
|
Attachment::Ptr a;
|
|
if ( !as.isEmpty() ) {
|
|
Attachment::List::ConstIterator it;
|
|
Attachment::List::ConstIterator end( as.constEnd() );
|
|
|
|
for ( it = as.constBegin(); it != end; ++it ) {
|
|
if ( (*it)->label() == attachmentName ) {
|
|
a = *it;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !a ) {
|
|
KMessageBox::error(
|
|
d->mParent,
|
|
i18n( "No attachment named \"%1\" found in the incidence.", attachmentName ) );
|
|
return Attachment::Ptr();
|
|
}
|
|
|
|
if ( a->isUri() ) {
|
|
if ( !KIO::NetAccess::exists( a->uri(), KIO::NetAccess::SourceSide, d->mParent ) ) {
|
|
KMessageBox::sorry(
|
|
d->mParent,
|
|
i18n( "The attachment \"%1\" is a web link that is inaccessible from this computer. ",
|
|
KUrl::fromPercentEncoding( a->uri().toLatin1() ) ) );
|
|
return Attachment::Ptr();
|
|
}
|
|
}
|
|
return a;
|
|
}
|
|
|
|
Attachment::Ptr AttachmentHandler::find( const QString &attachmentName,
|
|
const ScheduleMessage::Ptr &message )
|
|
{
|
|
if ( !message ) {
|
|
return Attachment::Ptr();
|
|
}
|
|
|
|
Incidence::Ptr incidence = message->event().dynamicCast<Incidence>();
|
|
if ( !incidence ) {
|
|
KMessageBox::error(
|
|
d->mParent,
|
|
i18n( "The calendar invitation stored in this email message is broken in some way. "
|
|
"Unable to continue." ) );
|
|
return Attachment::Ptr();
|
|
}
|
|
|
|
return find( attachmentName, incidence );
|
|
}
|
|
|
|
static KTemporaryFile *s_tempFile = 0;
|
|
|
|
static KUrl tempFileForAttachment( const Attachment::Ptr &attachment )
|
|
{
|
|
KUrl url;
|
|
|
|
s_tempFile = new KTemporaryFile();
|
|
s_tempFile->setAutoRemove( false );
|
|
QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
|
|
if ( !patterns.empty() ) {
|
|
s_tempFile->setSuffix( QString( patterns.first() ).remove( QLatin1Char('*') ) );
|
|
}
|
|
s_tempFile->open();
|
|
s_tempFile->setPermissions( QFile::ReadUser );
|
|
s_tempFile->write( QByteArray::fromBase64( attachment->data() ) );
|
|
s_tempFile->close();
|
|
QFile tf( s_tempFile->fileName() );
|
|
if ( tf.size() != attachment->size() ) {
|
|
//whoops. failed to write the entire attachment. return an invalid URL.
|
|
delete s_tempFile;
|
|
s_tempFile = 0;
|
|
return url;
|
|
}
|
|
|
|
url.setPath( s_tempFile->fileName() );
|
|
return url;
|
|
}
|
|
|
|
bool AttachmentHandler::view( const Attachment::Ptr &attachment )
|
|
{
|
|
if ( !attachment ) {
|
|
return false;
|
|
}
|
|
|
|
bool stat = true;
|
|
if ( attachment->isUri() ) {
|
|
KToolInvocation::invokeBrowser( attachment->uri() );
|
|
} else {
|
|
// put the attachment in a temporary file and launch it
|
|
KUrl tempUrl = tempFileForAttachment( attachment );
|
|
if ( tempUrl.isValid() ) {
|
|
stat = KRun::runUrl( tempUrl, attachment->mimeType(), 0, true );
|
|
} else {
|
|
stat = false;
|
|
KMessageBox::error(
|
|
d->mParent,
|
|
i18n( "Unable to create a temporary file for the attachment." ) );
|
|
}
|
|
delete s_tempFile;
|
|
s_tempFile = 0;
|
|
}
|
|
return stat;
|
|
}
|
|
|
|
bool AttachmentHandler::view( const QString &attachmentName,
|
|
const Incidence::Ptr &incidence )
|
|
{
|
|
return view( find( attachmentName, incidence ) );
|
|
}
|
|
|
|
void AttachmentHandler::view( const QString &attachmentName, const QString &uid )
|
|
{
|
|
Item item;
|
|
item.setGid(uid);
|
|
ItemFetchJob *job = new ItemFetchJob(item);
|
|
connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFinishView(KJob*)) );
|
|
ReceivedInfo info;
|
|
info.attachmentName = attachmentName;
|
|
info.uid = uid;
|
|
d->mJobToReceivedInfo[job] = info;
|
|
}
|
|
|
|
bool AttachmentHandler::view( const QString &attachmentName,
|
|
const ScheduleMessage::Ptr &message )
|
|
{
|
|
return view( find( attachmentName, message ) );
|
|
}
|
|
|
|
bool AttachmentHandler::saveAs( const Attachment::Ptr &attachment )
|
|
{
|
|
// get the saveas file name
|
|
QString saveAsFile = KFileDialog::getSaveFileName( attachment->label(), QString(), d->mParent,
|
|
i18n( "Save Attachment" ) );
|
|
if ( saveAsFile.isEmpty() ||
|
|
( QFile( saveAsFile ).exists() &&
|
|
( KMessageBox::warningYesNo(
|
|
d->mParent,
|
|
i18n( "%1 already exists. Do you want to overwrite it?",
|
|
saveAsFile ) ) == KMessageBox::No ) ) ) {
|
|
return false;
|
|
}
|
|
|
|
bool stat = false;
|
|
if ( attachment->isUri() ) {
|
|
// save the attachment url
|
|
stat = KIO::NetAccess::file_copy( attachment->uri(), KUrl( saveAsFile ) );
|
|
} else {
|
|
// put the attachment in a temporary file and save it
|
|
KUrl tempUrl = tempFileForAttachment( attachment );
|
|
if ( tempUrl.isValid() ) {
|
|
stat = KIO::NetAccess::file_copy( tempUrl, KUrl( saveAsFile ) );
|
|
if ( !stat && KIO::NetAccess::lastError() ) {
|
|
KMessageBox::error( d->mParent, KIO::NetAccess::lastErrorString() );
|
|
}
|
|
} else {
|
|
stat = false;
|
|
KMessageBox::error(
|
|
d->mParent,
|
|
i18n( "Unable to create a temporary file for the attachment." ) );
|
|
}
|
|
delete s_tempFile;
|
|
s_tempFile = 0;
|
|
}
|
|
return stat;
|
|
}
|
|
|
|
bool AttachmentHandler::saveAs( const QString &attachmentName,
|
|
const Incidence::Ptr &incidence )
|
|
{
|
|
return saveAs( find( attachmentName, incidence ) );
|
|
}
|
|
|
|
void AttachmentHandler::saveAs( const QString &attachmentName, const QString &uid )
|
|
{
|
|
Item item;
|
|
item.setGid(uid);
|
|
ItemFetchJob *job = new ItemFetchJob(item);
|
|
connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFinishView(KJob*)) );
|
|
|
|
ReceivedInfo info;
|
|
info.attachmentName = attachmentName;
|
|
info.uid = uid;
|
|
d->mJobToReceivedInfo[job] = info;
|
|
}
|
|
|
|
bool AttachmentHandler::saveAs( const QString &attachmentName,
|
|
const ScheduleMessage::Ptr &message )
|
|
{
|
|
return saveAs( find( attachmentName, message ) );
|
|
}
|
|
|
|
void AttachmentHandler::slotFinishSaveAs( KJob *job )
|
|
{
|
|
ReceivedInfo info = d->mJobToReceivedInfo[job];
|
|
bool success = false;
|
|
|
|
if ( job->error() != 0 ) {
|
|
ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
|
|
const Item::List items = fetchJob->items();
|
|
if ( !items.isEmpty() ) {
|
|
Incidence::Ptr incidence = CalendarSupport::incidence( items.first() );
|
|
success = incidence && saveAs( info.attachmentName, incidence );
|
|
} else {
|
|
kWarning() << Q_FUNC_INFO << "No item found";
|
|
}
|
|
} else {
|
|
kWarning() << Q_FUNC_INFO << "Job error:" << job->errorString();
|
|
}
|
|
|
|
emit saveAsFinished( info.uid, info.attachmentName, success );
|
|
d->mJobToReceivedInfo.remove( job );
|
|
}
|
|
|
|
void AttachmentHandler::slotFinishView( KJob *job )
|
|
{
|
|
ReceivedInfo info = d->mJobToReceivedInfo[job];
|
|
bool success = false;
|
|
|
|
if ( job->error() != 0 ) {
|
|
ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
|
|
const Item::List items = fetchJob->items();
|
|
if ( !items.isEmpty() ) {
|
|
Incidence::Ptr incidence = CalendarSupport::incidence( items.first() );
|
|
success = incidence && view( info.attachmentName, incidence );
|
|
} else {
|
|
kWarning() << Q_FUNC_INFO << "No item found";
|
|
}
|
|
} else {
|
|
kWarning() << Q_FUNC_INFO << "Job error:" << job->errorString();
|
|
}
|
|
|
|
emit viewFinished( info.uid, info.attachmentName, success );
|
|
d->mJobToReceivedInfo.remove( job );
|
|
}
|
|
|
|
} // namespace CalendarSupport
|
|
|