[Zope-CVS] CVS: Products/ExternalEditor - ExternalEditor.py:1.12 README.txt:1.4 zopeedit.py:1.32

Casey Duncan casey@zope.com
Wed, 17 Jul 2002 17:49:03 -0400


Update of /cvs-repository/Products/ExternalEditor
In directory cvs.zope.org:/tmp/cvs-serv16980

Modified Files:
	ExternalEditor.py README.txt zopeedit.py 
Log Message:
Added capability to borrow existing locks. This allows external editor to work
with CMFStaging which also uses DAV locks (on the server side).
Added always_borrow_locks option to suppress warning dialog.


=== Products/ExternalEditor/ExternalEditor.py 1.11 => 1.12 ===
 import Acquisition
 from AccessControl.SecurityManagement import getSecurityManager
 from webdav.common import rfc1123_date
+from webdav import Lockable
 
 class ExternalEditor(Acquisition.Implicit):
     """Create a response that encapsulates the data needed by the
@@ -64,7 +65,21 @@
                 
             r.append('auth:%s' % auth)
             
-        r.append('cookie:%s' % REQUEST.environ.get('HTTP_COOKIE',''))            
+        r.append('cookie:%s' % REQUEST.environ.get('HTTP_COOKIE',''))
+        
+        if Lockable.wl_isLocked(ob):
+            # Object is locked, send down the lock token 
+            # owned by this user (if any)
+            user_id = security.getUser().getId()
+            for lock in ob.wl_lockValues():
+                if not lock.isValid():
+                    continue # Skip invalid/expired locks
+                creator = lock.getCreator()
+                if creator and creator[1] == user_id:
+                    # Found a lock for this user, so send it
+                    r.append('lock-token:%s' % lock.getLockToken())
+                    break       
+              
         r.append('')
         
         if hasattr(ob, 'manage_FTPget'):


=== Products/ExternalEditor/README.txt 1.3 => 1.4 ===
       application checks the edited file for changes.
 
       use_locks -- (1 or 0) Whether to use WebDAV locking.
+      
+      always_borrow_locks -- (1 or 0) When use_locks is enabled this features
+      suppresses warnings when trying to edit an object you have already locked.
+      When enabled, external editor will always "borrow" the existing lock token
+      instead of doing the locking itself. This is useful when using CMFStaging
+      for instance. If omitted, this option defaults to 0. (new in 0.5)
 
       cleanup_files -- (1 or 0) Whether to delete the temp files created.
       WARNING the temp file coming from the browser contains authentication
@@ -154,7 +160,7 @@
       better handling of images and can improve syntax highlighting.
 
       temp_dir -- (path) Path to store local copies of object data being
-      edited. Defaults to operating system temp directory (new in 0.3).
+      edited. Defaults to operating system temp directory.
 
     Sections
     


=== Products/ExternalEditor/zopeedit.py 1.31 => 1.32 ===
 from urlparse import urlparse
 import urllib
 
+try:
+    # See if ssl is available on this system
+    from socket import ssl, sslerror
+except ImportError:
+    ssl_available = 0
+    sslerror = None # Used for catching sslserver protocol violations
+else:
+    ssl_available = 1
+    del ssl 
+
 win32 = sys.platform == 'win32'
 
 class Configuration:
@@ -86,6 +96,7 @@
 class ExternalEditor:
     
     saved = 1
+    did_lock = 0
     
     def __init__(self, input_file):
         try:
@@ -155,14 +166,10 @@
                 except OSError:
                     pass # Sometimes we aren't allowed to delete it
             
-            if self.ssl:
-                # See if our Python build supports ssl
-                try:
-                    from socket import ssl
-                except ImportError:
-                    fatalError('SSL support is not available on this system. '
-                               'Make sure openssl is installed '
-                               'and reinstall Python.')
+            if self.ssl and not ssl_available:
+                fatalError('SSL support is not available on this system. '
+                           'Make sure openssl is installed '
+                           'and reinstall Python.')
         except:
             # for security, always delete the input file even if
             # a fatal error occurs, unless explicitly stated otherwise
@@ -181,7 +188,7 @@
             # for security we always delete the files by default
             os.remove(self.content_file)
 
-        if hasattr(self, 'lock_token'):
+        if self.did_lock and hasattr(self, 'lock_token'):
             # Try not to leave dangling locks on the server
             self.unlock(interactive=0)
             
@@ -303,7 +310,7 @@
         editor = EditorProcess(command)
         
         if use_locks:
-            self.lock()
+            self.did_lock = self.lock()
             
         while 1:
             editor.wait(save_interval or 2)
@@ -326,8 +333,8 @@
                        'to editor process.\n'
                        '(%s)' % command)
         
-        if use_locks:
-            self.unlock()
+        if use_locks and self.did_lock:
+            self.did_lock = not self.unlock()
         
         if not self.saved \
            and askYesNo('File not saved to Zope.\nReopen local copy?'):
@@ -369,6 +376,18 @@
     def lock(self):
         """Apply a webdav lock to the object in Zope"""
         
+        # Check and see if we already have a lock token
+        # that came down with the data
+        if self.metadata.get('lock-token'):
+            if self.options.get('always_borrow_locks') \
+               or askYesNo('This object is already locked by you in another'
+                           ' session.\n Do you want to borrow this lock?'):
+                self.lock_token = 'opaquelocktoken:%s' \
+                                  % self.metadata['lock-token']
+                return 0
+            else:
+                sys.exit()            
+        
         headers = {'Content-Type':'text/xml; charset="utf-8"',
                    'Timeout':'infinite',
                    'Depth':'infinity',
@@ -392,7 +411,7 @@
             token_start = reply.find('>opaquelocktoken:')
             token_end = reply.find('<', token_start)
             if token_start > 0 and token_end > 0:
-               self.lock_token = reply[token_start+1:token_end]
+                self.lock_token = reply[token_start+1:token_end]
         else:
             # We can't lock her sir!
             if response.status == 423: