~ubuntu-branches/ubuntu/oneiric/kdepim/oneiric-updates

« back to all changes in this revision

Viewing changes to calendarsupport/attachmenthandler.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2011-06-28 19:33:24 UTC
  • mfrom: (0.2.13) (0.1.13 sid)
  • Revision ID: package-import@ubuntu.com-20110628193324-8yvjs8sdv9rdoo6c
Tags: 4:4.7.0-0ubuntu1
* New upstream release
  - update install files
  - add missing kdepim-doc package to control file
  - Fix Vcs lines
  - kontact breaks/replaces korganizer << 4:4.6.80
  - tighten the dependency of kdepim-dev on libkdepim4 to fix lintian error

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (c) 2010 Klar�lvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
 
3
 
 
4
  This library is free software; you can redistribute it and/or
 
5
  modify it under the terms of the GNU Library General Public
 
6
  License as published by the Free Software Foundation; either
 
7
  version 2 of the License, or (at your option) any later version.
 
8
 
 
9
  This library is distributed in the hope that it will be useful,
 
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
  Library General Public License for more details.
 
13
 
 
14
  You should have received a copy of the GNU Library General Public License
 
15
  along with this library; see the file COPYING.LIB.  If not, write to
 
16
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
17
  Boston, MA 02110-1301, USA.
 
18
*/
 
19
/**
 
20
  @file
 
21
  This file is part of the API for handling calendar data and provides
 
22
  static functions for dealing with calendar incidence attachments.
 
23
 
 
24
  @brief
 
25
  vCalendar/iCalendar attachment handling.
 
26
 
 
27
  @author Allen Winter \<winter@kde.org\>
 
28
*/
 
29
#include "attachmenthandler.h"
 
30
#include "akonadicalendar.h"
 
31
#include "next/incidencesearchjob.h"
 
32
 
 
33
#include <KFileDialog>
 
34
#include <KLocale>
 
35
#include <KMessageBox>
 
36
#include <KMimeType>
 
37
#include <KRun>
 
38
#include <KTemporaryFile>
 
39
#include <KToolInvocation>
 
40
#include <KIO/NetAccess>
 
41
#include <KJob>
 
42
 
 
43
#include <QFile>
 
44
#include <QPointer>
 
45
 
 
46
using namespace KCalCore;
 
