[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    A more flexible solution for internet keywords
From:       Andreas Hochsteger <e9625392 () student ! tuwien ! ac ! at>
Date:       2001-06-10 16:14:31
[Download RAW message or body]

Hi!

Sorry for this rather long mail, I hope you read it nevertheless ;-)
I've implemented a more flexible solution for the internet keywords which
solves some problems with more advanced queries and provides a more
flexible usage.


What was my intend to change the current scheme?
------------------------------------------------
Last week I wanted to create a simplified query for telephone numbers with
konqeror's internet keywords.
But I had troubles to get this working the way it should, because the url
to be generated looks like this:
http://my.telephone.book/query?name=MyName&city=MyCity
As you can see there are there are two different substitutions necessary,
which can't be done by the current substitution scheme.
It only replaces \1 by the whole (encoded) string of the user query.

I submitted a bug report (whishlist) therefore which can be read here:
http://lists.kde.org/?l=kde-bugs-dist&m=99189305712959&w=2


Overview to my implementation:
------------------------------
Since I never really programmed anything with KDE/Qt beyond some simple
"Hello World" programms, I wanted to try it myself.
It's now finished and working well.
I'm writing to this list, because I've got some remaining questions.
Perhaps someone can take a look at it, if I've done everything allright.

All changes were done in the method "formatResult".
Nothing else had to be modified which speaks a lot for the great design of
kde!
The parameters query and url of that method have been replaced to reflect
the real semantics of that parameters.
I've attached a diff for the file kuriikwsfiltereng.cpp and the whole,
plain method filterResult (for a quick look).


The algorithm works like this:
------------------------------
The user query gets split at the spaces into a QStringList.
Now every item of that list gets inserted to a map of type Map <QString,
QString> which I called IKWMap.
The key is the index of the list + 1 and the value is the data of the list
entry.
In addition the string is scanned for a '=' and if found then an
additional entry is made to the map with the part left of "=" as key and
the part right of "=" as the value.
Afterwards the map is iterated and every match for \<key> replaced by its
value in the map.
The charsets for the realnames query are added to the map too with the
references \ikw_charset and \ikw_responsecharset.
I adjusted the affected parts in the other methods wich used \0, \2 and \3
instead.


Testing:
--------
After applying the patch create an internet keyword 'ikw' with the
following (test-)URL:
http://www.ikwtest.com/1=\1&2=\2&3=\3&4=\4&5=\5&6=\6&7=\7&8=\8&9=\9&10=\10&11=\11&12=\12&name=\name&test=\test


Enter the following query into konqueror:
ikw:1 2 3 4 5 6 7 name=myname 9 test=mytest 11 12

This query gets replaced with the following url:
http://www.ikwtest.com/1=1&2=2&3=3&4=4&5=5&6=6&7=7&8=name%3Dmyname&9=9&10=test%3Dmytest&11=11&12=12&name=myname&test=mytest


\0 is a special reference and has the same meanig like \1 has now. It
simply expands to the whole user query.
The old internet keyword files needs to be changed therefore (replace \1
with \0) to work with the new scheme.


Future work:
------------
* Allow quoted string (name="My Name") and save spaces quotes.
* Let the user define some global references which can be used in query
definitions without specifying them at the user query
  Examples: name, e-mail address, some environment variables, ...
  Important: Don't use sensitive information by default, which can cause
some security weaks, but give the user the possibility to do so if he
wants to.
  Implementation is rather simple: Just initialize the IKW-Map with those
values.


Questions:
----------
* I don't know, if I've done everything right with the encoding of the
strings.
  Can somebody with more experience take a look at it and help me with
that?
* When the code works for everyone and all agree to put it into cvs:
  Can somebody put it into CVS for me, since I don't have an account?
* What do you think about the global reference thing?
  For that I think the interface of that function has


["formatResult_method.cpp" (TEXT/PLAIN)]

