webdav search

Best, Jan-Pascal van j.p.vanbest at tbm.tudelft.nl
Fri Apr 26 16:47:31 BST 2002


Hi all,

>From the kfm-devel mailing list I guessed that you were the people 
working on the http ioslave. Please let
me know if I should send this somewhere else

>From the kdepim/korganizer context, I've been working on
support for exchange 2000 calendar servers with webdav. 
I'm made some changes to my local kdelibs tree which I think
could be useful for more people.

At the end of this message is a patch to http.c/http.h that
- implements a davSearch() method
- implements the SEARCH function as a special().
- adds a "translate: f" header flag for all webdav GETs. This should
be an option of some kind, but i don't know how and where. Any
ideas?
- add a content-type: text/xml for dav search in httpOpen(). 
I guess this should be done somewhere else, but I don't know 
where. I've tried an addMetadata() in davSearch, but that
didn't work
- do not finish the header when there is still davData to send (this 
fixes a bug that just hasn't shown up yet)
- Strange thing: I had to substract 1 from the content-size header
before Exchange would swallow my search requests. Maybe something to
do with zero-terminated strings?

I'm also attaching searchjob.cpp and searchjob.h, which implement
a SearchJob class, which looks a lot like the ListJob class.  

So, what do you think? Should this ultimately go into kdelibs,
and what should be done before that?

Cheers

Jan-Pascal

PS: This is the first thing I ever wrote for KDE. Let me know if
I'm doing something stupid...

-- 
Jan-Pascal van Best
Delft University of Technology
http://www.tbm.tudelft.nl/webstaf/janb/index.htm 


Index: http.cc
===================================================================
RCS file: /home/kde/kdelibs/kioslave/http/http.cc,v
retrieving revision 1.494
diff -u -3 -p -r1.494 http.cc
--- http.cc	22 Apr 2002 13:00:20 -0000	1.494
+++ http.cc	26 Apr 2002 13:18:32 -0000
@@ -1175,6 +1175,96 @@ void HTTPProtocol::davUnlock( const KURL
     davError();
 }
 
+void HTTPProtocol::davSearch( const KURL &url, const QCString& query )
+{
+  UDSEntry entry;
+  UDSAtom atom;
+  
+  kdDebug() << "(" << m_pid << ") HTTPProtocol::davSearch "
+                << url.prettyURL() << endl;
+
+  if ( !checkRequestURL( url ) )
+    return;
+
+  m_request.method = DAV_SEARCH;
+  m_request.path = url.path();
+  m_request.query = QString::null;
+  m_request.cache = DEFAULT_CACHE_CONTROL;
+  m_request.doProxy = m_bUseProxy;
+  
+  // This doesn't work setMetaData("content-type", "text/xml");
+    
+  /* Create appropriate search XML request. */
+/*  
+  QDomDocument searchReq;
+
+  QDomElement searchInfo = searchReq.createElementNS( "DAV:",
"searchrequest" );
+  // searchInfo.appendChild( searchReq.createTextNode( query ) );
+  QDomCharacterData data;
+  data.setData(query);
+  searchInfo.appendChild ( data );
+  searchReq.appendChild( searchInfo );
+*/  
+  
+  QCString request = "<?xml version=\"1.0\"?>\r\n";
+  request.append("<g:searchrequest xmlns:g=\"DAV:\">\r\n");
+  request.append(query);
+  request.append("</g:searchrequest>\r\n");
+
+  // insert the document into the POST buffer
+  m_bufPOST = request;
+
+  retrieveContent( true );
+
+  if ( m_responseCode == 207 ) {
+    // success
+    QDomDocument multiResponse;
+    multiResponse.setContent( m_intData, true );
+
+    kdDebug() << m_intData << endl;
+
+    for ( QDomElement thisResponse =
multiResponse.documentElement().firstChild().toElement();
+          !thisResponse.isNull();
+          thisResponse = thisResponse.nextSibling().toElement() )
+    {
+      QDomElement href = thisResponse.namedItem( "href" ).toElement();
+      if ( !href.isNull() )
+      {
+        entry.clear();
+
+        KURL thisURL = KURL::decode_string( href.text() );
+        kdDebug() << thisURL.prettyURL() << endl;
+
+        // don't list the base dir of a listDir()
+        if ( thisURL.path(+1).length() == url.path(+1).length() )
+          continue;
+
+        atom.m_uds = KIO::UDS_NAME;
+        atom.m_str = thisURL.filename();
+        entry.append( atom );
+
+        QDomNodeList propstats = thisResponse.elementsByTagName(
"propstat" );
+
+        davParsePropstats( propstats, entry );
+
+        kdDebug() << "Calling listEntry() from
HTTPProtocol::davSearch()" << endl;
+        listEntry( entry, false );
+      }
+      else
+      {
+        kdDebug(7113) << "Error: no URL contained in response to SEARCH
on "
+                      << url.prettyURL() << endl;
+      }
+    }
+    listEntry( entry, true );
+    finished();
+
+  } else {
+    kdDebug(7113) << m_intData << endl;
+    davError();
+  }
+}
+
 QString HTTPProtocol::davError( int code /* = -1 */, QString url )
 {
   bool callError = false;
@@ -1214,6 +1304,9 @@ QString HTTPProtocol::davError( int code
     case DAV_LOCK:
       action = i18n( "lock the specified file or directory" );
       break;
+    case DAV_SEARCH:
+      action = i18n( "search the specified directory using a special
query" );
+      break;
     case DAV_UNLOCK:
       action = i18n( "unlock the specified file or directory" );
       break;
@@ -1807,6 +1900,8 @@ bool HTTPProtocol::httpOpen()
   {
   case HTTP_GET:
       header = "GET ";
+      if (m_protocol == "webdav" || m_protocol == "webdavs")
+        davHeader = "Translate: f\r\n";
       break;
   case HTTP_PUT:
       header = "PUT ";
@@ -1880,6 +1975,12 @@ bool HTTPProtocol::httpOpen()
       davHeader = "Lock-token: " + metaData("davLockToken") + "\r\n";
       m_bCachedWrite = false; // Do not put any result in the cache
       break;
+  case DAV_SEARCH:
+      header = "SEARCH ";
+      davHeader = "Content-Type: text/xml; charset=utf-8\r\n";
+      davData = true;
+      m_bCachedWrite = false;
+      break;
   }
 
   if ( isSSLTunnelEnabled() )
@@ -2109,9 +2210,11 @@ bool HTTPProtocol::httpOpen()
   if ( m_protocol == "webdav" || m_protocol == "webdavs" )
     header += davProcessLocks();
 
-  if ( !moreData )
+  if ( !moreData && !davData) {
     header += "\r\n";  /* end header */
-
+  }
+  
   kdDebug(7103) << "(" << m_pid << ") ============ Sending Header:" <<
endl;
 
   QStringList headerOutput = QStringList::split("\r\n", header);
@@ -3205,7 +3308,8 @@ bool HTTPProtocol::sendBody()
   if ( !m_bufPOST.isNull() )
     {
     kdDebug(7113) << "(" << m_pid << ") POST'ing saved data..." <<
endl;
-    length = m_bufPOST.size();
+    length = m_bufPOST.size()-1; // FIXME: JPvB: substracted because
the Exchange server complains if I don't
+    kdDebug() << "Length is " << length << endl;
     result = 0;
   }
   else
@@ -3374,6 +3480,15 @@ void HTTPProtocol::special( const QByteA
       KURL url;
       stream >> url;
       davUnlock( url );
+      break;
+    }
+    case 7: // WebDAV search
+    {
+      KURL url;
+      QString query;
+      stream >> url >> query;
+      kdDebug() << "URL, query " << url.prettyURL() << "," <<
query.utf8() << endl;
+      davSearch( url, query.utf8() );
       break;
     }
     default:
Index: http.h
===================================================================
RCS file: /home/kde/kdelibs/kioslave/http/http.h,v
retrieving revision 1.127
diff -u -3 -p -r1.127 http.h
--- http.h	17 Apr 2002 07:25:35 -0000	1.127
+++ http.h	26 Apr 2002 13:18:33 -0000
@@ -60,7 +60,7 @@ public:
   /** HTTP / DAV method **/
   enum HTTP_METHOD {HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_HEAD,
HTTP_DELETE,
                     HTTP_OPTIONS, DAV_PROPFIND, DAV_PROPPATCH,
DAV_MKCOL,
-                    DAV_COPY, DAV_MOVE, DAV_LOCK, DAV_UNLOCK };
+                    DAV_COPY, DAV_MOVE, DAV_LOCK, DAV_UNLOCK,
DAV_SEARCH };
 
   /** State of the current Connection **/
   typedef struct
@@ -147,6 +147,9 @@ public:
   void davLock( const KURL& url, const QString& scope,
                 const QString& type, const QString& owner );
   void davUnlock( const KURL& url );
+  
+  // Search using a query in a language the server supports
+  void davSearch( const KURL &url, const QCString& query );
 
   // Calls httpClose() and finished()
   void davFinished();

-------------- next part --------------
A non-text attachment was scrubbed...
Name: searchjob.cpp
Type: application/octet-stream
Size: 4505 bytes
Desc: searchjob.cpp
URL: <https://mail.kde.org/mailman/private/kfm-devel/attachments/20020426/7b8c2a23/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: searchjob.h
Type: application/octet-stream
Size: 2756 bytes
Desc: searchjob.h
URL: <https://mail.kde.org/mailman/private/kfm-devel/attachments/20020426/7b8c2a23/attachment-0001.obj>


More information about the kfm-devel mailing list