47
 
 
48
namespace CalendarSupport {
 
49
 
 
50
struct ReceivedInfo {
 
51
  QString uid;
 
52
  QString attachmentName;
 
53
};
 
54
 
 
55
class AttachmentHandler::Private
 
56
{
 
57
  public:
 
58
    Private( QWidget *parent )
 
59
    {
 
60
      mParent = parent;
 
61
    }
 
62
    QMap<KJob*,ReceivedInfo> mJobToReceivedInfo;
 
63
    QPointer<QWidget> mParent;
 
64
};
 
65
 
 
66
AttachmentHandler::AttachmentHandler( QWidget *parent ) : d( new Private( parent ) )
 
67
{
 
68
 
 
69
}
 
70
 
 
71
AttachmentHandler::~AttachmentHandler()
 
72
{
 
73
  delete d;
 
74
}
 
75
 
 
76
Attachment::Ptr AttachmentHandler::find( const QString &attachmentName,
 
77
                                         const Incidence::Ptr &incidence )
 
78
{
 
79
  if ( !incidence ) {
 
80
    return Attachment::Ptr();
 
81
  }
 
82
 
 
83
  // get the attachment by name from the incidence
 
84
  const Attachment::List as = incidence->attachments();
 
85
  Attachment::Ptr a;
 
86
  if ( !as.isEmpty() ) {
 
87
    Attachment::List::ConstIterator it;
 
88
    for ( it = as.begin(); it != as.end(); ++it ) {
 
89
      if ( (*it)->label() == attachmentName ) {
 
90
        a = *it;
 
91
        break;
 
92
      }
 
93
    }
 
94
  }
 
95
 
 
96
  if ( !a ) {
 
97
    KMessageBox::error(
 
98
      d->mParent,
 
99
      i18n( "No attachment named \"%1\" found in the incidence.", attachmentName ) );
 
100
    return Attachment::Ptr();
 
101
  }
 
102
 
 
103
  if ( a->isUri() ) {
 
104
    if ( !KIO::NetAccess::exists( a->uri(), KIO::NetAccess::SourceSide, d->mParent ) ) {
 
105
      KMessageBox::sorry(
 
106
        d->mParent,
 
107
        i18n( "The attachment \"%1\" is a web link that is inaccessible from this computer. ",
 
108
              KUrl::fromPercentEncoding( a->uri().toLatin1() ) ) );
 
109
      return Attachment::Ptr();
 
110
    }
 
111
  }
 
112
  return a;
 
113
}
 
114
 
 
115
 
 
116
Attachment::Ptr AttachmentHandler::find( const QString &attachmentName,
 
117
                                         const ScheduleMessage::Ptr &message )
 
118
{
 
119
  if ( !message ) {
 
120
    return Attachment::Ptr();
 
121
  }
 
122
 
 
123
  Incidence::Ptr incidence = message->event().dynamicCast<Incidence>();
 
124
  if ( !incidence ) {
 
125
    KMessageBox::error(
 
126
      d->mParent,
 
127
      i18n( "The calendar invitation stored in this email message is broken in some way. "
 
128
            "Unable to continue." ) );
 
129
    return Attachment::Ptr();
 
130
  }
 
131
 
 
132
  return find( attachmentName, incidence );
 
133
}
 
134
 
 
135
static KTemporaryFile *s_tempFile = 0;
 
136
 
 
137
static KUrl tempFileForAttachment( const Attachment::Ptr &attachment )
 
138
{
 
139
  KUrl url;
 
140
 
 
141
  s_tempFile = new KTemporaryFile();
 
142
  s_tempFile->setAutoRemove( false );
 
143
  QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
 
144
  if ( !patterns.empty() ) {
 
145
    s_tempFile->setSuffix( QString( patterns.first() ).remove( '*' ) );
 
146
  }
 
147
  s_tempFile->open();
 
148
  s_tempFile->setPermissions( QFile::ReadUser );
 
149
  s_tempFile->write( QByteArray::fromBase64( attachment->data() ) );
 
150
  s_tempFile->close();
 
151
  QFile tf( s_tempFile->fileName() );
 
152
  if ( tf.size() != attachment->size() ) {
 
153
    //whoops. failed to write the entire attachment. return an invalid URL.
 
154
    delete s_tempFile;
 
155
    s_tempFile = 0;
 
156
    return url;
 
157
  }
 
158
 
 
159
  url.setPath( s_tempFile->fileName() );
 
160
  return url;
 
161
}
 
162
 
 
163
bool AttachmentHandler::view( const Attachment::Ptr &attachment )
 
164
{
 
165
  if ( !attachment ) {
 
166
    return false;
 
167
  }
 
168
 
 
169
  bool stat = true;
 
170
  if ( attachment->isUri() ) {
 
171
    KToolInvocation::invokeBrowser( attachment->uri() );
 
172
  } else {
 
173
    // put the attachment in a temporary file and launch it
 
174
    KUrl tempUrl = tempFileForAttachment( attachment );
 
175
    if ( tempUrl.isValid() ) {
 
176
      stat = KRun::runUrl( tempUrl, attachment->mimeType(), 0, true );
 
177
    } else {
 
178
      stat = false;
 
179
      KMessageBox::error(
 
180
        d->mParent,
 
181
        i18n( "Unable to create a temporary file for the attachment." ) );
 
182
    }
 
183
    delete s_tempFile;
 
184
    s_tempFile = 0;
 
185
  }
 
186
  return stat;
 
187
}
 
188
 
 
189
bool AttachmentHandler::view( const QString &attachmentName,
 
190
                              const Incidence::Ptr &incidence )
 
191
{
 
192
  return view( find( attachmentName, incidence ) );
 
193
}
 
194
 
 
195
void AttachmentHandler::view( const QString &attachmentName, const QString &uid )
 
196
{
 
197
  IncidenceSearchJob *job = new IncidenceSearchJob();
 
198
  job->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, uid,
 
199
                 IncidenceSearchJob::ExactMatch );
 
200
  connect( job, SIGNAL( result( KJob* ) ), this, SLOT( slotFinishView( KJob* ) ) );
 
201
  ReceivedInfo info;
 
202
  info.attachmentName = attachmentName;
 
203
  info.uid = uid;
 
204
  d->mJobToReceivedInfo[job] = info;
 
205
}
 
206
 
 
207
bool AttachmentHandler::view( const QString &attachmentName,
 
208
                              const ScheduleMessage::Ptr &message )
 
209
{
 
210
  return view( find( attachmentName, message ) );
 
211
}
 
212
 
 
213
bool AttachmentHandler::saveAs( const Attachment::Ptr &attachment )
 
