20 #include "noteutils.h"
22 #include <klocalizedstring.h>
23 #include <kdatetime.h>
24 #include <kmime/kmime_message.h>
34 #define X_NOTES_UID_HEADER "X-Akonotes-UID"
35 #define X_NOTES_LASTMODIFIED_HEADER "X-Akonotes-LastModified"
36 #define X_NOTES_CLASSIFICATION_HEADER "X-Akonotes-Classification"
37 #define X_NOTES_CUSTOM_HEADER "X-Akonotes-Custom"
39 #define CLASSIFICATION_PUBLIC "Public"
40 #define CLASSIFICATION_PRIVATE "Private"
41 #define CLASSIFICATION_CONFIDENTIAL "Confidential"
43 #define X_NOTES_URL_HEADER "X-Akonotes-Url"
44 #define X_NOTES_LABEL_HEADER "X-Akonotes-Label"
45 #define X_NOTES_CONTENTTYPE_HEADER "X-Akonotes-Type"
46 #define CONTENT_TYPE_CUSTOM "custom"
47 #define CONTENT_TYPE_ATTACHMENT "attachment"
49 #define ENCODING "utf-8"
51 class Attachment::AttachmentPrivate
54 AttachmentPrivate(
const QUrl&
url,
const QString&
mimetype )
59 AttachmentPrivate(
const QByteArray&
data,
const QString&
mimetype )
64 AttachmentPrivate(
const AttachmentPrivate &other )
77 : d_ptr( new
Attachment::AttachmentPrivate( url, mimetype ) )
82 : d_ptr( new
Attachment::AttachmentPrivate( data, mimetype ) )
87 : d_ptr(new AttachmentPrivate(*other.d_func()) )
92 Attachment::~Attachment()
98 bool Attachment::operator==(
const Attachment &a )
const
101 if ( d->mUrl.isEmpty() ) {
102 return d->mUrl == a.d_func()->mUrl &&
103 d->mMimetype == a.d_func()->mMimetype &&
104 d->mLabel == a.d_func()->mLabel;
106 return d->mData == a.d_func()->mData &&
107 d->mMimetype == a.d_func()->mMimetype &&
108 d->mLabel == a.d_func()->mLabel;
111 void Attachment::operator=(
const Attachment &a )
148 class NoteMessageWrapper::NoteMessageWrapperPrivate
151 NoteMessageWrapperPrivate()
156 NoteMessageWrapperPrivate(
const KMime::Message::Ptr &msg )
160 readMimeMessage(msg);
163 void readMimeMessage(
const KMime::Message::Ptr &msg );
165 KMime::Content* createCustomPart()
const;
166 void parseCustomPart( KMime::Content * );
168 KMime::Content* createAttachmentPart(
const Attachment & )
const;
169 void parseAttachmentPart( KMime::Content * );
178 QMap< QString, QString >
custom;
183 void NoteMessageWrapper::NoteMessageWrapperPrivate::readMimeMessage(
const KMime::Message::Ptr& msg)
186 kWarning() <<
"Empty message";
189 title = msg->subject(
true )->asUnicodeString();
190 text = msg->mainBodyPart()->decodedText(
true );
191 if ( msg->from(
false ) )
192 from = msg->from(
false )->asUnicodeString();
193 creationDate = msg->date(
true )->dateTime();
194 if ( msg->contentType(
false ) && msg->contentType(
false )->asUnicodeString() == QLatin1String(
"text/html") ) {
195 textFormat = Qt::RichText;
198 if (KMime::Headers::Base *lastmod = msg->headerByType(X_NOTES_LASTMODIFIED_HEADER)) {
199 const QByteArray &s = lastmod->asUnicodeString().toLatin1();
200 const char *cursor = s.constData();
201 if (!KMime::HeaderParsing::parseDateTime( cursor, cursor + s.length(), lastModifiedDate)) {
202 kWarning() <<
"failed to parse lastModifiedDate";
206 if (KMime::Headers::Base *uidHeader = msg->headerByType(X_NOTES_UID_HEADER)) {
207 uid = uidHeader->asUnicodeString();
210 if (KMime::Headers::Base *classificationHeader = msg->headerByType(X_NOTES_CLASSIFICATION_HEADER)) {
211 const QString &c = classificationHeader->asUnicodeString();
212 if ( c == CLASSIFICATION_PRIVATE ) {
213 classification = Private;
214 }
else if ( c == CLASSIFICATION_CONFIDENTIAL ) {
215 classification = Confidential;
219 const KMime::Content::List list = msg->contents();
220 Q_FOREACH(KMime::Content *c, msg->contents()) {
221 if (KMime::Headers::Base *typeHeader = c->headerByType(X_NOTES_CONTENTTYPE_HEADER)) {
222 const QString &type = typeHeader->asUnicodeString();
223 if ( type == CONTENT_TYPE_CUSTOM ) {
225 }
else if ( type == CONTENT_TYPE_ATTACHMENT ) {
226 parseAttachmentPart(c);
228 qWarning() <<
"unknown type " << type;
234 QDomDocument createXMLDocument()
236 QDomDocument document;
237 QString p =
"version=\"1.0\" encoding=\"UTF-8\"";
238 document.appendChild(document.createProcessingInstruction(
"xml", p ) );
242 QDomDocument loadDocument(KMime::Content *part)
245 int errorLine, errorColumn;
246 QDomDocument document;
247 bool ok = document.setContent( part->body(), &errorMsg, &errorLine, &errorColumn );
249 kWarning() << part->body();
250 qWarning(
"Error loading document: %s, line %d, column %d", qPrintable( errorMsg ), errorLine, errorColumn );
251 return QDomDocument();
256 KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createCustomPart()
const
258 KMime::Content* content =
new KMime::Content();
259 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_CUSTOM, ENCODING ) );
260 QDomDocument document = createXMLDocument();
261 QDomElement element = document.createElement(
"custom" );
262 element.setAttribute(
"version",
"1.0" );
263 for ( QMap <QString, QString >::const_iterator it = custom.begin(); it != custom.end(); ++it ) {
264 QDomElement e = element.ownerDocument().createElement( it.key() );
265 QDomText t = element.ownerDocument().createTextNode( it.value() );
267 element.appendChild( e );
268 document.appendChild( element );
270 content->setBody( document.toString().toLatin1() );
274 void NoteMessageWrapper::NoteMessageWrapperPrivate::parseCustomPart( KMime::Content* part )
276 QDomDocument document = loadDocument( part );
277 if (document.isNull()) {
280 QDomElement top = document.documentElement();
281 if ( top.tagName() !=
"custom" ) {
282 qWarning(
"XML error: Top tag was %s instead of the expected custom",
283 top.tagName().toLatin1().data() );
287 for ( QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling() ) {
288 if ( n.isElement() ) {
289 QDomElement e = n.toElement();
290 custom.insert(e.tagName(), e.text());
292 kDebug() <<
"Node is not an element";
298 KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createAttachmentPart(
const Attachment &a )
const
300 KMime::Content* content =
new KMime::Content();
301 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_ATTACHMENT, ENCODING ) );
302 if (a.url().isValid()) {
303 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_URL_HEADER, content, a.url().toString().toLatin1(), ENCODING ) );
305 content->setBody( a.data() );
307 content->contentType()->setMimeType( a.mimetype().toLatin1() );
308 if (!a.label().isEmpty()) {
309 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_LABEL_HEADER, content, a.label().toLatin1(), ENCODING ) );
311 content->contentTransferEncoding()->setEncoding( KMime::Headers::CEbase64 );
312 content->contentDisposition()->setDisposition( KMime::Headers::CDattachment );
313 content->contentDisposition()->setFilename(
"attachment" );
317 void NoteMessageWrapper::NoteMessageWrapperPrivate::parseAttachmentPart( KMime::Content *part )
320 if ( KMime::Headers::Base *labelHeader = part->headerByType( X_NOTES_LABEL_HEADER ) ) {
321 label = labelHeader->asUnicodeString();
323 if ( KMime::Headers::Base *header = part->headerByType( X_NOTES_URL_HEADER ) ) {
324 Attachment attachment( QUrl( header->asUnicodeString() ), part->contentType()->mimeType() );
325 attachment.setLabel( label );
326 attachments.append(attachment);
328 Attachment attachment( part->decodedContent(), part->contentType()->mimeType() );
329 attachment.setLabel( label );
330 attachments.append(attachment);
334 NoteMessageWrapper::NoteMessageWrapper()
335 : d_ptr( new NoteMessageWrapperPrivate() )
339 NoteMessageWrapper::NoteMessageWrapper(
const KMime::Message::Ptr &msg )
340 : d_ptr( new NoteMessageWrapperPrivate(msg) )
344 NoteMessageWrapper::~NoteMessageWrapper()
352 KMime::Message::Ptr msg = KMime::Message::Ptr(
new KMime::Message() );
354 QString
title = i18nc(
"The default name for new notes.",
"New Note" );
355 if ( !d->title.isEmpty() ) {
359 QString
text = QLatin1String(
" ");
360 if ( !d->text.isEmpty() ) {
364 KDateTime
creationDate = KDateTime::currentLocalDateTime();
365 if ( d->creationDate.isValid() ) {
366 creationDate = d->creationDate;
370 if ( d->lastModifiedDate.isValid() ) {
371 lastModifiedDate = d->lastModifiedDate;
375 if ( !d->uid.isEmpty() ) {
378 uid = QUuid::createUuid();
381 msg->subject(
true )->fromUnicodeString( title, ENCODING );
382 msg->contentType(
true )->setMimeType( d->textFormat == Qt::RichText ?
"text/html" :
"text/plain" );
383 msg->date(
true )->setDateTime( creationDate );
384 msg->from(
true )->fromUnicodeString( d->from, ENCODING );
385 msg->mainBodyPart()->fromUnicodeString( text );
386 msg->appendHeader(
new KMime::Headers::Generic(X_NOTES_LASTMODIFIED_HEADER, msg.get(), lastModifiedDate.toString( KDateTime::RFCDateDay ).toLatin1(), ENCODING ) );
387 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_UID_HEADER, msg.get(),
uid, ENCODING ) );
389 QString
classification = QString::fromLatin1(CLASSIFICATION_PUBLIC);
390 switch ( d->classification ) {
392 classification = QString::fromLatin1(CLASSIFICATION_PRIVATE);
395 classification = QString::fromLatin1(CLASSIFICATION_CONFIDENTIAL);
401 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_CLASSIFICATION_HEADER, msg.get(),
classification, ENCODING ) );
403 foreach (
const Attachment &a, d->attachments) {
404 msg->addContent( d->createAttachmentPart(a) );
407 if ( !d->custom.isEmpty() ) {
408 msg->addContent( d->createCustomPart() );
436 return d->classification;
448 return d->lastModifiedDate;
460 return d->creationDate;
491 d->textFormat = format;
503 return d->textFormat;
509 if ( d->textFormat == Qt::PlainText ) {
514 QRegExp rx( QLatin1String(
"<body[^>]*>(.*)</body>"), Qt::CaseInsensitive );
515 rx.indexIn( d->text );
516 QString body = rx.cap( 1 );
518 return Qt::escape( body.remove( QRegExp( QLatin1String(
"<[^>]*>") ) ).trimmed() );
524 return d->attachments;
535 QString noteIconName()
537 return QString::fromLatin1(
"text-plain" );
540 QString noteMimeType()
542 return QString::fromLatin1(
"text/x-vnd.akonadi.note" );
void setFrom(const QString &from)
Set the origin (creator) of the note (stored in the mime header) This is usually the application crea...
Classification classification() const
Returns the classification of the note.
QString text() const
Returns the text of the note.
Qt::TextFormat textFormat() const
QString uid() const
Returns the uid of the note.
void setTitle(const QString &title)
Set the title of the note.
QByteArray data() const
Returns the date for inline attachments.
void setText(const QString &text, Qt::TextFormat format=Qt::PlainText)
Set the text of the note.
void setClassification(Classification)
Set the classification of the note.
void setLastModifiedDate(const KDateTime &lastModifiedDate)
Set the lastModified-date of the note.
void setUid(const QString &uid)
Set the uid of the note.
KDateTime lastModifiedDate() const
Returns the lastModified-date of the note.
QUrl url() const
Returns the url for url-only attachments.
void setCreationDate(const KDateTime &creationDate)
Set the creation date of the note (stored in the mime header)
QString toPlainText() const
void setLabel(const QString &label)
Sets the label to be presented to the user.
A convenience wrapper around KMime::Message::Ptr for notes.
Attachment(const QUrl &url, const QString &mimetype)
Create an attachment referencing a url only.
QString from() const
Returns the origin (creator) of the note.
An attachment for a note.
QString title() const
Returns the title of the note.
QMap< QString, QString > & custom()
Returns a reference to the custom-value map.
QString label() const
Returns the label of the attachment.
QList< Attachment > & attachments()
Returns a reference to the list of attachments of the note.
QString mimetype() const
Returns the mimetype.
KDateTime creationDate() const
Returns the creation date of the note.
KMime::MessagePtr message() const
Assemble a KMime message with the given values.