[Zope-CVS] CVS: Packages/Moztop/moztopsupport/dav - copy.py:1.1 move.py:1.1 configure.zcml:1.7 mkcol.py:1.2 propfind.py:1.8 views.py:1.4

Sidnei da Silva sidnei@x3ng.com.br
Sat, 29 Mar 2003 12:10:25 -0500


Update of /cvs-repository/Packages/Moztop/moztopsupport/dav
In directory cvs.zope.org:/tmp/cvs-serv26151/moztopsupport/dav

Modified Files:
	configure.zcml mkcol.py propfind.py views.py 
Added Files:
	copy.py move.py 
Log Message:
Adding working propfind with depth, except allprop. MKCOL is working. TRACE and placeholder classes for MOVE and COPY

=== Added File Packages/Moztop/moztopsupport/dav/copy.py ===
##############################################################################
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
##############################################################################
"""DAV method COPY

$Id: copy.py,v 1.1 2003/03/29 17:09:54 sidnei Exp $
"""
__metaclass__ = type

from zope.app.interfaces.file import IWriteDirectory
from zope.app.interfaces.file import IDirectoryFactory
from zope.app.interfaces.container import IZopeWriteContainer
from zope.app.event import publish
from zope.app.event.objectevent import ObjectCreatedEvent
from zope.component import queryAdapter, getAdapter

class COPY:
    """COPY handler
    """

    def __init__(self, context, request):
        self.context = context
        self.request = request

    def COPY(self):
        request = self.request
        destination = request.getHeader('destination', '')
        request.response.setStatus(403)
        return ''


=== Added File Packages/Moztop/moztopsupport/dav/move.py ===
##############################################################################
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
##############################################################################
"""DAV method MOVE

$Id: move.py,v 1.1 2003/03/29 17:09:54 sidnei Exp $
"""
__metaclass__ = type

from zope.app.interfaces.file import IWriteDirectory
from zope.app.interfaces.file import IDirectoryFactory
from zope.app.interfaces.container import IZopeWriteContainer
from zope.app.event import publish
from zope.app.event.objectevent import ObjectCreatedEvent
from zope.component import queryAdapter, getAdapter

class MOVE:
    """MOVE handler
    """

    def __init__(self, context, request):
        self.context = context
        self.request = request

    def MOVE(self):
        request = self.request
        destination = request.getHeader('destination', '')
        request.response.setStatus(403)
        return ''


=== Packages/Moztop/moztopsupport/dav/configure.zcml 1.6 => 1.7 ===
--- Packages/Moztop/moztopsupport/dav/configure.zcml:1.6	Tue Mar 25 16:16:00 2003
+++ Packages/Moztop/moztopsupport/dav/configure.zcml	Sat Mar 29 12:09:54 2003
@@ -4,8 +4,16 @@
  	name="PROPFIND"
 	type="zope.publisher.interfaces.http.IHTTPPresentation"
 	factory=".propfind.PROPFIND"
-	permission="zope.Public"
-	allowed_attributes="PROPFIND"
+	permission="zope.ManageContent"
+	allowed_attributes="PROPFIND setDepth getDepth"
+  />
+
+  <view for="zope.app.interfaces.http.INullResource"
+ 	name="MKCOL"
+	type="zope.publisher.interfaces.http.IHTTPPresentation"
+	factory=".mkcol.NullResource"
+	permission="zope.ManageContent"
+	allowed_attributes="MKCOL"
   />
 
   <view for="*"
@@ -16,6 +24,22 @@
 	allowed_attributes="MKCOL"
   />
 
+  <view for="*"
+ 	name="MOVE"
+	type="zope.publisher.interfaces.http.IHTTPPresentation"
+	factory=".move.MOVE"
+	permission="zope.ManageContent"
+	allowed_attributes="MOVE"
+  />
+
+  <view for="*"
+ 	name="COPY"
+	type="zope.publisher.interfaces.http.IHTTPPresentation"
+	factory=".copy.COPY"
+	permission="zope.ManageContent"
+	allowed_attributes="COPY"
+  />
+
   <view
     for="zope.app.interfaces.content.zpt.IZPTPage"
     type="zope.publisher.interfaces.http.IHTTPPresentation"
@@ -29,7 +53,7 @@
     name="DAVdisplayname"
     type="zope.publisher.interfaces.http.IHTTPPresentation"
     factory=".views.DAVDisplayName"
-    permission="zope.Public"
+    permission="zope.ManageContent"
     />
 
   <view
@@ -37,7 +61,7 @@
     name="DAVcreationdate"
     type="zope.publisher.interfaces.http.IHTTPPresentation"
     factory=".views.DAVCreationDate"
-    permission="zope.Public"
+    permission="zope.ManageContent"
     />
 
   <view
@@ -45,7 +69,31 @@
     name="DAVresourcetype"
     type="zope.publisher.interfaces.http.IHTTPPresentation"
     factory=".views.DAVResourceType"
-    permission="zope.Public"
+    permission="zope.ManageContent"
+    />
+
+  <view
+    for="*"
+    name="DAVexecutable"
+    type="zope.publisher.interfaces.http.IHTTPPresentation"
+    factory=".views.DAVExecutable"
+    permission="zope.ManageContent"
+    />
+
+  <view
+    for="*"
+    name="DAVgetcontentlength"
+    type="zope.publisher.interfaces.http.IHTTPPresentation"
+    factory=".views.DAVContentLength"
+    permission="zope.ManageContent"
+    />
+
+  <view
+    for="*"
+    name="DAVgetlastmodified"
+    type="zope.publisher.interfaces.http.IHTTPPresentation"
+    factory=".views.DAVLastModified"
+    permission="zope.ManageContent"
     />
 
 </zopeConfigure>


=== Packages/Moztop/moztopsupport/dav/mkcol.py 1.1 => 1.2 ===
--- Packages/Moztop/moztopsupport/dav/mkcol.py:1.1	Tue Mar 25 16:16:27 2003
+++ Packages/Moztop/moztopsupport/dav/mkcol.py	Sat Mar 29 12:09:54 2003
@@ -15,8 +15,15 @@
 """
 __metaclass__ = type
 
-class MKCOL:
-    """MKCOL handler for all Collections
+from zope.app.interfaces.file import IWriteDirectory
+from zope.app.interfaces.file import IDirectoryFactory
+from zope.app.interfaces.container import IZopeWriteContainer
+from zope.app.event import publish
+from zope.app.event.objectevent import ObjectCreatedEvent
+from zope.component import queryAdapter, getAdapter
+
+class NullResource:
+    """MKCOL handler for creating collections
     """
 
     def __init__(self, context, request):
@@ -24,5 +31,35 @@
         self.request = request
 
     def MKCOL(self):
+        request = self.request
+        container = self.context.container
+        name = self.context.name
+        
+        dir = queryAdapter(container, IWriteDirectory, None)
+        if dir is None:
+            request.response.setStatus(403)
+            return ''
+        
+        dir = getAdapter(dir, IZopeWriteContainer)
+
+        factory = getAdapter(container, IDirectoryFactory)
+        newdir = factory(name)
+        publish(self.context, ObjectCreatedEvent(newdir))
+        dir.setObject(name, newdir)
+
+        request.response.setStatus(201)
         return ''
 
+class MKCOL:
+    """MKCOL handler for existing objects
+    """
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def MKCOL(self):
+        # 405 (Method Not Allowed) - MKCOL can only be executed on a
+        # deleted/non-existent resource.
+        self.request.response.setStatus(405)
+        return ''


=== Packages/Moztop/moztopsupport/dav/propfind.py 1.7 => 1.8 ===
--- Packages/Moztop/moztopsupport/dav/propfind.py:1.7	Tue Mar 25 16:16:00 2003
+++ Packages/Moztop/moztopsupport/dav/propfind.py	Sat Mar 29 12:09:54 2003
@@ -17,8 +17,10 @@
 
 from xml.dom import minidom
 from zope.component import getAdapter, getView, queryView
+from zope.proxy.context import ContextWrapper
 from zope.proxy.introspection import removeAllProxies
 from zope.schema import getFieldNamesInOrder
+from zope.app.interfaces.container import IReadContainer
 
 from moztopsupport.dav.interfaces import IDAVSource, IDAVSchema
 
@@ -31,113 +33,137 @@
     def __init__(self, context, request):
         self.context = context
         self.request = request
-        self._depth = 'infinity'
+        self.setDepth(request.getHeader('depth', 'infinity'))
+        self.content_type = request.getHeader('content-type', '')
 
     def getDepth(self):
         return self._depth
 
     def setDepth(self, depth):
-        self._depth = depth
+        self._depth = depth.lower()
 
     def PROPFIND(self):
         request = self.request
-        content_type = request.getHeader('content-type', '')
-        hostname = request.getHeader('hostname', '')
+        context = self.context
+        resource_url = str(getView(context, 'absolute_url', request))
+        default_ns = 'DAV:'
         data = request.bodyFile
+        data.seek(0)
         response = ''
         body = ''
 
-        if content_type.lower() not in ['text/xml', 'application/xml']:
+        if self.content_type.lower() not in ['text/xml', 'application/xml']:
             request.response.setStatus(400)
             return body
-
-        depth = request.getHeader('depth', 'infinity')
         
-        if depth.lower() not in ['0', '1', 'infinity']:
+        if self.getDepth() not in ['0', '1', 'infinity']:
             request.response.setStatus(400)
             return body
 
-        self.setDepth(depth)
-
         xmldoc = minidom.parse(data)
+        response = minidom.Document()
+        ms = response.createElementNS(default_ns, 'D:multistatus')
+        ms.setAttributeNS(default_ns, 'xmlns:D', 'DAV:')
+        response.appendChild(ms)
+        re = response.createElementNS(default_ns, 'D:response')
+        ms.appendChild(re)
+        href = response.createElementNS(default_ns, 'D:href')
+        re.appendChild(href)
+        r_url = response.createTextNode(resource_url)
+        href.appendChild(r_url)
 
-        propname = xmldoc.getElementsByTagNameNS('DAV:', 'propname')
+        propname = xmldoc.getElementsByTagNameNS(default_ns, 'propname')
         if propname:
-            props = self._buildProps(_avail_props)
-            ok = self._buildOk(props)
-            body = self._buildBody(ok)
-            request.response.setStatus(207)
-            request.response.setBody(body)
-            return body
+            pstat = response.createElementNS(default_ns, 'D:propstat')
+            re.appendChild(pstat)
+            prop = response.createElementNS(default_ns, 'D:prop')
+            pstat.appendChild(prop)
+            for p in _avail_props:
+                el = response.createElementNS(default_ns, 'D:%s' % p )
+                prop.appendChild(el)
+            status = response.createElementNS(default_ns, 'D:status')
+            pstat.appendChild(status)
+            text = response.createTextNode('HTTP/1.1 200 OK')
+            status.appendChild(text)
 
-        source = xmldoc.getElementsByTagNameNS('DAV:', 'prop')
+        source = xmldoc.getElementsByTagNameNS(default_ns, 'prop')
         if not source:
             # allprop
-            return ''
+            #return ''
+            pass
 
-        source = source[0]
-        childs = [e for e in source.childNodes
-                  if e.nodeType == e.ELEMENT_NODE]
-        not_avail = []
-        for node in childs:
-            localname = node.localName
-            view = queryView(self.context, 'DAV%s' % localname, self.request, None)
-            if view is None:
-                not_avail.append(localname)
-            else:
-                view = removeAllProxies(view)
-                response += str(view)
-
-        if response:
-            response = self._buildOk(response)
-
-        if not_avail:
-            response += self._buildNotAvail(not_avail)
-            
-        body = self._buildBody(response)
+        if source:
+            source = source[0]
+            childs = [e for e in source.childNodes
+                      if e.nodeType == e.ELEMENT_NODE]
+            not_avail = []
+            avail = {}
+            props_ns = {}
+            for node in childs:
+                localname = node.localName
+                props_ns[localname] = node.namespaceURI
+                view = queryView(self.context, 'DAV%s' % localname, self.request, None)
+                if view is None:
+                    not_avail.append(localname)
+                else:
+                    view = removeAllProxies(view)
+                    avail[localname] = str(view)
+
+            if avail:
+                pstat = response.createElementNS(default_ns, 'D:propstat')
+                re.appendChild(pstat)
+                prop = response.createElementNS(default_ns, 'D:prop')
+                pstat.appendChild(prop)
+                status = response.createElementNS(default_ns, 'D:status')
+                pstat.appendChild(status)
+                text = response.createTextNode('HTTP/1.1 200 OK')
+                status.appendChild(text)
+                for p in avail.keys():
+                    ns = props_ns.get(p, None)
+                    if ns is not None:
+                        el = response.createElementNS(ns, '%s' % p )
+                        el.setAttribute('xmlns', ns)
+                    else:
+                        el = response.createElementNS(default_ns, 'D:%s' % p )
+                    prop.appendChild(el)
+                    try:
+                        value = minidom.parseString(avail[p]).documentElement
+                    except:
+                        value = response.createTextNode(avail[p])
+                    el.appendChild(value)
+
+            if not_avail:
+                pstat = response.createElementNS(default_ns, 'D:propstat')
+                re.appendChild(pstat)
+                prop = response.createElementNS(default_ns, 'D:prop')
+                pstat.appendChild(prop)
+                status = response.createElementNS(default_ns, 'D:status')
+                pstat.appendChild(status)
+                text = response.createTextNode('HTTP/1.1 403 Forbidden')
+                status.appendChild(text)
+                for p in not_avail:
+                    el = response.createElementNS(default_ns, 'D:%s' % p )
+                    prop.appendChild(el)
+
+        depth = self.getDepth()
+        if depth == '1':
+            subdepth = '0'
+        if depth == 'infinity':
+            subdepth = 'infinity'
+        if depth != '0':
+            if IReadContainer.isImplementedBy(context):
+                for id, obj in context.items():
+                    wrapped = ContextWrapper(obj, self.context, name=id)
+                    pfind = queryView(wrapped, 'PROPFIND', request, None)
+                    if pfind is not None:
+                        pfind.setDepth(subdepth)
+                        value = pfind.PROPFIND()
+                        parsed = minidom.parseString(value)
+                        responses = parsed.getElementsByTagNameNS(default_ns, 'response')
+                        for r in responses:
+                            ms.appendChild(r)
+                        
+        body = response.toxml('utf-8')
         request.response.setBody(body)
-            
         request.response.setStatus(207)
         return body
-
-    def _buildBody(self, response):
-        resource_url = str(getView(self.context, 'absolute_url', self.request))
-        return self._xml % ({'resource_url':resource_url,
-                             'response':response})
-
-    _xml = '''<?xml version="1.0" encoding="utf-8" ?>
-        <D:multistatus xmlns:D="DAV:">
-          <D:response>
-            <D:href>%(resource_url)s</D:href>
-            %(response)s
-         </D:response>
-       </D:multistatus>
-    '''
-
-    def _buildProps(self, props):
-        result = ''
-        for p in props:
-            result += '<D:%s />' % p
-        return result
-
-    def _buildOk(self, response):
-        return self._ok_xml % {'response':response}
-
-    _ok_xml = '''<D:propstat>
-    <D:prop>%(response)s</D:prop>
-    <D:status>HTTP/1.1 200 OK</D:status>
-    </D:propstat>'''
-
-    def _buildNotAvail(self, props):
-        props = self._buildProps(props)
-        return self._not_avail_xml % {'props':props}
-
-    _not_avail_xml = '''<D:propstat>
-        <D:prop>
-        %(props)s
-        </D:prop>
-        <D:status>HTTP/1.1 403 Forbidden</D:status>
-        <D:responsedescription> The user does not have access to this resource.
-        </D:responsedescription>
-        </D:propstat>
-        '''


=== Packages/Moztop/moztopsupport/dav/views.py 1.3 => 1.4 ===
--- Packages/Moztop/moztopsupport/dav/views.py:1.3	Mon Mar 24 17:23:04 2003
+++ Packages/Moztop/moztopsupport/dav/views.py	Sat Mar 29 12:09:54 2003
@@ -1,7 +1,11 @@
+from xml.dom import minidom
 from zope.component import getView, getAdapter, queryAdapter
 from zope.app.interfaces.traversing import IObjectName
 from zope.app.interfaces.dublincore import IDCTimes
 from zope.app.interfaces.container import IReadContainer
+from zope.app.interfaces.file import IReadFile
+from zope.app.interfaces.file import IReadDirectory
+from zope.app.interfaces.size import ISized
 from zope.publisher.browser import BrowserView
 
 from moztopsupport.dav.interfaces import IDAVSource, IDAVDisplayName, IDAVCreationDate
@@ -13,66 +17,92 @@
     def __str__(self):
         resource_url = str(getView(self.context, 'absolute_url', self.request))
         source_url = '%s/getSource' % resource_url
-        return self._xml % {'resource_url':resource_url,
-                            'source_url':source_url}
+        xml = minidom.Document()
+        link = xml.createElementNS('DAV:', 'D:link')
+        xml.appendChild(link)
+        src = xml.createElementNS('DAV:', 'D:src')
+        link.appendChild(src)
+        r_url = xml.createTextNode(resource_url)
+        src.appendChild(r_url)
+        dst = xml.createElementNS('DAV:', 'D:dst')
+        link.appendChild(dst)
+        s_url = xml.createTextNode(source_url)
+        dst.appendChild(s_url)
+        return xml.documentElement.toxml()
 
     __call__ = __str__
     
-    _xml = '''
-    <D:source>
-      <D:link>
-       <D:src>%(resource_url)s</D:src>
-       <D:dst>%(source_url)s</D:dst>
-      </D:link>
-    </D:source>
-    '''
-
 class DAVDisplayName(BrowserView):
 
     __implements__ = IDAVDisplayName
 
     def __str__(self):
         value = getAdapter(self.context, IObjectName)()
-        return self._xml % {'value':value}
+        xml = minidom.Document()
+        text = xml.createTextNode(value)
+        return text.toxml()
 
     __call__ = __str__
     
-    _xml = '''
-    <D:displayname>
-      %(value)s
-    </D:displayname>
-    '''
-
 class DAVCreationDate(BrowserView):
 
     __implements__ = IDAVCreationDate
 
     def __str__(self):
         value = getAdapter(self.context, IDCTimes).created
-        return self._xml % {'value':value}
+        if value is None:
+            return ''
+        value = value.strftime('%Y-%m-%d %TZ')
+        xml = minidom.Document()
+        text = xml.createTextNode(value)
+        return text.toxml()
 
     __call__ = __str__
     
-    _xml = '''
-    <D:creationdate>
-      %(value)s
-    </D:creationdate>
-    '''
-
 class DAVResourceType(BrowserView):
 
     def __str__(self):
         value = queryAdapter(self.context, IReadContainer)
+        xml = minidom.Document()
         if value is not None:
-            value = '<D:collection />'
-        else:
-            value = ''
-        return self._xml % {'value':value}
+            node = xml.createElementNS('DAV:', 'D:collection')
+            xml.appendChild(node)
+        doc = xml.documentElement
+        if doc is None:
+            return ''
+        return doc.toxml()
+
+    __call__ = __str__
+    
+class DAVContentLength(BrowserView):
+
+    def __str__(self):
+        value = getAdapter(self.context, ISized).sizeForDisplay()
+        value = str(value)
+        xml = minidom.Document()
+        text = xml.createTextNode(value)
+        return text.toxml()
+
 
     __call__ = __str__
     
-    _xml = '''
-    <D:resourcetype>
-      %(value)s
-    </D:resourcetype>
-    '''
+class DAVLastModified(BrowserView):
+
+    def __str__(self):
+        value = getAdapter(self.context, IDCTimes).modified
+        if value is None:
+            return ''
+        value = value.strftime('%a, %d %b %Y %H:%M:%S GMT')
+        xml = minidom.Document()
+        text = xml.createTextNode(value)
+        return text.toxml()
+
+    __call__ = __str__
+
+
+class DAVExecutable(BrowserView):
+
+    def __str__(self):
+        return ''
+
+    __call__ = __str__