214
{
 
215
  // get the saveas file name
 
216
  QString saveAsFile = KFileDialog::getSaveFileName( attachment->label(), QString(), d->mParent,
 
217
                                                     i18n( "Save Attachment" ) );
 
218
  if ( saveAsFile.isEmpty() ||
 
219
       ( QFile( saveAsFile ).exists() &&
 
220
         ( KMessageBox::warningYesNo(
 
221
             d->mParent,
 
222
             i18n( "%1 already exists. Do you want to overwrite it?",
 
223
                   saveAsFile ) ) == KMessageBox::No ) ) ) {
 
224
    return false;
 
225
  }
 
226
 
 
227
  bool stat = false;
 
228
  if ( attachment->isUri() ) {
 
229
    // save the attachment url
 
230
    stat = KIO::NetAccess::file_copy( attachment->uri(), KUrl( saveAsFile ) );
 
231
  } else {
 
232
    // put the attachment in a temporary file and save it
 
233
    KUrl tempUrl = tempFileForAttachment( attachment );
 
234
    if ( tempUrl.isValid() ) {
 
235
      stat = KIO::NetAccess::file_copy( tempUrl, KUrl( saveAsFile ) );
 
236
      if ( !stat && KIO::NetAccess::lastError() ) {
 
237
        KMessageBox::error( d->mParent, KIO::NetAccess::lastErrorString() );
 
238
      }
 
239
    } else {
 
240
      stat = false;
 
241
      KMessageBox::error(
 
242
        d->mParent,
 
243
        i18n( "Unable to create a temporary file for the attachment." ) );
 
244
    }
 
245
    delete s_tempFile;
 
246
    s_tempFile = 0;
 
247
  }
 
248
  return stat;
 
249
}
 
250
 
 
251
bool AttachmentHandler::saveAs( const QString &attachmentName,
 
252
                                const Incidence::Ptr &incidence )
 
253
{
 
254
  return saveAs( find( attachmentName, incidence ) );
 
255
}
 
256
 
 
257
void AttachmentHandler::saveAs( const QString &attachmentName, const QString &uid )
 
258
{
 
259
  IncidenceSearchJob *job = new IncidenceSearchJob();
 
260
  job->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, uid,
 
261
                 IncidenceSearchJob::ExactMatch );
 
262
  connect( job, SIGNAL( result( KJob* ) ), this, SLOT( slotFinishView( KJob* ) ) );
 
263
 
 
264
  ReceivedInfo info;
 
265
  info.attachmentName = attachmentName;
 
266
  info.uid = uid;
 
267
  d->mJobToReceivedInfo[job] = info;
 
268
}
 
269
 
 
270
bool AttachmentHandler::saveAs( const QString &attachmentName,
 
271
                                const ScheduleMessage::Ptr &message )
 
272
{
 
273
  return saveAs( find( attachmentName, message ) );
 
274
}
 
275
 
 
276
void AttachmentHandler::slotFinishSaveAs( KJob *job )
 
277
{
 
278
  IncidenceSearchJob *searchJob = qobject_cast<IncidenceSearchJob*>( job );
 
279
  const KCalCore::Incidence::List incidences = searchJob->incidences();
 
280
  ReceivedInfo info = d->mJobToReceivedInfo[job];
 
281
 
 
282
  bool success = false;
 
283
  if ( !incidences.isEmpty() ) {
 
284
    if ( saveAs( info.attachmentName, incidences.first() ) ) {
 
285
      success = true;
 
286
    }
 
287
  }
 
288
 
 
289
  emit saveAsFinished( info.uid, info.attachmentName, success );
 
290
  d->mJobToReceivedInfo.remove( job );
 
291
}
 
292
 
 
293
void AttachmentHandler::slotFinishView( KJob *job )
 
294
{
 
295
  IncidenceSearchJob *searchJob = qobject_cast<IncidenceSearchJob*>( job );
 
296
  const KCalCore::Incidence::List incidences = searchJob->incidences();
 
297
  ReceivedInfo info = d->mJobToReceivedInfo[job];
 
298
 
 
299
  bool success = false;
 
300
  if ( !incidences.isEmpty() ) {
 
301
    if ( view( info.attachmentName, incidences.first() ) ) {
 
302
      success = true;
 
303
    }
 
304
  }
 
305
 
 
306
  emit viewFinished( info.uid, info.attachmentName, success );
 
307
  d->mJobToReceivedInfo.remove( job );
 
308
}
 
309
 
 
310
 
 
311
} // namespace CalendarSupport
 
312