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 )
76 : d_ptr( new
Attachment::AttachmentPrivate( url, mimetype ) )
81 : d_ptr( new
Attachment::AttachmentPrivate( data, mimetype ) )
86 : d_ptr(new AttachmentPrivate(*other.d_func()) )
91 Attachment::~Attachment()
96 bool Attachment::operator==(
const Attachment &a )
const
99 if ( d->mUrl.isEmpty() ) {
100 return d->mUrl == a.d_func()->mUrl &&
101 d->mMimetype == a.d_func()->mMimetype &&
102 d->mLabel == a.d_func()->mLabel;
104 return d->mData == a.d_func()->mData &&
105 d->mMimetype == a.d_func()->mMimetype &&
106 d->mLabel == a.d_func()->mLabel;
109 void Attachment::operator=(
const Attachment &a )
144 class NoteMessageWrapper::NoteMessageWrapperPrivate
147 NoteMessageWrapperPrivate()
152 NoteMessageWrapperPrivate(
const KMime::Message::Ptr &msg )
156 readMimeMessage(msg);
159 void readMimeMessage(
const KMime::Message::Ptr &msg );
161 KMime::Content* createCustomPart()
const;
162 void parseCustomPart( KMime::Content * );
164 KMime::Content* createAttachmentPart(
const Attachment & )
const;
165 void parseAttachmentPart( KMime::Content * );
174 QMap< QString, QString >
custom;
179 void NoteMessageWrapper::NoteMessageWrapperPrivate::readMimeMessage(
const KMime::Message::Ptr& msg)
182 kWarning() <<
"Empty message";
185 title = msg->subject(
true )->asUnicodeString();
186 text = msg->mainBodyPart()->decodedText(
true );
187 if ( msg->from(
false ) )
188 from = msg->from(
false )->asUnicodeString();
189 creationDate = msg->date(
true )->dateTime();
190 if ( msg->contentType(
false ) && msg->contentType(
false )->asUnicodeString() == QLatin1String(
"text/html") ) {
191 textFormat = Qt::RichText;
194 if (KMime::Headers::Base *lastmod = msg->headerByType(X_NOTES_LASTMODIFIED_HEADER)) {
195 const QByteArray &s = lastmod->asUnicodeString().toLatin1();
196 const char *cursor = s.constData();
197 if (!KMime::HeaderParsing::parseDateTime( cursor, cursor + s.length(), lastModifiedDate)) {
198 kWarning() <<
"failed to parse lastModifiedDate";
202 if (KMime::Headers::Base *uidHeader = msg->headerByType(X_NOTES_UID_HEADER)) {
203 uid = uidHeader->asUnicodeString();
206 if (KMime::Headers::Base *classificationHeader = msg->headerByType(X_NOTES_CLASSIFICATION_HEADER)) {
207 const QString &c = classificationHeader->asUnicodeString();
208 if ( c == CLASSIFICATION_PRIVATE ) {
209 classification = Private;
210 }
else if ( c == CLASSIFICATION_CONFIDENTIAL ) {
211 classification = Confidential;
215 const KMime::Content::List list = msg->contents();
216 Q_FOREACH(KMime::Content *c, msg->contents()) {
217 if (KMime::Headers::Base *typeHeader = c->headerByType(X_NOTES_CONTENTTYPE_HEADER)) {
218 const QString &type = typeHeader->asUnicodeString();
219 if ( type == CONTENT_TYPE_CUSTOM ) {
221 }
else if ( type == CONTENT_TYPE_ATTACHMENT ) {
222 parseAttachmentPart(c);
224 qWarning() <<
"unknown type " << type;
230 QDomDocument createXMLDocument()
232 QDomDocument document;
233 QString p =
"version=\"1.0\" encoding=\"UTF-8\"";
234 document.appendChild(document.createProcessingInstruction(
"xml", p ) );
238 QDomDocument loadDocument(KMime::Content *part)
241 int errorLine, errorColumn;
242 QDomDocument document;
243 bool ok = document.setContent( part->body(), &errorMsg, &errorLine, &errorColumn );
245 kWarning() << part->body();
246 qWarning(
"Error loading document: %s, line %d, column %d", qPrintable( errorMsg ), errorLine, errorColumn );
247 return QDomDocument();
252 KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createCustomPart()
const
254 KMime::Content* content =
new KMime::Content();
255 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_CUSTOM, ENCODING ) );
256 QDomDocument document = createXMLDocument();
257 QDomElement element = document.createElement(
"custom" );
258 element.setAttribute(
"version",
"1.0" );
259 for ( QMap <QString, QString >::const_iterator it = custom.begin(); it != custom.end(); ++it ) {
260 QDomElement e = element.ownerDocument().createElement( it.key() );
261 QDomText t = element.ownerDocument().createTextNode( it.value() );
263 element.appendChild( e );
264 document.appendChild( element );
266 content->setBody( document.toString().toLatin1() );
270 void NoteMessageWrapper::NoteMessageWrapperPrivate::parseCustomPart( KMime::Content* part )
272 QDomDocument document = loadDocument( part );
273 if (document.isNull()) {
276 QDomElement top = document.documentElement();
277 if ( top.tagName() !=
"custom" ) {
278 qWarning(
"XML error: Top tag was %s instead of the expected custom",
279 top.tagName().toLatin1().data() );
283 for ( QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling() ) {
284 if ( n.isElement() ) {
285 QDomElement e = n.toElement();
286 custom.insert(e.tagName(), e.text());
288 kDebug() <<
"Node is not an element";
294 KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createAttachmentPart(
const Attachment &a )
const
296 KMime::Content* content =
new KMime::Content();
297 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_ATTACHMENT, ENCODING ) );
298 if (a.url().isValid()) {
299 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_URL_HEADER, content, a.url().toString().toLatin1(), ENCODING ) );
301 content->setBody( a.data() );
303 content->contentType()->setMimeType( a.mimetype().toLatin1() );
304 if (!a.label().isEmpty()) {
305 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_LABEL_HEADER, content, a.label().toLatin1(), ENCODING ) );
307 content->contentTransferEncoding()->setEncoding( KMime::Headers::CEbase64 );
308 content->contentDisposition()->setDisposition( KMime::Headers::CDattachment );
309 content->contentDisposition()->setFilename(
"attachment" );
313 void NoteMessageWrapper::NoteMessageWrapperPrivate::parseAttachmentPart( KMime::Content *part )
316 if ( KMime::Headers::Base *labelHeader = part->headerByType( X_NOTES_LABEL_HEADER ) ) {
317 label = labelHeader->asUnicodeString();
319 if ( KMime::Headers::Base *header = part->headerByType( X_NOTES_URL_HEADER ) ) {
320 Attachment attachment( QUrl( header->asUnicodeString() ), part->contentType()->mimeType() );
321 attachment.setLabel( label );
322 attachments.append(attachment);
324 Attachment attachment( part->decodedContent(), part->contentType()->mimeType() );
325 attachment.setLabel( label );
326 attachments.append(attachment);
330 NoteMessageWrapper::NoteMessageWrapper()
331 : d_ptr( new NoteMessageWrapperPrivate() )
335 NoteMessageWrapper::NoteMessageWrapper(
const KMime::Message::Ptr &msg )
336 : d_ptr( new NoteMessageWrapperPrivate(msg) )
340 NoteMessageWrapper::~NoteMessageWrapper()
348 KMime::Message::Ptr msg = KMime::Message::Ptr(
new KMime::Message() );
350 QString
title = i18nc(
"The default name for new notes.",
"New Note" );
351 if ( !d->title.isEmpty() ) {
355 QString
text = QLatin1String(
" ");
356 if ( !d->text.isEmpty() ) {
360 KDateTime
creationDate = KDateTime::currentLocalDateTime();
361 if ( d->creationDate.isValid() ) {
362 creationDate = d->creationDate;
366 if ( d->lastModifiedDate.isValid() ) {
367 lastModifiedDate = d->lastModifiedDate;
371 if ( !d->uid.isEmpty() ) {
374 uid = QUuid::createUuid();
377 msg->subject(
true )->fromUnicodeString( title, ENCODING );
378 msg->contentType(
true )->setMimeType( d->textFormat == Qt::RichText ?
"text/html" :
"text/plain" );
379 msg->date(
true )->setDateTime( creationDate );
380 msg->from(
true )->fromUnicodeString( d->from, ENCODING );
381 msg->mainBodyPart()->fromUnicodeString( text );
382 msg->appendHeader(
new KMime::Headers::Generic(X_NOTES_LASTMODIFIED_HEADER, msg.get(), lastModifiedDate.toString( KDateTime::RFCDateDay ).toLatin1(), ENCODING ) );
383 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_UID_HEADER, msg.get(),
uid, ENCODING ) );
385 QString
classification = QString::fromLatin1(CLASSIFICATION_PUBLIC);
386 switch ( d->classification ) {
388 classification = QString::fromLatin1(CLASSIFICATION_PRIVATE);
391 classification = QString::fromLatin1(CLASSIFICATION_CONFIDENTIAL);
397 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_CLASSIFICATION_HEADER, msg.get(),
classification, ENCODING ) );
399 foreach (
const Attachment &a, d->attachments) {
400 msg->addContent( d->createAttachmentPart(a) );
403 if ( !d->custom.isEmpty() ) {
404 msg->addContent( d->createCustomPart() );
432 return d->classification;
444 return d->lastModifiedDate;
456 return d->creationDate;
487 d->textFormat = format;
499 return d->textFormat;
505 if ( d->textFormat == Qt::PlainText ) {
510 QRegExp rx( QLatin1String(
"<body[^>]*>(.*)</body>"), Qt::CaseInsensitive );
511 rx.indexIn( d->text );
512 QString body = rx.cap( 1 );
514 return Qt::escape( body.remove( QRegExp( QLatin1String(
"<[^>]*>") ) ).trimmed() );
520 return d->attachments;
529 QString noteIconName()
531 return QString::fromLatin1(
"text-plain" );
534 QString noteMimeType()
536 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.