QString KURISearchFilterEngine::formatResult( const QString& url,
                                              const QString& cset1,
                                              const QString& cset2,
                                              const QString& query,
                                              bool isMalformed ) const
{
        kdDebug(7023) << "(" << getpid() << ") query='" << query << "', \
url='" << url << "'\n";

	// Return nothing if userquery is empty:
	if (query.isEmpty()) return QString::null;

	typedef QMap <QString, QString> IKWMap;
	IKWMap map;
	QString newurl = url;
	int pct;

	// Decode strings for better handling (for ' ' and '='):
	QString userquery = KURL::decode_string(query);

        kdDebug(7023) << "(" << getpid() << ") userquery='" << userquery << \
"', newurl='" << newurl << "'\n";

	// Create a codec for the desired encoding so that we can transcode the \
user's "url".  QString cseta = cset1;
	if (cseta.isEmpty()) {
		cseta = "iso-8859-1";
	}
	QTextCodec *csetacodec = QTextCodec::codecForName(cseta.latin1());
	if (!csetacodec) {
		cseta = "iso-8859-1";
		csetacodec = QTextCodec::codecForName(cseta.latin1());
	}

	// Add charset indicator for the query to substitution map:
	map.replace("ikw_charset", cseta);

	// Add charset indicator for the fallback query to substitution map:
	QString csetb = cset2;
	if (csetb.isEmpty())
		csetb = "iso-8859-1";
	map.replace("ikw_responsecharset", csetb);

        userquery = csetacodec->fromUnicode(userquery);
	int space_pos;
	while ((space_pos=userquery.find('+')) != -1 )
        	userquery=userquery.replace(space_pos, 1, "%2B");

	// Add whole query with reference '\0' to substitution map:
	map.replace("0", KURL::encode_string(userquery));

	// Generate IKW substitution map from user query:
	QStringList l = QStringList::split(" ", userquery.simplifyWhiteSpace());
	for (int i=0; i<l.count(); i++) {
		QString v = l[i];

		// Insert partial queries (referenced by \1 ... \n) to map:
		map.replace(QString::number(i+1), KURL::encode_string(v));

		// Insert named variables (referenced by \name) to map:
		if ((pct = v.find("=")) > 0)
			map.replace(v.left(pct), KURL::encode_string(v.right(pct + 2)));
	}

	// Substitute references (\refname) from map with the values in the map:
	for (IKWMap::Iterator it = map.begin(); it != map.end(); ++it) {
		QString ref = "\\" + it.key();
		kdDebug (7023)  << "(" << getpid() << ") key='" << it.key() << "' val='" \
<< it.data() << "'\n";  if ((pct = newurl.find(ref)) >= 0)
			newurl = newurl.replace(pct, ref.length(), it.data());
	}

        kdDebug(7023) << "(" << getpid() << ") userquery='" << userquery << \
"', url='" << url << "', newurl='" << newurl << "'\n";

        return newurl;
}


["kuriikwsfiltereng.cpp.diff" (TEXT/PLAIN)]

--- kuriikwsfiltereng.cpp.orig	Thu Jun  7 21:44:13 2001
+++ kuriikwsfiltereng.cpp	Sun Jun 10 16:37:27 2001
@@ -101,12 +101,12 @@
                         _url = _url.replace(question, "");
                         return formatResult(search, fallback->charset(), \
QString::null, _url, true);  } else {
-                        int pct = \
m_currInternetKeywordsEngine.m_strQueryWithSearch.find("\\|"); +            \
int pct = m_currInternetKeywordsEngine.m_strQueryWithSearch.find("\\ikw_fallbackuri");
  if (pct >= 0)
                         {
                                 search = KURL::encode_string( search );
                                 QString res = \
                m_currInternetKeywordsEngine.m_strQueryWithSearch;
-                                return formatResult( res.replace(pct, 2, \
search), fallback->charset(), QString::null, _url, url.isMalformed() ); +   \
return formatResult( res.replace(pct, 16, search), fallback->charset(), \
QString::null, _url, url.isMalformed() );  }
                 }
             }
@@ -159,64 +159,79 @@
     return s_pSelf;
 }
 
-QString KURISearchFilterEngine::formatResult( const QString& query,
+QString KURISearchFilterEngine::formatResult( const QString& url,
                                               const QString& cset1,
                                               const QString& cset2,
-                                              const QString& url,
+                                              const QString& query,
                                               bool isMalformed ) const
 {
-    // Substitute the variable part we find in the query.
-    if (!query.isEmpty())
-	{
-	    QString newurl = query;
-	    int pct;
+        kdDebug(7023) << "(" << getpid() << ") query='" << query << "', \
url='" << url << "'\n"; +
+	// Return nothing if userquery is empty:
+	if (query.isEmpty()) return QString::null;
+
+	typedef QMap <QString, QString> IKWMap;
+	IKWMap map;
+	QString newurl = url;
+	int pct;
+
+	// Decode strings for better handling (for ' ' and '='):
+	QString userquery = KURL::decode_string(query);
+
+        kdDebug(7023) << "(" << getpid() << ") userquery='" << userquery \
<< "', newurl='" << newurl << "'\n";  
-	    // Create a codec for the desired encoding so that we can
-	    // transcode the user's "url".
-	    QString cseta = cset1;
-	    if (cseta.isEmpty()) {
+	// Create a codec for the desired encoding so that we can transcode the \
user's "url". +	QString cseta = cset1;
+	if (cseta.isEmpty()) {
 		cseta = "iso-8859-1";
-	    }
-	    QTextCodec *csetacodec = QTextCodec::codecForName(cseta.latin1());
-	    if (!csetacodec) {
+	}
+	QTextCodec *csetacodec = QTextCodec::codecForName(cseta.latin1());
+	if (!csetacodec) {
 		cseta = "iso-8859-1";
 		csetacodec = QTextCodec::codecForName(cseta.latin1());
-	    }
-
-	    // Substitute the charset indicator for the query.
-	    if ((pct = newurl.find("\\2")) >= 0) {
-		newurl = newurl.replace(pct, 2, cseta);
-	    }
-
-	    // Substitute the charset indicator for the fallback query.
-	    if ((pct = newurl.find("\\3")) >= 0) {
-		QString csetb = cset2;
-		if (csetb.isEmpty()) {
-		    csetb = "iso-8859-1";
-		}
-		newurl = newurl.replace(pct, 2, csetb);
-	    }
+	}
 
-        QString userquery = csetacodec->fromUnicode(url);
-        int space_pos;
-        while( (space_pos=userquery.find('+')) != -1 )
-        userquery=userquery.replace( space_pos, 1, "%2B" );
-
-        while( (space_pos=userquery.find(' ')) != -1 )
-        userquery=userquery.replace( space_pos, 1, "+" );
+	// Add charset indicator for the query to substitution map:
+	map.replace("ikw_charset", cseta);
 
-        if ( isMalformed )
-        userquery = KURL::encode_string(userquery);
+	// Add charset indicator for the fallback query to substitution map:
+	QString csetb = cset2;
+	if (csetb.isEmpty())
+		csetb = "iso-8859-1";
+	map.replace("ikw_responsecharset", csetb);
+
+        userquery = csetacodec->fromUnicode(userquery);
+	int space_pos;
+	while ((space_pos=userquery.find('+')) != -1 )
+        	userquery=userquery.replace(space_pos, 1, "%2B");
+
+	// Add whole query with reference '\0' to substitution map:
+	map.replace("0", KURL::encode_string(userquery));
+
+	// Generate IKW substitution map from user query:
+	QStringList l = QStringList::split(" ", userquery.simplifyWhiteSpace());
+	for (int i=0; i<l.count(); i++) {
+		QString v = l[i];
+
+		// Insert partial queries (referenced by \1 ... \n) to map:
+		map.replace(QString::number(i+1), KURL::encode_string(v));
+
+		// Insert named variables (referenced by \name) to map:
+		if ((pct = v.find("=")) > 0)
+			map.replace(v.left(pct), KURL::encode_string(v.right(pct + 2)));
+	}
 
-        if ((pct = newurl.find("\\1")) >= 0)
-        newurl = newurl.replace(pct, 2, userquery);
+	// Substitute references (\refname) from map with the values in the map:
+	for (IKWMap::Iterator it = map.begin(); it != map.end(); ++it) {
+		QString ref = "\\" + it.key();
+		kdDebug (7023)  << "(" << getpid() << ") key='" << it.key() << "' val='" \
<< it.data() << "'\n"; +		if ((pct = newurl.find(ref)) >= 0)
+			newurl = newurl.replace(pct, ref.length(), it.data());
+	}
 
-        if ( m_bVerbose )
-        kdDebug(7023) << "(" << getpid() << ") filtered " << url << " to " \
<< newurl << "\n"; +        kdDebug(7023) << "(" << getpid() << ") \
userquery='" << userquery << "', url='" << url << "', newurl='" << newurl \
<< "'\n";  
         return newurl;
-    }
-    return QString::null;
 }
 
 void KURISearchFilterEngine::loadConfig()
@@ -329,10 +344,10 @@
     IKWSEntry rn = ikwsEntryByName(IKW_REALNAMES);
     if (rn.m_strName.isEmpty())	{
 	rn.m_strName = IKW_REALNAMES;
-	rn.m_strQuery = QString::fromLatin1("http://navigation.realnames.com/resolver.dll?realname=\\1&charset=\\2&responsecharset=\\3&providerid=180");
 +	rn.m_strQuery = QString::fromLatin1("http://navigation.realnames.com/reso \
lver.dll?realname=\\0&charset=\\ikw_charset&responsecharset=\\ikw_responsecharset&providerid=180");
  rn.m_strCharset = "utf-8";
 	rn.m_strQueryWithSearch = \
                QString::fromLatin1("http://navigation.realnames.com/resolver.dll?"
                
-						      "action=navigation&realname=\\1&charset=\\2&providerid=180&fallbackuri=\\|");
 +						      "action=navigation&realname=\\0&charset=\\ikw_charset&providerid=180&fallbackuri=\\ikw_fallbackuri");
  if (rn.m_strName == selIKWSEngine)
 	    m_currInternetKeywordsEngine = rn;
 



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic