webdav search

Best, Jan-Pascal van j.p.vanbest at tbm.tudelft.nl
Fri May 3 10:10:48 BST 2002


Hi all,

I've worked some more on the webdav search code. Find diff below.
The suggestions by Hamish and Waldo have been incorporated.
Some remarks:
- search is made a special case of listDir in stead of of stat, since
search usually gives a bunch of responses (for instance, every
appointment in a certain period of time), like list. Using a 
ListJob seems to be the natural way for this.
- The special() for SEARCH might be removed, since SEARCH can be done
via listDir(). What do you think?
- I've modified the signature for davStatlist() since it now has three 
uses, for stat, list and search. It now takes an enum argument for
the use method, and a QString for the search query (defaults to null).
The listDir() method distinguishes between list and search by checking
the davSearchQuery metadata. If it exists, it's a SEARCH...
- In httpOpen(), I've grouped together some of the webdav-related
header options for clarity
- I've tried the webdav list using konqi and it still works. Haven't 
really tried the stat, but the creation dates of webdav elements in
konqi seem to be OK

- Use cases:
  QString query = 
        "<D:sql> "
        "  SELECT \"DAV:displayname\"\r\n"
        "  FROM Scope('shallow traversal of \"\"')\r\n"
        "  WHERE \"urn:schemas:calendar:dtend\" > '2002/05/01'\r\n"
        "  AND \"urn:schemas:calendar:dtstart\" < '2002/05/03'\r\n"
        "</D:sql>\r\n";

  KIO::ListJob *job = KIO::listDir(url, true);
  job->addMetaData("davSearchQuery", query);
  connect(job, SIGNAL(entries( KIO::Job *, const KIO::UDSEntryList& )),
this, SLOT(slotEntries(KIO::Job *, const KIO::UDSEntryList&)));

And for the Translate: f flag stuff, now moved out of the ioslave
  KIO::TransferJob *job = KIO::get(url, false, false);
  job->addMetaData("dav-header", "Translate: f\r\n");

Is there more to be done to this patch (except maybe removing the
stuff in special()) before it can go in?

Cheers

Jan-Pascal
janpascal at vanbest.org




Index: http.cc
===================================================================
RCS file: /home/kde/kdelibs/kioslave/http/http.cc,v
retrieving revision 1.496
diff -u -3 -p -r1.496 http.cc
--- http.cc	2 May 2002 01:18:20 -0000	1.496
+++ http.cc	3 May 2002 08:15:08 -0000
@@ -458,10 +458,21 @@ void HTTPProtocol::listDir( const KURL& 
   if ( !checkRequestURL( url ) )
     return;
 
-  davStatList( url, false );
+  if ( m_protocol == "webdav" || m_protocol == "webdavs" )
+  {
+    // Maybe it's a disguised SEARCH...
+    QString query = metaData("davSearchQuery");
+    if ( !query.isEmpty() ) 
+    {
+      davStatList( url, STATLIST_SEARCH, query );
+      return;
+    }
+  }
+  
+  davStatList( url, STATLIST_LIST );
 }
 
-void HTTPProtocol::davStatList( const KURL& url, bool stat )
+void HTTPProtocol::davStatList( const KURL& url, const STATLISTMETHOD
method /* = STATLIST_STAT */ , const QString &query /* = QString::null
*/ )
 {
   UDSEntry entry;
   UDSAtom atom;
@@ -470,14 +481,25 @@ void HTTPProtocol::davStatList( const KU
   if ( !davHostOk() )
     return;
 
-  // WebDAV Stat or List...
-  m_request.method = DAV_PROPFIND;
+  m_request.method = method == STATLIST_SEARCH ? DAV_SEARCH :
DAV_PROPFIND;
   m_request.query = QString::null;
   m_request.cache = CC_Reload;
   m_request.doProxy = m_bUseProxy;
-  m_request.davData.depth = stat ? 0 : 1;
-  if (!stat)
+  m_request.davData.depth = method == STATLIST_LIST ? 1 : 0;
+  if (method == STATLIST_LIST)
      m_request.url.adjustPath(+1);
+     
+  if ( method == STATLIST_SEARCH )
+  {
+    QCString request = "<?xml version=\"1.0\"?>\r\n";
+    request.append( "<D:searchrequest xmlns:D=\"DAV:\">\r\n" );
+    request.append( query.utf8() );
+    request.append( "</D:searchrequest>\r\n" );
+
+    // insert the document into the POST buffer, kill trailing zero
byte
+    m_bufPOST = request;
+    if (m_bufPOST.size()) m_bufPOST.truncate( m_bufPOST.size() - 1 );
+  }
 
   retrieveContent( true );
 
@@ -496,7 +518,7 @@ void HTTPProtocol::davStatList( const KU
       KURL thisURL = KURL::decode_string( href.text() );
 
       // don't list the base dir of a listDir()
-      if ( !stat && thisURL.path(+1).length() == url.path(+1).length()
)
+      if ( method==STATLIST_LIST && thisURL.path(+1).length() ==
url.path(+1).length() )
         continue;
 
       atom.m_uds = KIO::UDS_NAME;
@@ -507,7 +529,7 @@ void HTTPProtocol::davStatList( const KU
 
       davParsePropstats( propstats, entry );
 
-      if ( stat )
+      if ( method == STATLIST_STAT )
       {
         // return an item
         statEntry( entry );
@@ -526,7 +548,7 @@ void HTTPProtocol::davStatList( const KU
     }
   }
 
-  if ( stat )
+  if ( method == STATLIST_STAT )
   {
     error( ERR_DOES_NOT_EXIST, url.prettyURL() );
   }
@@ -1166,7 +1188,7 @@ void HTTPProtocol::davUnlock( const KURL
   m_request.query = QString::null;
   m_request.cache = CC_Reload;
   m_request.doProxy = m_bUseProxy;
-
+  
   retrieveContent( true );
 
   if ( m_responseCode == 200 )
@@ -1214,6 +1325,9 @@ QString HTTPProtocol::davError( int code
     case DAV_LOCK:
       action = i18n( "lock the specified file or directory" );
       break;
+    case DAV_SEARCH:
+      action = i18n( "search in the specified directory" );
+      break;
     case DAV_UNLOCK:
       action = i18n( "unlock the specified file or directory" );
       break;
@@ -1880,6 +1994,11 @@ 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 ";
+      davData = true;
+      m_bCachedWrite = false;
+      break;
   }
 
   if ( isSSLTunnelEnabled() )
@@ -2004,7 +2123,6 @@ bool HTTPProtocol::httpOpen()
     if (!m_request.languages.isEmpty())
       header += "Accept-Language: " + m_request.languages + "\r\n";
 
-
     /* support for virtual hosts and required by HTTP 1.1 */
     header += "Host: ";
     if (m_state.hostname.find(':') != -1)
@@ -2101,17 +2219,29 @@ bool HTTPProtocol::httpOpen()
     if ( m_state.doProxy && !m_bIsTunneled )
       header += proxyAuthenticationHeader();
   }
-
-  // add extra header elements for WebDAV
-  if ( !davHeader.isNull() )
-    header += davHeader;
-
-  if ( m_protocol == "webdav" || m_protocol == "webdavs" )
+  
+  if ( m_protocol == "webdav" || m_protocol == "webdavs" ) 
+  {
     header += davProcessLocks();
+    
+    // add extra webdav headers, if supplied
+    QString davExtraHeader = metaData("dav-header");
+    kdDebug() << "(" << m_pid << ") dav-header: " << davExtraHeader <<
endl;
+    if ( !davExtraHeader.isEmpty() )
+      davHeader += davExtraHeader;
+
+    // Set content type of webdav data
+    if (davData)
+      davHeader += "Content-Type: text/xml; charset=utf-8\r\n";
+  
+    // add extra header elements for WebDAV
+    if ( !davHeader.isNull() )
+     header += davHeader;
+  }
 
-  if ( !moreData )
+  if ( !moreData && !davData)
     header += "\r\n";  /* end header */
-
+    
   kdDebug(7103) << "(" << m_pid << ") ============ Sending Header:" <<
endl;
 
   QStringList headerOutput = QStringList::split("\r\n", header);
@@ -3382,6 +3503,14 @@ void HTTPProtocol::special( const QByteA
       davUnlock( url );
       break;
     }
+    case 7: // WebDAV search
+    {
+      KURL url;
+      QString query;
+      stream >> url >> query;
+      davStatList( url, STATLIST_SEARCH, query );
+      break;
+    }
     default:
       // Some command we don't understand.
       // Just ignore it, it may come from some future version of KDE.
 
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	3 May 2002 08:15:08 -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
@@ -161,8 +161,9 @@ public:
    * 2 - Cache has been updated
    * 3 - SSL Certificate Cache has been updated
    * 4 - HTTP multi get
-   * 5 - DAV LOCK     (see
-   * 6 - DAV UNLOCK     README.webdav)
+   * 5 - DAV LOCK     (
+   * 6 - DAV UNLOCK   ( see README.webdav
+   * 7 - DAV SEARCH   (
    */
   virtual void special( const QByteArray &data );
 
@@ -238,8 +239,10 @@ protected:
 
   /**
    * Performs a WebDAV stat or list
+   * query is only relevant if method==STATLIST_SEARCH
    */
-  void davStatList( const KURL& url, bool stat = true );
+  enum STATLISTMETHOD { STATLIST_STAT, STATLIST_LIST, STATLIST_SEARCH
};
+  void davStatList( const KURL& url, STATLISTMETHOD method =
STATLIST_STAT, const QString &query = QString::null );
   void davParsePropstats( const QDomNodeList& propstats, KIO::UDSEntry&
entry );
   void davParseActiveLocks( const QDomNodeList& activeLocks,
                             uint& lockCount );
Index: README.webdav
===================================================================
RCS file: /home/kde/kdelibs/kioslave/http/README.webdav,v
retrieving revision 1.3
diff -u -3 -p -r1.3 README.webdav
--- README.webdav	20 Jan 2002 12:15:09 -0000	1.3
+++ README.webdav	3 May 2002 08:15:08 -0000
@@ -26,6 +26,19 @@ are passed as element davSource.
 
 Content languages are passed as element davContentLanguage.
 
+Extra webdav headers are passed as metadata element dav-header
+
+=== webdav SEARCH ===
+To do a webdav SEARCH, either call a special request or use listDir().
+The special request should have the following data:
+int, value 7 (SEARCH request)
+KURL url
+QString query
+
+If you use listDir(), set the metadata element davSearchQuery to the 
+search query. The root element of this query should be like
+<d:basicsearch> or <d:sql>.
+
 === CREATING A LOCK ===
 To create a lock, call a special request, with the following data:
 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: winmail.dat
Type: application/ms-tnef
Size: 7086 bytes
Desc: not available
URL: <https://mail.kde.org/mailman/private/kfm-devel/attachments/20020503/e341edc1/attachment.bin>


More information about the kfm-devel mailing list