[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: [PATCH] Fix KMail mailto url handling / new KURL method
From: Marc Mutz <mutz () kde ! org>
Date: 2002-12-21 17:07:13
[Download RAW message or body]
[Attachment #2 (multipart/mixed)]
Hi!
I've attached two patches. One for kdecore/kurl.* implementing
QMap< QString, QString >
KURL::queryItems(bool caseInsensitiveKeys=false) const;
and the second for fixing mailto URL handling in KMMailtoComposeCommand
and KMUrlClickedCommand.
The details:
- kdecore:
- KURL has a new method queryItems that returns the query parsed into
key/value pairs, optionally normalizing the keys to lowercase.
- kmail:
- new method KMMessage::setFieldsAndBodyFromMailtoUrl() which sets the
information encoded in the mailto url. Since it uses
KURL::queryItems(true), it is robust against case in header names
(as reported on ietf-822@imc.org).
Expl.: mailto:mutz@kde.org?Subject=is+not+shown
- new config key [General]HeadersAllowedForMailtoUrls that contains a
list of header fields that are interpreted in mailto urls (in
addition to To and Body, both of which are special).
- KMMainWin::slotUrlClicked() dispatches mailto urls to
KMMailtoComposeCommand instead of KMUrlClickedCommand, thus
eleminating a bit of code duplication.
I'd like to commit both to KDE_3_1_BRANCH. For reference, the reported
URL was:
mailto:%3D%3fiso-8859-1%3FQ%3fJ%3dFCrgen%3F%3d%20%3cj@foo.com%3E?Subject=list
Marc
--
"Similia similibus curentur"
-- Bush's new motto in fighting terrorism.
["kurl.diff" (text/x-diff)]
Index: kurl.h
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kurl.h,v
retrieving revision 1.102
diff -u -3 -p -r1.102 kurl.h
--- kurl.h 22 Oct 2002 17:11:40 -0000 1.102
+++ kurl.h 21 Dec 2002 17:04:35 -0000
@@ -25,6 +25,7 @@
class QUrl;
class QStringList;
+template <typename K, typename V> class QMap;
class KURLPrivate;
/**
@@ -473,6 +474,18 @@ public:
* specified item does not exist.
*/
QString queryItem( const QString& _item ) const;
+
+ /**
+ * Returns the list of query items as a map mapping keys to values.
+ *
+ * @param caseInsensitiveKeys whether to normalize query keys to lowercase
+ *
+ * @return the map of query items or the empty map if the url has no
+ * query items.
+ *
+ * @since 3.1
+ */
+ QMap< QString, QString > queryItems( bool caseInsensitiveKeys=false ) const;
/**
* Add an additional query item.
Index: kurl.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kurl.cpp,v
retrieving revision 1.223
diff -u -3 -p -r1.223 kurl.cpp
--- kurl.cpp 31 Oct 2002 17:01:01 -0000 1.223
+++ kurl.cpp 21 Dec 2002 17:04:37 -0000
@@ -34,7 +34,7 @@
#include <qstringlist.h>
#include <qregexp.h>
#include <qstylesheet.h>
-
+#include <qmap.h>
#include <qtextcodec.h>
static QTextCodec * codecForHint( int encoding_hint /* not 0 ! */ )
@@ -1752,6 +1752,37 @@ bool urlcmp( const QString& _url1, const
return false;
return true;
+}
+
+QMap< QString, QString > KURL::queryItems( bool cisKeys ) const {
+ if ( m_strQuery_encoded.isEmpty() )
+ return QMap<QString,QString>();
+
+ QMap< QString, QString > result;
+ QStringList items = QStringList::split( '&', m_strQuery_encoded );
+ for ( QStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) \
{ + int equal_pos = (*it).find( '=' );
+ if ( equal_pos > 0 ) { // = is not the first char...
+ QString name = (*it).left( equal_pos );
+ if ( cisKeys )
+ name = name.lower();
+ QString value = (*it).mid( equal_pos + 1 );
+ if ( value.isEmpty() )
+ result.insert( name, QString::fromLatin1("") );
+ else {
+ // ### why is decoding name not neccessary?
+ value.replace( '+', ' ' ); // + in queries means space
+ result.insert( name, decode_string( value ) );
+ }
+ } else if ( equal_pos < 0 ) { // no =
+ QString name = (*it);
+ if ( cisKeys )
+ name = name.lower();
+ result.insert( name, QString::null );
+ }
+ }
+
+ return result;
}
QString KURL::queryItem( const QString& _item ) const
Index: tests/kurltest.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdecore/tests/kurltest.cpp,v
retrieving revision 1.64
diff -u -3 -p -r1.64 kurltest.cpp
--- tests/kurltest.cpp 31 Oct 2002 17:18:20 -0000 1.64
+++ tests/kurltest.cpp 21 Dec 2002 17:04:37 -0000
@@ -518,6 +518,8 @@ int main(int argc, char *argv[])
check("queryItem (invalid item)", theKow.queryItem("InterstellarCounselor"), \
QString::null); check("queryItem (empty item)", theKow.queryItem("empty"), "");
check("queryItem (item with encoded chars)", theKow.queryItem("test"), "+ :%");
+ check("queryItems (keys)", QStringList(theKow.queryItems().keys()).join(", "), \
"empty, hl, hlx, lr, q, test" ); + check("queryItems (values)", \
QStringList(theKow.queryItems().values()).join(", "), ", de, xx, lang de, frerich, + \
:%" );
KURL umlaut1("http://www.clever-tanken.de/liste.asp?ort=N%FCrnberg&typ=Diesel");
check("umlaut1.url()", umlaut1.url(), \
"http://www.clever-tanken.de/liste.asp?ort=N%FCrnberg&typ=Diesel");
["kmail-mailto-url-handling.diff" (text/x-diff)]
Index: kmcommands.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmcommands.cpp,v
retrieving revision 1.8.2.6
diff -u -3 -p -r1.8.2.6 kmcommands.cpp
--- kmcommands.cpp 26 Nov 2002 23:37:01 -0000 1.8.2.6
+++ kmcommands.cpp 21 Dec 2002 17:08:29 -0000
@@ -283,7 +283,8 @@ void KMMailtoComposeCommand::execute()
msg->initHeader(id);
msg->setCharset("utf-8");
- msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
+
+ msg->setFieldsAndBodyFromMailtoUrl( mUrl );
win = new KMComposeWin(msg, id);
win->setCharset("", TRUE);
@@ -1182,48 +1183,13 @@ KMUrlClickedCommand::KMUrlClickedCommand
void KMUrlClickedCommand::execute()
{
- KMComposeWin *win;
- KMMessage* msg;
-
- if (mUrl.protocol() == "mailto")
- {
- uint id = 0;
- if ( mFolder )
- id = mFolder->identity();
-
- msg = new KMMessage;
- msg->initHeader(id);
- msg->setCharset("utf-8");
- msg->setTo( KMMessage::decodeMailtoUrl( mUrl.path() ) );
- QString query=mUrl.query();
- while (!query.isEmpty()) {
- QString queryPart;
- int secondQuery = query.find('?',1);
- if (secondQuery != -1)
- queryPart = query.left(secondQuery);
- else
- queryPart = query;
- query = query.mid(queryPart.length());
-
- if (queryPart.left(9) == "?subject=")
- msg->setSubject( KURL::decode_string(queryPart.mid(9)) );
- else if (queryPart.left(6) == "?body=")
- // It is correct to convert to latin1() as URL should not contain
- // anything except ascii.
- msg->setBody( KURL::decode_string(queryPart.mid(6)).latin1() );
- else if (queryPart.left(4) == "?cc=")
- msg->setCc( KURL::decode_string(queryPart.mid(4)) );
- }
-
- win = new KMComposeWin(msg, id);
- win->setCharset("", TRUE);
- win->show();
- }
- else if ((mUrl.protocol() == "http") || (mUrl.protocol() == "https") ||
- (mUrl.protocol() == "ftp") || (mUrl.protocol() == "file") ||
- (mUrl.protocol() == "ftps") || (mUrl.protocol() == "sftp" ) ||
- (mUrl.protocol() == "help") || (mUrl.protocol() == "vnc") ||
- (mUrl.protocol() == "smb"))
+ kdWarning( mUrl.protocol() != "mailto", 5006 )
+ << "KMUrlClickedCommand::execute(): mailto URLs should be handled by \
KMMailtoComposeCommand" << endl; + if ((mUrl.protocol() == "http") || \
(mUrl.protocol() == "https") || + (mUrl.protocol() == "ftp") || (mUrl.protocol() \
== "file") || + (mUrl.protocol() == "ftps") || (mUrl.protocol() == "sftp" ) ||
+ (mUrl.protocol() == "help") || (mUrl.protocol() == "vnc") ||
+ (mUrl.protocol() == "smb"))
{
if (mMainWin)
mMainWin->statusMsg(i18n("Opening URL..."));
Index: kmmainwin.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmmainwin.cpp,v
retrieving revision 1.525.2.41
diff -u -3 -p -r1.525.2.41 kmmainwin.cpp
--- kmmainwin.cpp 2 Dec 2002 14:57:57 -0000 1.525.2.41
+++ kmmainwin.cpp 21 Dec 2002 17:08:33 -0000
@@ -2066,9 +2066,13 @@ void KMMainWin::slotSelectText() {
//-----------------------------------------------------------------------------
void KMMainWin::slotUrlClicked(const KURL &aUrl, int)
{
- KMCommand *command = new KMUrlClickedCommand( aUrl, mFolder, mMsgView,
- mFolderHtmlPref, this );
- command->start();
+ if ( aUrl.protocol() == "mailto" )
+ (new KMMailtoComposeCommand( aUrl, mHeaders->currentMsg() ))->start();
+ else {
+ KMCommand *command = new KMUrlClickedCommand( aUrl, mFolder, mMsgView,
+ mFolderHtmlPref, this );
+ command->start();
+ }
}
Index: kmmessage.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmmessage.cpp,v
retrieving revision 1.318.2.41
diff -u -3 -p -r1.318.2.41 kmmessage.cpp
--- kmmessage.cpp 30 Nov 2002 16:34:18 -0000 1.318.2.41
+++ kmmessage.cpp 21 Dec 2002 17:08:36 -0000
@@ -19,6 +19,7 @@
#include "kmversion.h"
#include "kmidentity.h"
#include "kmkernel.h"
+#include "kmsender.h"
#include "identitymanager.h"
#include <kapplication.h>
@@ -37,6 +38,7 @@
#include <qstrlist.h>
#include <qmessagebox.h>
#include <qregexp.h>
+#include <qmap.h>
#include <kmime_util.h>
#include <kmime_charfreq.h>
@@ -68,7 +70,7 @@ static QString sReplyLanguage, sReplyStr
static bool sSmartQuote, sReplaceSubjPrefix, sReplaceForwSubjPrefix;
static int sWrapCol;
static QStringList sReplySubjPrefixes, sForwardSubjPrefixes;
-static QStringList sPrefCharsets;
+static QStringList sPrefCharsets, sAllowedHeadersForMailtoUrls;
QString KMMessage::sForwardStr = "";
int KMMessage::sHdrStyle = KMReaderWin::HdrFancy;
@@ -2601,6 +2603,44 @@ void KMMessage::setBody(const QCString&
mNeedsAssembly = TRUE;
}
+void KMMessage::setFieldsAndBodyFromMailtoUrl( const KURL & url ) {
+
+ setCharset( "utf-8" );
+
+ // handle "to", which can be specified implicitly in the "path",
+ // explicitely in the query, or both, and needs to be concatenated
+ // from both:
+ QString to = KMMessage::decodeMailtoUrl( url.path() ); // implicit
+ QMap< QString, QString > query = url.queryItems( true /*case ins. keys*/ );
+ if ( query.contains( "to" ) ) { // explicit
+ QString queryTo = KMMsgBase::decodeRFC2047String( query["to"].latin1() );
+ if ( to.isEmpty() )
+ to = queryTo;
+ else if ( !queryTo.isEmpty() )
+ to += ", " + queryTo;
+ query.erase( "to" );
+ }
+ setTo( to );
+
+ // handle "body"
+ if ( query.contains( "body" ) ) {
+ QString body = query["body"];
+ if ( !body.isEmpty() ) {
+ QValueList<int> dummy;
+ setBodyAndGuessCte( body.utf8(), dummy,
+ !kernel->msgSender()->sendQuotedPrintable() );
+ }
+ query.erase( "body" );
+ }
+
+ // handle the rest of the headers that can be specified in the query:
+ for ( QMap< QString, QString >::const_iterator it = query.begin() ; it != \
query.end() ; ++it ) { + if ( sAllowedHeadersForMailtoUrls.contains( it.key() ) )
+ setHeaderField( it.key().latin1(),
+ KMMsgBase::decodeRFC2047String( it.data().latin1() ) );
+ }
+
+}
// Patched by Daniel Moisset <dmoisset@grulic.org.ar>
// modified numbodyparts, bodypart to take nested body parts as
@@ -3439,6 +3479,19 @@ void KMMessage::readConfig(void)
KConfigGroupSaver saver(config, "General");
config->setGroup("General");
+
+ if ( config->hasKey( "HeadersAllowedForMailtoUrls" ) ) {
+ sAllowedHeadersForMailtoUrls =
+ config->readListEntry( "HeadersAllowedForMailtoUrls" );
+ for ( QStringList::iterator it = sAllowedHeadersForMailtoUrls.begin() ;
+ it != sAllowedHeadersForMailtoUrls.end() ; ++it )
+ *it = (*it).lower();
+ } else {
+ sAllowedHeadersForMailtoUrls.clear();
+ sAllowedHeadersForMailtoUrls << "cc" << "bcc"
+ << "subject" << "keywords"
+ << "in-reply-to" << "references";
+ }
int languageNr = config->readNumEntry("reply-current-language",0);
Index: kmmessage.h
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmmessage.h,v
retrieving revision 1.102.2.16
diff -u -3 -p -r1.102.2.16 kmmessage.h
--- kmmessage.h 30 Nov 2002 15:39:20 -0000 1.102.2.16
+++ kmmessage.h 21 Dec 2002 17:08:37 -0000
@@ -13,6 +13,8 @@
#include <kmime_mdn.h>
+class KURL;
+
template <typename T>
class QValueList;
@@ -454,6 +456,10 @@ public:
method is meant for binary data, not null is appended */
virtual QCString bodyDecoded(void) const;
virtual QByteArray bodyDecodedBinary(void) const;
+
+ /** Sets the message body and headers from a given mailto: URL.
+ **/
+ void setFieldsAndBodyFromMailtoUrl( const KURL & url );
/** Number of body parts the message has. This is one for plain messages
without any attachment. */
[Attachment #7 (application/pgp-signature)]
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic