20 #include "noteutils.h" 22 #include <klocalizedstring.h> 23 #include <kdatetime.h> 24 #include <kmime/kmime_message.h> 30 #include <QTextDocument> 35 #define X_NOTES_UID_HEADER "X-Akonotes-UID" 36 #define X_NOTES_LASTMODIFIED_HEADER "X-Akonotes-LastModified" 37 #define X_NOTES_CLASSIFICATION_HEADER "X-Akonotes-Classification" 38 #define X_NOTES_CUSTOM_HEADER "X-Akonotes-Custom" 40 #define CLASSIFICATION_PUBLIC "Public" 41 #define CLASSIFICATION_PRIVATE "Private" 42 #define CLASSIFICATION_CONFIDENTIAL "Confidential" 44 #define X_NOTES_URL_HEADER "X-Akonotes-Url" 45 #define X_NOTES_LABEL_HEADER "X-Akonotes-Label" 46 #define X_NOTES_CONTENTTYPE_HEADER "X-Akonotes-Type" 47 #define CONTENT_TYPE_CUSTOM "custom" 48 #define CONTENT_TYPE_ATTACHMENT "attachment" 50 #define ENCODING "utf-8" 52 class Attachment::AttachmentPrivate
55 AttachmentPrivate(
const QUrl&
url,
const QString&
mimetype )
60 AttachmentPrivate(
const QByteArray&
data,
const QString&
mimetype )
65 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()
97 bool Attachment::operator==(
const Attachment &a )
const 100 if ( d->mUrl.isEmpty() ) {
101 return d->mUrl == a.d_func()->mUrl &&
102 d->mMimetype == a.d_func()->mMimetype &&
103 d->mLabel == a.d_func()->mLabel;
105 return d->mData == a.d_func()->mData &&
106 d->mMimetype == a.d_func()->mMimetype &&
107 d->mLabel == a.d_func()->mLabel;
110 void Attachment::operator=(
const Attachment &a )
145 class NoteMessageWrapper::NoteMessageWrapperPrivate
148 NoteMessageWrapperPrivate()
149 : classification( Public )
153 NoteMessageWrapperPrivate(
const KMime::Message::Ptr &msg )
154 : classification( Public ),
155 textFormat( Qt::PlainText )
157 readMimeMessage(msg);
160 void readMimeMessage(
const KMime::Message::Ptr &msg );
162 KMime::Content* createCustomPart()
const;
163 void parseCustomPart( KMime::Content * );
165 KMime::Content* createAttachmentPart(
const Attachment & )
const;
166 void parseAttachmentPart( KMime::Content * );
172 KDateTime creationDate;
173 KDateTime lastModifiedDate;
174 QMap< QString, QString > custom;
175 QList<Attachment> attachments;
176 Classification classification;
177 Qt::TextFormat textFormat;
180 void NoteMessageWrapper::NoteMessageWrapperPrivate::readMimeMessage(
const KMime::Message::Ptr& msg)
183 kWarning() <<
"Empty message";
186 title = msg->subject(
true )->asUnicodeString();
187 text = msg->mainBodyPart()->decodedText(
true );
188 if ( msg->from(
false ) )
189 from = msg->from(
false )->asUnicodeString();
190 creationDate = msg->date(
true )->dateTime();
191 if ( msg->mainBodyPart()->contentType(
false ) && msg->mainBodyPart()->contentType()->mimeType() ==
"text/html" ) {
192 textFormat = Qt::RichText;
195 if (KMime::Headers::Base *lastmod = msg->headerByType(X_NOTES_LASTMODIFIED_HEADER)) {
196 const QByteArray &s = lastmod->asUnicodeString().toLatin1();
197 const char *cursor = s.constData();
198 if (!KMime::HeaderParsing::parseDateTime( cursor, cursor + s.length(), lastModifiedDate)) {
199 kWarning() <<
"failed to parse lastModifiedDate";
203 if (KMime::Headers::Base *uidHeader = msg->headerByType(X_NOTES_UID_HEADER)) {
204 uid = uidHeader->asUnicodeString();
207 if (KMime::Headers::Base *classificationHeader = msg->headerByType(X_NOTES_CLASSIFICATION_HEADER)) {
208 const QString &c = classificationHeader->asUnicodeString();
209 if ( c == CLASSIFICATION_PRIVATE ) {
210 classification = Private;
211 }
else if ( c == CLASSIFICATION_CONFIDENTIAL ) {
212 classification = Confidential;
216 const KMime::Content::List list = msg->contents();
217 Q_FOREACH(KMime::Content *c, msg->contents()) {
218 if (KMime::Headers::Base *typeHeader = c->headerByType(X_NOTES_CONTENTTYPE_HEADER)) {
219 const QString &type = typeHeader->asUnicodeString();
220 if ( type == CONTENT_TYPE_CUSTOM ) {
222 }
else if ( type == CONTENT_TYPE_ATTACHMENT ) {
223 parseAttachmentPart(c);
225 qWarning() <<
"unknown type " << type;
231 QDomDocument createXMLDocument()
233 QDomDocument document;
234 QString p =
"version=\"1.0\" encoding=\"UTF-8\"";
235 document.appendChild(document.createProcessingInstruction(
"xml", p ) );
239 QDomDocument loadDocument(KMime::Content *part)
242 int errorLine, errorColumn;
243 QDomDocument document;
244 bool ok = document.setContent( part->body(), &errorMsg, &errorLine, &errorColumn );
246 kWarning() << part->body();
247 qWarning(
"Error loading document: %s, line %d, column %d", qPrintable( errorMsg ), errorLine, errorColumn );
248 return QDomDocument();
253 KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createCustomPart()
const 255 KMime::Content* content =
new KMime::Content();
256 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_CUSTOM, ENCODING ) );
257 QDomDocument document = createXMLDocument();
258 QDomElement element = document.createElement(
"custom" );
259 element.setAttribute(
"version",
"1.0" );
260 for ( QMap <QString, QString >::const_iterator it = custom.begin(); it != custom.end(); ++it ) {
261 QDomElement e = element.ownerDocument().createElement( it.key() );
262 QDomText t = element.ownerDocument().createTextNode( it.value() );
264 element.appendChild( e );
265 document.appendChild( element );
267 content->setBody( document.toString().toLatin1() );
271 void NoteMessageWrapper::NoteMessageWrapperPrivate::parseCustomPart( KMime::Content* part )
273 QDomDocument document = loadDocument( part );
274 if (document.isNull()) {
277 QDomElement top = document.documentElement();
278 if ( top.tagName() !=
"custom" ) {
279 qWarning(
"XML error: Top tag was %s instead of the expected custom",
280 top.tagName().toLatin1().data() );
284 for ( QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling() ) {
285 if ( n.isElement() ) {
286 QDomElement e = n.toElement();
287 custom.insert(e.tagName(), e.text());
289 kDebug() <<
"Node is not an element";
295 KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createAttachmentPart(
const Attachment &a )
const 297 KMime::Content* content =
new KMime::Content();
298 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_ATTACHMENT, ENCODING ) );
299 if (a.
url().isValid()) {
300 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_URL_HEADER, content, a.
url().toString().toLatin1(), ENCODING ) );
302 content->setBody( a.
data() );
304 content->contentType()->setMimeType( a.
mimetype().toLatin1() );
305 if (!a.
label().isEmpty()) {
306 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_LABEL_HEADER, content, a.
label().toLatin1(), ENCODING ) );
308 content->contentTransferEncoding()->setEncoding( KMime::Headers::CEbase64 );
309 content->contentDisposition()->setDisposition( KMime::Headers::CDattachment );
310 content->contentDisposition()->setFilename(
"attachment" );
314 void NoteMessageWrapper::NoteMessageWrapperPrivate::parseAttachmentPart( KMime::Content *part )
317 if ( KMime::Headers::Base *labelHeader = part->headerByType( X_NOTES_LABEL_HEADER ) ) {
318 label = labelHeader->asUnicodeString();
320 if ( KMime::Headers::Base *header = part->headerByType( X_NOTES_URL_HEADER ) ) {
321 Attachment attachment( QUrl( header->asUnicodeString() ), part->contentType()->mimeType() );
323 attachments.append(attachment);
325 Attachment attachment( part->decodedContent(), part->contentType()->mimeType() );
327 attachments.append(attachment);
331 NoteMessageWrapper::NoteMessageWrapper()
332 : d_ptr(
new NoteMessageWrapperPrivate() )
336 NoteMessageWrapper::NoteMessageWrapper(
const KMime::Message::Ptr &msg )
337 : d_ptr(
new NoteMessageWrapperPrivate(msg) )
341 NoteMessageWrapper::~NoteMessageWrapper()
349 KMime::Message::Ptr msg = KMime::Message::Ptr(
new KMime::Message() );
351 QString title = i18nc(
"The default name for new notes.",
"New Note" );
352 if ( !d->title.isEmpty() ) {
356 QString text = QLatin1String(
" ");
357 if ( !d->text.isEmpty() ) {
361 KDateTime creationDate = KDateTime::currentLocalDateTime();
362 if ( d->creationDate.isValid() ) {
363 creationDate = d->creationDate;
366 KDateTime lastModifiedDate = KDateTime::currentLocalDateTime();
367 if ( d->lastModifiedDate.isValid() ) {
368 lastModifiedDate = d->lastModifiedDate;
372 if ( !d->uid.isEmpty() ) {
375 uid = QUuid::createUuid();
378 msg->subject(
true )->fromUnicodeString( title, ENCODING );
379 msg->date(
true )->setDateTime( creationDate );
380 msg->from(
true )->fromUnicodeString( d->from, ENCODING );
381 msg->mainBodyPart()->fromUnicodeString( text );
382 msg->mainBodyPart()->contentType(
true )->setMimeType( d->textFormat == Qt::RichText ?
"text/html" :
"text/plain" );
383 msg->appendHeader(
new KMime::Headers::Generic(X_NOTES_LASTMODIFIED_HEADER, msg.get(), lastModifiedDate.toString( KDateTime::RFCDateDay ).toLatin1(), ENCODING ) );
384 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_UID_HEADER, msg.get(), uid, ENCODING ) );
386 QString classification = QString::fromLatin1(CLASSIFICATION_PUBLIC);
387 switch ( d->classification ) {
389 classification = QString::fromLatin1(CLASSIFICATION_PRIVATE);
392 classification = QString::fromLatin1(CLASSIFICATION_CONFIDENTIAL);
398 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_CLASSIFICATION_HEADER, msg.get(), classification, ENCODING ) );
400 foreach (
const Attachment &a, d->attachments) {
401 msg->addContent( d->createAttachmentPart(a) );
404 if ( !d->custom.isEmpty() ) {
405 msg->addContent( d->createCustomPart() );
427 d->classification = classification;
433 return d->classification;
439 d->lastModifiedDate = lastModifiedDate;
445 return d->lastModifiedDate;
451 d->creationDate = creationDate;
457 return d->creationDate;
488 d->textFormat = format;
500 return d->textFormat;
506 if ( d->textFormat == Qt::PlainText ) {
511 QRegExp rx( QLatin1String(
"<body[^>]*>(.*)</body>"), Qt::CaseInsensitive );
512 rx.indexIn( d->text );
513 QString body = rx.cap( 1 );
515 return Qt::escape( body.remove( QRegExp( QLatin1String(
"<[^>]*>") ) ).trimmed() );
521 return d->attachments;
530 QString noteIconName()
532 return QString::fromLatin1(
"text-plain" );
535 QString noteMimeType()
537 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.
FreeBusyManager::Singleton.
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.