Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
3beb18c2
Commit
3beb18c2
authored
Jan 31, 2001
by
Jeffrey Shell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merging in WriteLocking. Yeehaw!
parent
9563f2bc
Changes
32
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1825 additions
and
114 deletions
+1825
-114
lib/python/AccessControl/User.py
lib/python/AccessControl/User.py
+2
-2
lib/python/App/ApplicationManager.py
lib/python/App/ApplicationManager.py
+5
-1
lib/python/App/DavLockManager.py
lib/python/App/DavLockManager.py
+93
-0
lib/python/App/dtml/davLockManager.dtml
lib/python/App/dtml/davLockManager.dtml
+98
-0
lib/python/App/dtml/manage_tabs.dtml
lib/python/App/dtml/manage_tabs.dtml
+5
-0
lib/python/OFS/DTMLDocument.py
lib/python/OFS/DTMLDocument.py
+12
-1
lib/python/OFS/DTMLMethod.py
lib/python/OFS/DTMLMethod.py
+11
-1
lib/python/OFS/Folder.py
lib/python/OFS/Folder.py
+4
-2
lib/python/OFS/Image.py
lib/python/OFS/Image.py
+12
-1
lib/python/OFS/PropertySheets.py
lib/python/OFS/PropertySheets.py
+15
-1
lib/python/OFS/dtml/documentEdit.dtml
lib/python/OFS/dtml/documentEdit.dtml
+10
-2
lib/python/OFS/dtml/fileEdit.dtml
lib/python/OFS/dtml/fileEdit.dtml
+12
-4
lib/python/OFS/dtml/imageEdit.dtml
lib/python/OFS/dtml/imageEdit.dtml
+12
-4
lib/python/OFS/dtml/main.dtml
lib/python/OFS/dtml/main.dtml
+5
-0
lib/python/OFS/misc_.py
lib/python/OFS/misc_.py
+2
-0
lib/python/Products/OFSP/help/DavLocks-ManageLocks.stx
lib/python/Products/OFSP/help/DavLocks-ManageLocks.stx
+36
-0
lib/python/Products/PythonScripts/PythonScript.py
lib/python/Products/PythonScripts/PythonScript.py
+9
-1
lib/python/Products/PythonScripts/www/pyScriptEdit.dtml
lib/python/Products/PythonScripts/www/pyScriptEdit.dtml
+11
-3
lib/python/Products/ZSQLMethods/SQL.py
lib/python/Products/ZSQLMethods/SQL.py
+4
-2
lib/python/Products/ZSQLMethods/dtml/edit.dtml
lib/python/Products/ZSQLMethods/dtml/edit.dtml
+8
-4
lib/python/Shared/DC/ZRDB/DA.py
lib/python/Shared/DC/ZRDB/DA.py
+6
-2
lib/python/webdav/Collection.py
lib/python/webdav/Collection.py
+43
-7
lib/python/webdav/EtagSupport.py
lib/python/webdav/EtagSupport.py
+126
-0
lib/python/webdav/LockItem.py
lib/python/webdav/LockItem.py
+160
-0
lib/python/webdav/Lockable.py
lib/python/webdav/Lockable.py
+111
-0
lib/python/webdav/NullResource.py
lib/python/webdav/NullResource.py
+294
-13
lib/python/webdav/Resource.py
lib/python/webdav/Resource.py
+220
-43
lib/python/webdav/WriteLockInterface.py
lib/python/webdav/WriteLockInterface.py
+198
-0
lib/python/webdav/client.py
lib/python/webdav/client.py
+3
-2
lib/python/webdav/common.py
lib/python/webdav/common.py
+68
-2
lib/python/webdav/davcmds.py
lib/python/webdav/davcmds.py
+219
-16
lib/python/webdav/dtml/locknullmain.dtml
lib/python/webdav/dtml/locknullmain.dtml
+11
-0
No files found.
lib/python/AccessControl/User.py
View file @
3beb18c2
...
...
@@ -84,7 +84,7 @@
##############################################################################
"""Access control package"""
__version__
=
'$Revision: 1.13
8
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.13
9
$'
[
11
:
-
2
]
import
Globals
,
socket
,
ts_regex
,
SpecialUsers
import
os
...
...
@@ -536,7 +536,7 @@ class BasicUserFolder(Implicit, Persistent, Navigation, Tabs, RoleManager,
return
None
def
authorize
(
self
,
user
,
accessed
,
container
,
name
,
value
,
roles
):
newSecurityManager
(
None
,
user
)
newSecurityManager
(
None
,
user
.
__of__
(
self
)
)
security
=
getSecurityManager
()
try
:
try
:
...
...
lib/python/App/ApplicationManager.py
View file @
3beb18c2
...
...
@@ -83,7 +83,7 @@
#
##############################################################################
__doc__
=
"""System management components"""
__version__
=
'$Revision: 1.6
4
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.6
5
$'
[
11
:
-
2
]
import
sys
,
os
,
time
,
string
,
Globals
,
Acquisition
,
os
,
Undo
...
...
@@ -91,6 +91,7 @@ from Globals import DTMLFile
from
OFS.ObjectManager
import
ObjectManager
from
OFS.Folder
import
Folder
from
CacheManager
import
CacheManager
from
DavLockManager
import
DavLockManager
from
DateTime.DateTime
import
DateTime
from
OFS
import
SimpleItem
from
App.Dialogs
import
MessageDialog
...
...
@@ -258,6 +259,7 @@ class ApplicationManager(Folder,CacheManager):
Database
=
DatabaseManager
()
Versions
=
VersionManager
()
DebugInfo
=
DebugManager
()
DavLocks
=
DavLockManager
()
manage
=
manage_main
=
DTMLFile
(
'dtml/cpContents'
,
globals
())
manage_undoForm
=
DTMLFile
(
'dtml/undo'
,
globals
())
...
...
@@ -276,6 +278,8 @@ class ApplicationManager(Folder,CacheManager):
'meta_type'
:
Database
.
meta_type
},
{
'id'
:
'Versions'
,
'meta_type'
:
Versions
.
meta_type
},
{
'id'
:
'DavLocks'
,
'meta_type'
:
DavLocks
.
meta_type
},
{
'id'
:
'Products'
,
'meta_type'
:
'Product Management'
},
{
'id'
:
'DebugInfo'
,
...
...
lib/python/App/DavLockManager.py
0 → 100644
View file @
3beb18c2
import
OFS
,
Acquisition
,
Globals
from
AccessControl
import
getSecurityManager
,
ClassSecurityInfo
from
webdav.Lockable
import
wl_isLocked
class
DavLockManager
(
OFS
.
SimpleItem
.
Item
,
OFS
.
FindSupport
.
FindSupport
,
Acquisition
.
Implicit
):
id
=
'DavLockManager'
name
=
title
=
'WebDAV Lock Manager'
meta_type
=
'WebDAV Lock Manager'
icon
=
'p_/davlocked'
security
=
ClassSecurityInfo
()
security
.
declareProtected
(
'Manage WebDAV Locks'
,
'findLockedObjects'
,
'manage_davlocks'
,
'manage_unlockObjects'
)
security
.
declarePrivate
(
'unlockObjects'
)
manage_davlocks
=
manage_main
=
manage
=
Globals
.
DTMLFile
(
'dtml/davLockManager'
,
globals
())
manage_options
=
(
{
'label'
:
'Write Locks'
,
'action'
:
'manage_main'
,
'help'
:
(
'OFSP'
,
'DavLocks-ManageLocks.stx'
),
},
)
def
locked_in_version
(
self
):
return
0
def
findLockedObjects
(
self
,
frompath
=
''
):
app
=
self
.
getPhysicalRoot
()
if
frompath
:
if
frompath
[
0
]
==
'/'
:
frompath
=
frompath
[
1
:]
# since the above will turn '/' into an empty string, check
# for truth before chopping a final slash
if
frompath
and
frompath
[
-
1
]
==
'/'
:
frompath
=
frompath
[:
-
1
]
# Now we traverse to the node specified in the 'frompath' if
# the user chose to filter the search, and run a ZopeFind with
# the expression 'wl_isLocked()' to find locked objects.
obj
=
app
.
unrestrictedTraverse
(
frompath
)
lockedobjs
=
self
.
_findapply
(
obj
,
path
=
frompath
)
return
lockedobjs
def
unlockObjects
(
self
,
paths
=
[]):
app
=
self
.
getPhysicalRoot
()
for
path
in
paths
:
ob
=
app
.
unrestrictedTraverse
(
path
)
ob
.
wl_clearLocks
()
def
manage_unlockObjects
(
self
,
paths
=
[],
REQUEST
=
None
):
" Management screen action to unlock objects. "
if
paths
:
self
.
unlockObjects
(
paths
)
if
REQUEST
is
not
None
:
m
=
'%s objects unlocked.'
%
len
(
paths
)
return
self
.
manage_davlocks
(
self
,
REQUEST
,
manage_tabs_message
=
m
)
def
_findapply
(
self
,
obj
,
result
=
None
,
path
=
''
):
# recursive function to actually dig through and find the locked
# objects.
if
result
is
None
:
result
=
[]
base
=
Acquisition
.
aq_base
(
obj
)
if
not
hasattr
(
base
,
'objectItems'
):
return
result
try
:
items
=
obj
.
objectItems
()
except
:
return
result
addresult
=
result
.
append
for
id
,
ob
in
items
:
if
path
:
p
=
'%s/%s'
%
(
path
,
id
)
else
:
p
=
id
dflag
=
hasattr
(
ob
,
'_p_changed'
)
and
(
ob
.
_p_changed
==
None
)
bs
=
Acquisition
.
aq_base
(
ob
)
if
wl_isLocked
(
bs
):
li
=
[]
addlockinfo
=
li
.
append
for
token
,
lock
in
bs
.
wl_lockItems
():
addlockinfo
({
'owner'
:
lock
.
getCreatorPath
(),
'token'
:
token
})
addresult
(
p
,
li
)
dflag
=
0
if
hasattr
(
bs
,
'objectItems'
):
self
.
_findapply
(
ob
,
result
,
p
)
if
dflag
:
ob
.
_p_deactivate
()
return
result
Globals
.
default__class_init__
(
DavLockManager
)
lib/python/App/dtml/davLockManager.dtml
0 → 100644
View file @
3beb18c2
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<script type="text/javascript">
<!--
isSelected = false;
function toggleSelect() {
if (isSelected == false) {
for (i = 0; i < document.objectItems.length; i++)
document.objectItems.elements[i].checked = true ;
isSelected = true;
document.objectItems.selectButton.value = "Deselect All";
return isSelected;
}
else {
for (i = 0; i < document.objectItems.length; i++)
document.objectItems.elements[i].checked = false ;
isSelected = false;
document.objectItems.selectButton.value = "Select All";
return isSelected;
}
}
//-->
</script>
<dtml-let lockedobjs="findLockedObjects(frompath=REQUEST.get('frompath',''))">
<dtml-if lockedobjs>
<p class="std-text">All locked objects
<dtml-if frompath>from path <em>&dtml-frompath;</em></dtml-if>
are listed below.</p>
<dtml-else>
<p class="std-text">No locked objects
<dtml-if frompath>from path <em>&dtml-frompath;</em></dtml-if>
were found.</p>
</dtml-if>
<form action="&dtml-URL0;" name="finderform">
<p class="std-text">Search for locked objects starting from path:
<input type="text" size="14" name="frompath" value="&dtml.missing-frompath;"
class="form-element" />
<input type="submit" value="Go" class="form-element" />
</p>
</form>
<form action="manage_unlockObjects" name="objectItems" method="post">
<dtml-if lockedobjs>
<table width="100%" cellspacing="0" cellpadding="2" border="0">
<tr class="list-header">
<td width="60%" class="list-item">Locked Item</td>
<td width="40%" class="list-item">Lock Info</td>
</tr>
</table>
<table width="100%" cellspacing="0" cellpadding="2" border="0">
<dtml-in lockedobjs>
<dtml-if sequence-odd>
<tr class="row-normal">
<dtml-else>
<tr class="row-hilite">
</dtml-if sequence-odd>
<td align="left" valign="top" width="16">
<input type="checkbox" name="paths:list" value="&dtml-sequence-key;"
id="cb_&dtml-sequence-index;" />
</td>
<td align="left" valign="top" width="16">
<dtml-if icon>
<img src="&dtml-BASEPATH1;/&dtml-icon;" alt="[&dtml-meta_type;]"
title="[&dtml-meta_type;]" />
</dtml-if icon>
</td>
<td align="left" valign="top" class="list-item">
<label for="cb_&dtml-sequence-index;">&dtml-sequence-key;</label>
</td>
<td align="left" valign="top" width="40%" class="list-item">
<dtml-in sequence-item mapping>
<strong>Owner:</strong> &dtml-owner;,
<strong>Token:</strong> &dtml-token;<br />
</dtml-in>
</td>
</tr>
</dtml-in lockedobjs>
</table>
<input type="hidden" name="frompath" value="&dtml.missing-frompath;" />
<script type="text/javascript">
<!--
document.write('<input class="form-element" type="button" name="selectButton" value="Select All" onClick="toggleSelect(); return false">')
//-->
</script>
<input class="form-element" type="submit" value="Unlock objects" />
</dtml-if>
</form>
</dtml-let>
<dtml-var manage_page_footer>
lib/python/App/dtml/manage_tabs.dtml
View file @
3beb18c2
...
...
@@ -125,6 +125,11 @@
(<em><dtml-var locked_in_version></em>)
</dtml-if>
</dtml-if>
<dtml-if wl_isLocked>
<img src="&dtml-BASEPATH1;/p_/davlocked"
alt="This item has been locked by WebDAV"
title="This item has been locked by WebDAV" />
</dtml-if wl_isLocked>
</div>
</td>
<dtml-if "_.has_key('help_topic') and _.has_key('help_product')">
...
...
lib/python/OFS/DTMLDocument.py
View file @
3beb18c2
...
...
@@ -84,7 +84,8 @@
##############################################################################
"""DTML Document objects."""
__version__
=
'$Revision: 1.42 $'
[
11
:
-
2
]
__version__
=
'$Revision: 1.43 $'
[
11
:
-
2
]
from
DocumentTemplate.DT_Util
import
InstanceDict
,
TemplateDict
from
ZPublisher.Converters
import
type_converters
from
Globals
import
HTML
,
DTMLFile
,
MessageDialog
...
...
@@ -92,6 +93,8 @@ from OFS.content_types import guess_content_type
from
DTMLMethod
import
DTMLMethod
,
decapitate
from
PropertyManager
import
PropertyManager
from
webdav.common
import
rfc1123_date
from
webdav.Lockable
import
ResourceLockedError
from
webdav.WriteLockInterface
import
WriteLockInterface
from
sgmllib
import
SGMLParser
from
string
import
find
from
urllib
import
quote
...
...
@@ -106,6 +109,7 @@ class DTMLDocument(PropertyManager, DTMLMethod):
"""DTML Document objects are DocumentTemplate.HTML objects that act
as methods whose 'self' is the DTML Document itself."""
__implements__
=
(
WriteLockInterface
,)
meta_type
=
'DTML Document'
icon
=
'p_/dtmldoc'
...
...
@@ -139,6 +143,10 @@ class DTMLDocument(PropertyManager, DTMLMethod):
self
.
_validateProxy
(
REQUEST
)
if
self
.
_size_changes
.
has_key
(
SUBMIT
):
return
self
.
_er
(
data
,
title
,
SUBMIT
,
dtpref_cols
,
dtpref_rows
,
REQUEST
)
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
(
'This document has been locked via WebDAV.'
)
self
.
title
=
str
(
title
)
if
type
(
data
)
is
not
type
(
''
):
data
=
data
.
read
()
self
.
munge
(
data
)
...
...
@@ -150,6 +158,9 @@ class DTMLDocument(PropertyManager, DTMLMethod):
def
manage_upload
(
self
,
file
=
''
,
REQUEST
=
None
):
"""Replace the contents of the document with the text in file."""
self
.
_validateProxy
(
REQUEST
)
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
(
'This document has been locked via WebDAV.'
)
if
type
(
file
)
is
not
type
(
''
):
file
=
file
.
read
()
self
.
munge
(
file
)
self
.
ZCacheable_invalidate
()
...
...
lib/python/OFS/DTMLMethod.py
View file @
3beb18c2
...
...
@@ -84,7 +84,7 @@
##############################################################################
"""DTML Method objects."""
__version__
=
'$Revision: 1.6
0
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.6
1
$'
[
11
:
-
2
]
import
History
from
Globals
import
HTML
,
DTMLFile
,
MessageDialog
...
...
@@ -94,6 +94,8 @@ from OFS.content_types import guess_content_type
from
PropertyManager
import
PropertyManager
from
AccessControl.Role
import
RoleManager
from
webdav.common
import
rfc1123_date
from
webdav.Lockable
import
ResourceLockedError
from
webdav.WriteLockInterface
import
WriteLockInterface
from
ZDOM
import
ElementWithTitle
from
DateTime.DateTime
import
DateTime
from
urllib
import
quote
...
...
@@ -115,6 +117,8 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
index_html
=
None
# Prevent accidental acquisition
_cache_namespace_keys
=
()
__implements__
=
(
WriteLockInterface
,)
# Documents masquerade as functions:
class
func_code
:
pass
func_code
=
func_code
()
...
...
@@ -304,6 +308,8 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
self
.
_validateProxy
(
REQUEST
)
if
self
.
_size_changes
.
has_key
(
SUBMIT
):
return
self
.
_er
(
data
,
title
,
SUBMIT
,
dtpref_cols
,
dtpref_rows
,
REQUEST
)
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
'This DTML Method is locked via WebDAV'
self
.
title
=
str
(
title
)
if
type
(
data
)
is
not
type
(
''
):
data
=
data
.
read
()
...
...
@@ -316,6 +322,9 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
def
manage_upload
(
self
,
file
=
''
,
REQUEST
=
None
):
"""Replace the contents of the document with the text in file."""
self
.
_validateProxy
(
REQUEST
)
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
'This DTML Method is locked via WebDAV'
if
type
(
file
)
is
not
type
(
''
):
file
=
file
.
read
()
self
.
munge
(
file
)
self
.
ZCacheable_invalidate
()
...
...
@@ -369,6 +378,7 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
def
PUT
(
self
,
REQUEST
,
RESPONSE
):
"""Handle HTTP PUT requests."""
self
.
dav__init
(
REQUEST
,
RESPONSE
)
self
.
dav__simpleifhandler
(
REQUEST
,
RESPONSE
,
refresh
=
1
)
body
=
REQUEST
.
get
(
'BODY'
,
''
)
self
.
_validateProxy
(
REQUEST
)
self
.
munge
(
body
)
...
...
lib/python/OFS/Folder.py
View file @
3beb18c2
...
...
@@ -87,12 +87,13 @@
Folders are the basic container objects and are analogous to directories.
$Id: Folder.py,v 1.9
3 2001/01/11 21:11:04 chrism
Exp $"""
$Id: Folder.py,v 1.9
4 2001/01/31 21:26:52 jeffrey
Exp $"""
__version__
=
'$Revision: 1.9
3
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.9
4
$'
[
11
:
-
2
]
import
Globals
,
SimpleItem
,
ObjectManager
,
PropertyManager
import
AccessControl.Role
,
webdav
.
Collection
,
FindSupport
from
webdav.WriteLockInterface
import
WriteLockInterface
from
Globals
import
DTMLFile
from
AccessControl
import
getSecurityManager
...
...
@@ -150,6 +151,7 @@ class Folder(
interface for object management. Folder objects also implement
a management interface and can have arbitrary properties.
"""
__implements__
=
(
WriteLockInterface
,)
meta_type
=
'Folder'
_properties
=
({
'id'
:
'title'
,
'type'
:
'string'
},)
...
...
lib/python/OFS/Image.py
View file @
3beb18c2
...
...
@@ -84,7 +84,7 @@
##############################################################################
"""Image object"""
__version__
=
'$Revision: 1.12
4
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.12
5
$'
[
11
:
-
2
]
import
Globals
,
string
,
struct
,
content_types
from
OFS.content_types
import
guess_content_type
...
...
@@ -92,6 +92,8 @@ from Globals import DTMLFile, MessageDialog
from
PropertyManager
import
PropertyManager
from
AccessControl.Role
import
RoleManager
from
webdav.common
import
rfc1123_date
from
webdav.Lockable
import
ResourceLockedError
from
webdav.WriteLockInterface
import
WriteLockInterface
from
SimpleItem
import
Item_w__name__
from
cStringIO
import
StringIO
from
Globals
import
Persistent
...
...
@@ -135,6 +137,7 @@ class File(Persistent, Implicit, PropertyManager,
RoleManager
,
Item_w__name__
,
Cacheable
):
"""A File object is a content object for arbitrary files."""
__implements__
=
(
WriteLockInterface
,)
meta_type
=
'File'
...
...
@@ -265,6 +268,9 @@ class File(Persistent, Implicit, PropertyManager,
"""
Changes the title and content type attributes of the File or Image.
"""
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
"File is locked via WebDAV"
self
.
title
=
str
(
title
)
self
.
content_type
=
str
(
content_type
)
if
precondition
:
self
.
precondition
=
str
(
precondition
)
...
...
@@ -280,6 +286,9 @@ class File(Persistent, Implicit, PropertyManager,
The file or images contents are replaced with the contents of 'file'.
"""
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
"File is locked via WebDAV"
data
,
size
=
self
.
_read_data
(
file
)
content_type
=
self
.
_get_content_type
(
file
,
data
,
self
.
__name__
,
'application/octet-stream'
)
...
...
@@ -369,6 +378,7 @@ class File(Persistent, Implicit, PropertyManager,
def
PUT
(
self
,
REQUEST
,
RESPONSE
):
"""Handle HTTP PUT requests"""
self
.
dav__init
(
REQUEST
,
RESPONSE
)
self
.
dav__simpleifhandler
(
REQUEST
,
RESPONSE
,
refresh
=
1
)
type
=
REQUEST
.
get_header
(
'content-type'
,
None
)
file
=
REQUEST
[
'BODYFILE'
]
...
...
@@ -504,6 +514,7 @@ class Image(File):
as File objects. Images also have a string representation that
renders an HTML 'IMG' tag.
"""
__implements__
=
(
WriteLockInterface
,)
meta_type
=
'Image'
...
...
lib/python/OFS/PropertySheets.py
View file @
3beb18c2
...
...
@@ -84,9 +84,10 @@
##############################################################################
"""Property sheets"""
__version__
=
'$Revision: 1.6
4
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.6
5
$'
[
11
:
-
2
]
import
time
,
string
,
App
.
Management
,
Globals
from
webdav.WriteLockInterface
import
WriteLockInterface
from
ZPublisher.Converters
import
type_converters
from
DocumentTemplate.DT_Util
import
html_quote
from
Globals
import
DTMLFile
,
MessageDialog
...
...
@@ -531,6 +532,8 @@ class DAVProperties(Virtual, PropertySheet, View):
{
'id'
:
'getcontenttype'
,
'mode'
:
'r'
},
{
'id'
:
'getcontentlength'
,
'mode'
:
'r'
},
{
'id'
:
'source'
,
'mode'
:
'r'
},
{
'id'
:
'supportedlock'
,
'mode'
:
'r'
},
{
'id'
:
'lockdiscovery'
,
'mode'
:
'r'
},
)
def
getProperty
(
self
,
id
,
default
=
None
):
...
...
@@ -598,6 +601,17 @@ class DAVProperties(Virtual, PropertySheet, View):
' <d:locktype><d:write/></d:locktype>
\
n
'
\
' </n:lockentry>
\
n
'
def
dav__lockdiscovery
(
self
):
vself
=
self
.
v_self
()
out
=
'
\
n
'
if
WriteLockInterface
.
isImplementedBy
(
vself
):
locks
=
vself
.
wl_lockValues
(
killinvalids
=
1
)
for
lock
in
locks
:
out
=
'%s
\
n
%s'
%
(
out
,
lock
.
asLockDiscoveryProperty
(
'n'
))
out
=
'%s
\
n
'
%
out
return
out
Globals
.
default__class_init__
(
DAVProperties
)
...
...
lib/python/OFS/dtml/documentEdit.dtml
View file @
3beb18c2
...
...
@@ -36,7 +36,11 @@ the <em>browse</em> button to select a local file to upload.
<tr>
<td align="left" valign="top" colspan="2">
<div class="form-element">
<input class="form-element" type="submit" name="SUBMIT" value="Save Changes">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" name="SUBMIT" value="Save Changes">
</dtml-if>
<input class="form-element" type="submit" name="SUBMIT" value="Taller">
<input class="form-element" type="submit" name="SUBMIT" value="Shorter">
...
...
@@ -64,7 +68,11 @@ the <em>browse</em> button to select a local file to upload.
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" value="Upload File">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" value="Upload File">
</dtml-if>
</div>
</td>
</tr>
...
...
lib/python/OFS/dtml/fileEdit.dtml
View file @
3beb18c2
...
...
@@ -77,8 +77,12 @@ kind>.
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="manage_edit:method"
value="Save Changes">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" name="manage_edit:method"
value="Save Changes">
</dtml-if>
</div>
</td>
</tr>
...
...
@@ -100,8 +104,12 @@ kind>.
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="manage_upload:method"
value="Upload">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" name="manage_upload:method"
value="Upload">
</dtml-if>
</div>
</td>
</tr>
...
...
lib/python/OFS/dtml/imageEdit.dtml
View file @
3beb18c2
...
...
@@ -66,8 +66,12 @@ kind>.
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value="Save Changes">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" name="submit"
value="Save Changes">
</dtml-if>
</div>
</td>
</tr>
...
...
@@ -95,8 +99,12 @@ kind>.
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value="Upload">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" name="submit"
value="Upload">
</dtml-if>
</div>
</td>
</tr>
...
...
lib/python/OFS/dtml/main.dtml
View file @
3beb18c2
...
...
@@ -131,6 +131,11 @@ function toggleSelect() {
(<em>&dtml-locked_in_version;</em>)
</dtml-if>
</dtml-if>
<dtml-if wl_isLocked>
<img src="&dtml-BASEPATH1;/p_/davlocked"
alt="This item has been locked by WebDAV"
title="This item has been locked by WebDAV" />
</dtml-if>
</div>
</td>
...
...
lib/python/OFS/misc_.py
View file @
3beb18c2
...
...
@@ -101,6 +101,8 @@ class p_:
locked
=
ImageFile
(
'www/modified.gif'
,
globals
())
lockedo
=
ImageFile
(
'www/locked.gif'
,
globals
())
davlocked
=
ImageFile
(
'webdav/www/davlock.gif'
)
pl
=
ImageFile
(
'TreeDisplay/www/Plus_icon.gif'
)
mi
=
ImageFile
(
'TreeDisplay/www/Minus_icon.gif'
)
rtab
=
ImageFile
(
'App/www/rtab.gif'
)
...
...
lib/python/Products/OFSP/help/DavLocks-ManageLocks.stx
0 → 100644
View file @
3beb18c2
WebDAV Lock Management - Manage Locks
Description
This view allows you to manage WebDAV WriteLocks. WebDAV, as an
extension to the HTTP Protocol, allows the users to create *Write
Locks* as a way of trying to avoid the "lost updates problem".
However, sometimes WriteLocks may become abandoned. This may be due
to users forgetting to unlock their resources, software failures
such as crashes, etc. In many cases, locks might just time out
before this becomes a problem. In cases where it's not, this
control panel object may be used to locate locked resources inside
of Zope and clear *ALL* of their WebDAV writelocks. **This does not
clear locks caused by use of Versions**.
Controls
'Path' -- This lets you enter a path (based off the root of the Zope
site) to filter down the list of locked objects. Clicking 'Go'
executes the filter.
When locked objects are found, they are listed one per line with a
checkbox that can be used to select the item. Also listed in each
line is information about the lock(s) on the object - the user who
created the lock (identified by the path to the user folder the user
is defined in), and the locktoken that identifies the lock. In the
majority of cases, there should only be one lock per object.
'[Checkbox]' -- Selects locked items.
'Select All' -- This button marks all items displayed as selected.
'Deselect All' -- After 'Select All' has been clicked, it changes to
say 'Deselect All'. Clicking this deselects all displayed items.
'Unlock objects' -- Unlocks the selected items.
\ No newline at end of file
lib/python/Products/PythonScripts/PythonScript.py
View file @
3beb18c2
...
...
@@ -89,7 +89,7 @@ This product provides support for Script objects containing restricted
Python code.
"""
__version__
=
'$Revision: 1.2
0
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.2
1
$'
[
11
:
-
2
]
import
sys
,
os
,
traceback
,
re
from
Globals
import
DTMLFile
,
MessageDialog
...
...
@@ -98,6 +98,8 @@ from OFS.SimpleItem import SimpleItem
from
DateTime.DateTime
import
DateTime
from
string
import
join
,
strip
,
rstrip
,
split
,
replace
,
lower
from
urllib
import
quote
from
webdav.Lockable
import
ResourceLockedError
from
webdav.WriteLockInterface
import
WriteLockInterface
from
Shared.DC.Scripts.Script
import
Script
,
BindingsUI
,
defaultBindings
from
AccessControl
import
getSecurityManager
from
OFS.History
import
Historical
,
html_diff
...
...
@@ -136,6 +138,7 @@ class PythonScript(Script, Historical, Cacheable):
not attempt to use the "exec" statement or certain restricted builtins.
"""
__implements__
=
(
WriteLockInterface
,)
meta_type
=
'Script (Python)'
_proxy_roles
=
()
...
...
@@ -190,6 +193,8 @@ class PythonScript(Script, Historical, Cacheable):
def
ZPythonScript_edit
(
self
,
params
,
body
):
self
.
_validateProxy
()
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
"The script is locked via WebDAV."
if
type
(
body
)
is
not
type
(
''
):
body
=
body
.
read
()
if
self
.
_params
<>
params
or
self
.
_body
<>
body
:
...
...
@@ -198,6 +203,8 @@ class PythonScript(Script, Historical, Cacheable):
def
ZPythonScriptHTML_upload
(
self
,
REQUEST
,
file
=
''
):
"""Replace the body of the script with the text in file."""
if
self
.
wl_isLocked
():
raise
ResourceLockedError
,
"The script is locked via WebDAV."
if
type
(
file
)
is
not
type
(
''
):
file
=
file
.
read
()
self
.
write
(
file
)
message
=
'Saved changes.'
...
...
@@ -376,6 +383,7 @@ class PythonScript(Script, Historical, Cacheable):
def PUT(self, REQUEST, RESPONSE):
""" Handle HTTP PUT requests """
self.dav__init(REQUEST, RESPONSE)
self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
self.write(REQUEST.get('
BODY
', ''))
RESPONSE.setStatus(204)
return RESPONSE
...
...
lib/python/Products/PythonScripts/www/pyScriptEdit.dtml
View file @
3beb18c2
...
...
@@ -70,8 +70,12 @@
<tr>
<td align="left" valign="top" colspan="2">
<div class="form-element">
<input class="form-element" type="submit"
name="ZPythonScriptHTML_editAction:method" value="Save Changes">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit"
name="ZPythonScriptHTML_editAction:method" value="Save Changes">
</dtml-if>
<input class="form-element" type="submit" name="height" value="Taller">
<input class="form-element" type="submit" name="height" value="Shorter">
...
...
@@ -108,7 +112,11 @@ to <a href="document_src">view or download</a> the current source.
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" value="Upload File">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" value="Upload File">
</dtml-if>
</div>
</td>
</tr>
...
...
lib/python/Products/ZSQLMethods/SQL.py
View file @
3beb18c2
...
...
@@ -85,11 +85,12 @@
__doc__
=
'''SQL Methods
$Id: SQL.py,v 1.1
6 2001/01/11 19:52:54 chrism
Exp $'''
__version__
=
'$Revision: 1.1
6
$'
[
11
:
-
2
]
$Id: SQL.py,v 1.1
7 2001/01/31 21:26:55 jeffrey
Exp $'''
__version__
=
'$Revision: 1.1
7
$'
[
11
:
-
2
]
import
Shared.DC.ZRDB.DA
from
Globals
import
DTMLFile
from
webdav.WriteLockInterface
import
WriteLockInterface
def
SQLConnectionIDs
(
self
):
"""Find SQL database connections in the current folder and above
...
...
@@ -188,6 +189,7 @@ class SQL(Shared.DC.ZRDB.DA.DA):
employees/employee_id/1234/service_record
"""
__implements__
=
(
WriteLockInterface
,)
meta_type
=
'Z SQL Method'
manage_main
=
DTMLFile
(
'dtml/edit'
,
globals
())
...
...
lib/python/Products/ZSQLMethods/dtml/edit.dtml
View file @
3beb18c2
...
...
@@ -69,10 +69,14 @@
<tr>
<td align="left" valign="top" colspan="2">
<div class="form-element">
<input class="form-element" type="submit" name="SUBMIT"
value="Save Changes">
<input class="form-element" type="submit" name="SUBMIT"
value="Change and Test">
<dtml-if wl_isLocked>
<em>Locked by WebDAV</em>
<dtml-else>
<input class="form-element" type="submit" name="SUBMIT"
value="Save Changes">
<input class="form-element" type="submit" name="SUBMIT"
value="Change and Test">
</dtml-if wl_isLocked>
<br />
<input class="form-element" type="submit" name="SUBMIT" value="Taller">
<input class="form-element" type="submit" name="SUBMIT" value="Shorter">
...
...
lib/python/Shared/DC/ZRDB/DA.py
View file @
3beb18c2
...
...
@@ -85,8 +85,7 @@
__doc__
=
'''Generic Database adapter
$Id: DA.py,v 1.97 2001/01/24 16:14:54 brian Exp $'''
__version__
=
'$Revision: 1.97 $'
[
11
:
-
2
]
__version__='$Revision: 1.98 $'[11:-2]
import OFS.SimpleItem, Aqueduct, RDB, re
import DocumentTemplate, marshal, md5, base64, Acquisition, os
...
...
@@ -108,6 +107,7 @@ from Results import Results
from App.Extensions import getBrain
from AccessControl import getSecurityManager
from webdav.Resource import Resource
from webdav.Lockable import ResourceLockedError
try: from IOBTree import Bucket
except: Bucket=lambda:{}
...
...
@@ -232,6 +232,9 @@ class DA(
return self._er(title,connection_id,arguments,template,
SUBMIT,sql_pref__cols,sql_pref__rows,REQUEST)
if self.wl_isLocked():
raise ResourceLockedError, 'SQL Method is locked via WebDAV'
self.title=str(title)
self.connection_id=str(connection_id)
arguments=str(arguments)
...
...
@@ -338,6 +341,7 @@ class DA(
def PUT(self, REQUEST, RESPONSE):
"""Handle put requests"""
self.dav__init(REQUEST, RESPONSE)
self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
body = REQUEST.get('BODY', '')
m = re.match('
\
s*<p
a
rams>(.*)</params>
\
s*
\
n', body, re.I)
if m:
...
...
lib/python/webdav/Collection.py
View file @
3beb18c2
...
...
@@ -85,12 +85,14 @@
"""WebDAV support - collection objects."""
__version__
=
'$Revision: 1.1
7
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.1
8
$'
[
11
:
-
2
]
import
sys
,
os
,
string
,
Globals
import
sys
,
os
,
string
,
Globals
,
davcmds
,
Lockable
from
common
import
urlfix
,
rfc1123_date
from
Resource
import
Resource
from
AccessControl
import
getSecurityManager
from
urllib
import
unquote
from
WriteLockInterface
import
WriteLockInterface
class
Collection
(
Resource
):
...
...
@@ -143,11 +145,45 @@ class Collection(Resource):
success, or may return 207 (Multistatus) to indicate partial
success. Note that in Zope a DELETE currently never returns 207."""
self
.
dav__init
(
REQUEST
,
RESPONSE
)
url
=
urlfix
(
REQUEST
[
'URL'
],
'DELETE'
)
name
=
unquote
(
filter
(
None
,
string
.
split
(
url
,
'/'
))[
-
1
])
# TODO: add lock checking here
self
.
aq_parent
.
_delObject
(
name
)
RESPONSE
.
setStatus
(
204
)
ifhdr
=
REQUEST
.
get_header
(
'If'
,
''
)
url
=
urlfix
(
REQUEST
[
'URL'
],
'DELETE'
)
name
=
unquote
(
filter
(
None
,
string
.
split
(
url
,
'/'
))[
-
1
])
parent
=
self
.
aq_parent
user
=
getSecurityManager
().
getUser
()
token
=
None
# Level 1 of lock checking (is the collection or its parent locked?)
if
Lockable
.
wl_isLocked
(
self
):
if
ifhdr
:
self
.
dav__simpleifhandler
(
REQUEST
,
RESPONSE
,
'DELETE'
,
col
=
1
)
else
:
raise
'Locked'
elif
Lockable
.
wl_isLocked
(
parent
):
if
ifhdr
:
parent
.
dav__simpleifhandler
(
REQUEST
,
RESPONSE
,
'DELETE'
,
col
=
1
)
else
:
raise
'Precondition Failed'
# Second level of lock\conflict checking (are any descendants locked,
# or is the user not permitted to delete?). This results in a
# multistatus response
if
ifhdr
:
tokens
=
self
.
wl_lockTokens
()
for
tok
in
tokens
:
# We already know that the simple if handler succeeded,
# we just want to get the right token out of the header now
if
string
.
find
(
ifhdr
,
tok
)
>
-
1
:
token
=
tok
cmd
=
davcmds
.
DeleteCollection
()
result
=
cmd
.
apply
(
self
,
token
,
user
,
REQUEST
[
'URL'
])
if
result
:
# There were conflicts, so we need to report them
RESPONSE
.
setStatus
(
207
)
RESPONSE
.
setHeader
(
'Content-Type'
,
'text/xml; charset="utf-8"'
)
RESPONSE
.
setBody
(
result
)
else
:
# There were no conflicts, so we can go ahead and delete
self
.
aq_parent
.
_delObject
(
name
)
RESPONSE
.
setStatus
(
204
)
return
RESPONSE
...
...
lib/python/webdav/EtagSupport.py
0 → 100644
View file @
3beb18c2
from
string
import
capitalize
,
split
,
join
,
strip
import
time
,
Interface
,
re
class
EtagBaseInterface
(
Interface
.
Base
):
"""
\
Basic Etag support interface, meaning the object supports generating
an Etag that can be used by certain HTTP and WebDAV Requests.
"""
def
http__etag
(
self
):
"""
\
Entity tags are used for comparing two or more entities from
the same requested resource. Predominantly used for Caching,
Etags can also be used to deal with the 'Lost Updates Problem'.
An HTTP Client such as Amaya that supports PUT for editing can
use the Etag value returned in the head of a GET response in the
'if-match' header submitted with a PUT request. If the Etag
for the requested resource in the PUT request's 'if-match' header
is different from the current Etag value returned by this method,
the PUT will fail (it means that the state of the resource has
changed since the last copy the Client recieved) because the
precondition (the 'if-match') fails (the submitted Etag does not
match the current Etag).
"""
def
http__refreshEtag
(
self
):
"""
\
While it may make sense to use the ZODB Object Id or
bobobase_modification_time to generate an Etag, this could
fail on certain REQUESTS because:
o The object is not stored in the ZODB, or
o A Request such as PUT changes the oid or bobobase_modification_time
*AFTER* the Response has been written out, but the Etag needs
to be updated and returned with the Response of the PUT request.
Thus, Etags need to be refreshed manually when an object changes.
"""
class
EtagSupport
:
"""
\
This class is the basis for supporting Etags in Zope. It's main
function right now is to support the *Lost Updates Problem* by
allowing Etags and If-Match headers to be checked on PUT calls to
provide a *Seatbelt* style functionality. The Etags is based on
the bobobase_modification_time, and thus is updated whenever the
object is updated. If a PUT request, or other HTTP or Dav request
comes in with an Etag different than the current one, that request
can be rejected according to the type of header (If-Match,
If-None-Match).
"""
__implements__
=
(
EtagBaseInterface
,)
def
http__etag
(
self
):
try
:
etag
=
self
.
__etag
except
AttributeError
:
self
.
http__refreshEtag
()
etag
=
self
.
__etag
return
etag
def
http__refreshEtag
(
self
):
self
.
__etag
=
'ts%s'
%
str
(
time
.
time
())[
2
:]
def
http__parseMatchList
(
self
,
REQUEST
,
header
=
"if-match"
):
# Return a sequence of strings found in the header specified
# (should be one of {'if-match' or 'if-none-match'}). If the
# header is not in the request, returns None. Otherwise,
# returns a tuple of Etags.
matchlist
=
REQUEST
.
get_header
(
header
)
if
matchlist
is
None
:
# capitalize the words of the header, splitting on '-'
tmp
=
map
(
capitalize
,
split
(
header
,
'-'
))
tmp
=
join
(
tmp
,
'-'
)
matchlist
=
REQUEST
.
get_header
(
tmp
)
if
matchlist
is
None
:
return
None
matchlist
=
map
(
strip
,
split
(
matchlist
,
','
))
r
=
[]
for
match
in
matchlist
:
if
match
==
'*'
:
r
.
insert
(
0
,
match
)
elif
(
match
[
0
]
+
match
[
-
1
]
==
'""'
)
and
(
len
(
match
)
>
2
):
r
.
append
(
match
[
1
:
-
1
])
return
tuple
(
r
)
def
http__processMatchHeaders
(
self
,
REQUEST
=
None
):
# Process if-match and if-none-match headers
if
REQUEST
is
None
:
REQUEST
=
self
.
aq_acquire
(
'REQUEST'
)
matchlist
=
self
.
http__parseMatchList
(
REQUEST
,
'if-match'
)
nonematch
=
self
.
http__parseMatchList
(
REQUEST
,
'if-none-match'
)
if
matchlist
is
None
:
# There's no Matchlist, but 'if-none-match' might need processing
pass
elif
(
'*'
in
matchlist
):
return
1
# * matches everything
elif
self
.
http__etag
()
not
in
matchlist
:
# The resource etag is not in the list of etags required
# to match, as specified in the 'if-match' header. The
# condition fails and the HTTP Method may *not* execute.
raise
"Precondition Failed"
elif
self
.
http__etag
()
in
matchlist
:
return
1
if
nonematch
is
None
:
# There's no 'if-none-match' header either, so there's no
# problem continuing with the request
return
1
elif
(
'*'
in
nonelist
):
# if-none-match: * means that the operation should not
# be performed if the specified resource exists
# (webdav.NullResource will want to do special behavior
# here)
raise
"Precondition Failed"
elif
self
.
http__etag
()
in
nonelist
:
# The opposite of if-match, the condition fails
# IF the resources Etag is in the if-none-match list
raise
"Precondition Failed"
elif
self
.
http__etag
()
not
in
nonelist
:
return
1
lib/python/webdav/LockItem.py
0 → 100644
View file @
3beb18c2
from
string
import
lower
,
split
,
join
from
Globals
import
Persistent
from
WriteLockInterface
import
LockItemInterface
from
AccessControl
import
ClassSecurityInfo
from
AccessControl.Owned
import
ownerInfo
from
common
import
generateLockToken
import
time
MAXTIMEOUT
=
(
2L
**
32
)
-
1
# Maximum timeout time
DEFAULTTIMEOUT
=
12
*
60L
# Default timeout
def
validateTimeout
(
timeout
):
# Timeout *should* be in the form "Seconds-XXX" or "Infinite"
errors
=
[]
try
:
t
=
split
(
str
(
timeout
),
'-'
)[
-
1
]
if
lower
(
t
)
==
'infinite'
:
timeout
=
DEFAULTTIMEOUT
# Default to 1800 secods for infinite
else
:
# requests
timeout
=
long
(
t
)
except
ValueError
:
errors
.
append
(
"Bad timeout value"
)
if
timeout
>
MAXTIMEOUT
:
errors
.
append
(
"Timeout request is greater than %s"
%
MAXTIMEOUT
)
return
timeout
,
errors
class
LockItem
(
Persistent
):
__implements__
=
(
LockItemInterface
,)
# Use the Zope 2.3 declarative security to manage access
security
=
ClassSecurityInfo
()
security
.
declarePublic
(
'getOwner'
,
'getLockToken'
,
'getDepth'
,
'getTimeout'
,
'getTimeoutString'
,
'getModifiedTime'
,
'isValid'
,
'getLockScope'
,
'getLockType'
)
security
.
declareProtected
(
'Change Lock Information'
,
'setTimeout'
,
'refresh'
)
security
.
declareProtected
(
'Access contents information'
,
'getCreator'
,
'getCreatorPath'
)
def
__init__
(
self
,
creator
,
owner
=
''
,
depth
=
0
,
timeout
=
'Infinite'
,
locktype
=
'write'
,
lockscope
=
'exclusive'
,
token
=
None
):
errors
=
[]
# First check the values and raise value errors if outside of contract
if
not
getattr
(
creator
,
'getUserName'
,
None
):
errors
.
append
(
"Creator not a user object"
)
if
lower
(
str
(
depth
))
not
in
(
'0'
,
'infinity'
):
errors
.
append
(
"Depth must be 0 or infinity"
)
if
lower
(
locktype
)
!=
'write'
:
errors
.
append
(
"Lock type '%s' not supported"
%
locktype
)
if
lower
(
lockscope
)
!=
'exclusive'
:
errors
.
append
(
"Lock scope '%s' not supported"
%
lockscope
)
timeout
,
e
=
validateTimeout
(
timeout
)
errors
=
errors
+
e
# Finally, if there were errors, report them ALL to on high
if
errors
:
raise
ValueError
,
errors
# AccessControl.Owned.ownerInfo returns the id of the creator
# and the path to the UserFolder they're defined in
self
.
_creator
=
ownerInfo
(
creator
)
self
.
_owner
=
owner
self
.
_depth
=
depth
self
.
_timeout
=
timeout
self
.
_locktype
=
locktype
self
.
_lockscope
=
lockscope
self
.
_modifiedtime
=
time
.
time
()
if
token
is
None
:
self
.
_token
=
generateLockToken
()
else
:
self
.
_token
=
token
def
getCreator
(
self
):
return
self
.
_creator
def
getCreatorPath
(
self
):
db
,
name
=
self
.
_creator
path
=
join
(
db
,
'/'
)
return
"/%s/%s"
%
(
path
,
name
)
def
getOwner
(
self
):
return
self
.
_owner
def
getLockToken
(
self
):
return
self
.
_token
def
getDepth
(
self
):
return
self
.
_depth
def
getTimeout
(
self
):
return
self
.
_timeout
def
getTimeoutString
(
self
):
t
=
str
(
self
.
_timeout
)
if
t
[
-
1
]
==
'L'
:
t
=
t
[:
-
1
]
# lob off Long signifier
return
"Second-%s"
%
t
def
setTimeout
(
self
,
newtimeout
):
timeout
,
errors
=
validateTimeout
(
newtimeout
)
if
errors
:
raise
ValueError
,
errors
else
:
self
.
_timeout
=
timeout
self
.
_modifiedtime
=
time
.
time
()
# reset modified
def
getModifiedTime
(
self
):
return
self
.
_modifiedtime
def
refresh
(
self
):
self
.
_modifiedtime
=
time
.
time
()
def
isValid
(
self
):
now
=
time
.
time
()
modified
=
self
.
_modifiedtime
timeout
=
self
.
_timeout
return
(
modified
+
timeout
)
>
now
def
getLockType
(
self
):
return
self
.
_locktype
def
getLockScope
(
self
):
return
self
.
_lockscope
def
asLockDiscoveryProperty
(
self
,
ns
=
'd'
):
s
=
(
' <%(ns)s:activelock>
\
n
'
' <%(ns)s:locktype><%(ns)s:%(locktype)s/></%(ns)s:locktype>
\
n
'
' <%(ns)s:lockscope><%(ns)s:%(lockscope)s/></%(ns)s:lockscope>
\
n
'
' <%(ns)s:depth>%(depth)s</%(ns)s:depth>
\
n
'
' <%(ns)s:owner>%(owner)s</%(ns)s:owner>
\
n
'
' <%(ns)s:timeout>%(timeout)s</%(ns)s:timeout>
\
n
'
' <%(ns)s:locktoken>
\
n
'
' <%(ns)s:href>opaquelocktoken:%(locktoken)s</%(ns)s:href>
\
n
'
' </%(ns)s:locktoken>
\
n
'
' </%(ns)s:activelock>
\
n
'
)
%
{
'ns'
:
ns
,
'locktype'
:
self
.
_locktype
,
'lockscope'
:
self
.
_lockscope
,
'depth'
:
self
.
_depth
,
'owner'
:
self
.
_owner
,
'timeout'
:
self
.
getTimeoutString
(),
'locktoken'
:
self
.
_token
,
}
return
s
def
asXML
(
self
):
s
=
"""<?xml version="1.0" encoding="utf-8" ?>
<d:prop xmlns:d="DAV:">
<d:lockdiscovery>
%s
</d:lockdiscovery>
</d:prop>"""
%
self
.
asLockDiscoveryProperty
(
ns
=
"d"
)
return
s
lib/python/webdav/Lockable.py
0 → 100644
View file @
3beb18c2
from
WriteLockInterface
import
WriteLockInterface
,
LockItemInterface
from
EtagSupport
import
EtagSupport
from
LockItem
import
LockItem
from
AccessControl
import
ClassSecurityInfo
from
Globals
import
PersistentMapping
import
Acquisition
class
ResourceLockedError
(
Exception
):
pass
class
LockableItem
(
EtagSupport
):
"""
\
Implements the WriteLockInterface, and is inherited by Resource which
is then inherited by the majority of Zope objects. For an object to
be lockable, however, it should have the WriteLockInterface in its
__implements__ list, ie:
__implements__ = (WriteLockInterface,)
"""
# Protect methods using declarative security
security
=
ClassSecurityInfo
()
security
.
declarePrivate
(
'wl_lockmapping'
)
security
.
declarePublic
(
'wl_isLocked'
,
'wl_getLock'
,
'wl_isLockedByUser'
,
'wl_lockItems'
,
'wl_lockValues'
,
'wl_lockTokens'
,)
security
.
declareProtected
(
'WebDAV Lock items'
,
'wl_grantLockToUser'
,
'wl_setLock'
)
security
.
declareProtected
(
'WebDAV Unlock items'
,
'wl_delLock'
)
security
.
declareProtected
(
'Manage WebDAV Locks'
,
'wl_killAllLocks'
)
def
wl_lockmapping
(
self
,
killinvalids
=
0
):
""" if 'killinvalids' is 1, locks who are no longer valid
will be deleted """
try
:
locks
=
getattr
(
self
,
'_dav_writelocks'
,
None
)
except
:
locks
=
None
if
locks
is
None
:
locks
=
self
.
_dav_writelocks
=
PersistentMapping
()
return
locks
elif
killinvalids
:
# Delete invalid locks
for
token
,
lock
in
locks
.
items
():
if
not
lock
.
isValid
():
del
locks
[
token
]
if
(
not
locks
)
and
hasattr
(
Acquisition
.
aq_base
(
self
),
'__no_valid_write_locks__'
):
self
.
__no_valid_write_locks__
()
return
locks
else
:
return
locks
def
wl_lockItems
(
self
,
killinvalids
=
0
):
return
self
.
wl_lockmapping
(
killinvalids
).
items
()
def
wl_lockValues
(
self
,
killinvalids
=
0
):
return
self
.
wl_lockmapping
(
killinvalids
).
values
()
def
wl_lockTokens
(
self
,
killinvalids
=
0
):
return
self
.
wl_lockmapping
(
killinvalids
).
keys
()
def
wl_hasLock
(
self
,
token
,
killinvalids
=
0
):
if
not
token
:
return
0
return
token
in
self
.
wl_lockmapping
(
killinvalids
).
keys
()
def
wl_isLocked
(
self
):
# returns true if 'self' is locked at all
# We set 'killinvalids' to 1 to delete all locks who are no longer
# valid (timeout has been exceeded)
locks
=
self
.
wl_lockmapping
(
killinvalids
=
1
)
if
locks
.
keys
():
return
1
else
:
return
0
def
wl_setLock
(
self
,
locktoken
,
lock
):
locks
=
self
.
wl_lockmapping
()
if
LockItemInterface
.
isImplementedBy
(
lock
):
if
locktoken
==
lock
.
getLockToken
():
locks
[
locktoken
]
=
lock
else
:
raise
ValueError
,
'Lock tokens do not match'
else
:
raise
ValueError
,
'Lock does not implement the LockItem Interface'
def
wl_getLock
(
self
,
locktoken
):
locks
=
self
.
wl_lockmapping
(
killinvalids
=
1
)
return
locks
.
get
(
locktoken
,
None
)
def
wl_delLock
(
self
,
locktoken
):
locks
=
self
.
wl_lockmapping
()
if
locks
.
has_key
(
locktoken
):
del
locks
[
locktoken
]
def
wl_clearLocks
(
self
):
# Called by lock management machinery to quickly and effectively
# destroy all locks.
locks
=
self
.
wl_lockmapping
()
locks
.
clear
()
import
Globals
Globals
.
default__class_init__
(
LockableItem
)
### Utility functions
def
wl_isLocked
(
ob
):
""" Returns true if the object is locked, returns 0 if the object
is not locked or does not implement the WriteLockInterface """
return
WriteLockInterface
.
isImplementedBy
(
ob
)
and
ob
.
wl_isLocked
()
lib/python/webdav/NullResource.py
View file @
3beb18c2
This diff is collapsed.
Click to expand it.
lib/python/webdav/Resource.py
View file @
3beb18c2
This diff is collapsed.
Click to expand it.
lib/python/webdav/WriteLockInterface.py
0 → 100644
View file @
3beb18c2
import
Interface
class
LockItemInterface
(
Interface
.
Base
):
"""
\
A LockItem contains information about a lock. This includes:
o The locktoken uri (used to identify the lock by WebDAV)
o The lock owner (The string passed in the 'owner' property by WebDAV)
o The lock creator (the Zope user who physically owns the lock)
o Depth
o Timeout information
o Modified time (for calculating timeouts)
o LockType (only EXCLUSIVE is supported right now)
"""
def
__init__
(
self
,
creator
,
owner
,
depth
=
0
,
timeout
=
'Infinite'
,
locktype
=
'write'
,
lockscope
=
'exclusive'
,
token
=
None
):
"""
\
If any of the following are untrue, a **ValueError** exception
will be raised.
- **creator** MUST be a Zope user object or string to find a
valid user object.
- **owner** MUST be a nonempty string, or type that can be converted
to a nonempty string.
- **depth** MUST be in the set {0,'infinity'}
- **timeout** MUST either be an integer, or a string in the form
of 'Seconds-nnn' where nnn is an integer. The timeout value
MUST be less than (2^32)-1. *IF* timeout is the string value
'Infinite', the timeout value will be set to 1800 (30 minutes).
(Timeout is the value in seconds from creation
\
modi
f
ication
time until the lock MAY time out).
- **locktype** not in set {'write'} *this may expand later*
- **lockscope** not in set {'exclusive'} *this may expand later*
If the value passed in to 'token' is 'None', the a new locktoken
will be generated during the construction process.
__init__ must generate the opaquelocktoken uri used to identify the
lock (if 'token' is 'None')and set all of the above attributes on
the object.
"""
def
getCreator
(
self
):
""" Returns the Zope user who created the lock. This is returned
in a tuple containing the Users ID and the path to the user folder
they came from."""
def
getCreatorPath
(
self
):
""" Returns a string of the path to the user object in the user
folder they were found in. """
def
getOwner
(
self
):
""" Returns the string value of the 'owner' property sent
in by WebDAV """
def
getLockToken
(
self
):
""" returns the opaque lock token """
def
getDepth
(
self
):
""" returns the depth of the lock """
def
getTimeout
(
self
):
""" returns an integer value of the timeout setting """
def
getTimeoutString
(
self
):
""" returns the timeout value in a form acceptable by
WebDAV (ie - 'Seconds-40800') """
def
setTimeout
(
self
,
newtimeout
):
""" refreshes the timeout information """
def
getModifiedTime
(
self
):
""" returns a time.time value of the last time the Lock was
modified. From RFC 2518:
The timeout counter SHOULD be restarted any time an owner of the
lock sends a method to any member of the lock, including unsupported
methods or methods which are unsucscessful. The lock MUST be
refreshed if a refresh LOCK method is successfully received.
The modified time is used to calculate the refreshed value """
def
refresh
(
self
):
""" Tickles the locks modified time by setting it to the current
time.time() value. (As stated in the RFC, the timeout counter
SHOULD be restarted for any HTTP method called by the lock owner
on the locked object). """
def
isValid
(
self
):
""" Returns true if (self.getModifiedTime() + self.getTimeout())
is greater than the current time.time() value. """
# now = time.time()
# modified = self.getModifiedTime()
# timeout = self.getTimeout()
#
# return (modified + timeout > now) # there's time remaining
def
getLockType
(
self
):
""" returns the lock type ('write') """
def
getLockScope
(
self
):
""" returns the lock scope ('exclusive') """
def
asLockDiscoveryProperty
(
self
,
ns
=
'd'
):
""" Return the lock rendered as an XML representation of a
WebDAV 'lockdiscovery' property. 'ns' is the namespace identifier
used on the XML elements."""
def
asXML
(
self
):
""" Render a full XML representation of a lock for WebDAV,
used when returning the value of a newly created lock. """
class
WriteLockInterface
(
Interface
.
Base
):
"""
\
This represents the basic protocol needed to support the write lock
machinery.
It must be able to answer the questions:
o Is the object locked?
o Is the lock owned by the current user?
o What lock tokens are associated with the current object?
o What is their state (how long until they're supposed to time out?,
what is their depth? what type are they?
And it must be able to do the following:
o Grant a write lock on the object to a specified user.
- *If lock depth is infinite, this must also grant locks on **all**
subobjects, or fail altogether*
o Revoke a lock on the object.
- *If lock depth is infinite, this must also revoke locks on all
subobjects*
**All methods in the WriteLock interface that deal with checking valid
locks MUST check the timeout values on the lockitem (ie, by calling
'lockitem.isValid()'), and DELETE the lock if it is no longer valid**
"""
def
wl_lockItems
(
self
,
killinvalids
=
0
):
""" Returns (key, value) pairs of locktoken, lock.
if 'killinvalids' is true, invalid locks (locks whose timeout
has been exceeded) will be deleted"""
def
wl_lockValues
(
self
,
killinvalids
=
0
):
""" Returns a sequence of locks. if 'killinvalids' is true,
invalid locks will be deleted"""
def
wl_lockTokens
(
self
,
killinvalids
=
0
):
""" Returns a sequence of lock tokens. if 'killinvalids' is true,
invalid locks will be deleted"""
def
wl_hasLock
(
self
,
token
,
killinvalids
=
0
):
""" Returns true if the lock identified by the token is attached
to the object. """
def
wl_isLocked
(
self
):
""" Returns true if 'self' is locked at all. If invalid locks
still exist, they should be deleted."""
def
wl_setLock
(
self
,
locktoken
,
lock
):
""" Store the LockItem, 'lock'. The locktoken will be used to fetch
and delete the lock. If the lock exists, this MUST
overwrite it if all of the values except for the 'timeout' on the
old and new lock are the same. """
def
wl_getLock
(
self
,
locktoken
):
""" Returns the locktoken identified by the locktokenuri """
def
wl_delLock
(
self
,
locktoken
):
""" Deletes the locktoken identified by the locktokenuri """
def
wl_clearLocks
(
self
):
""" Deletes ALL DAV locks on the object - should only be called
by lock management machinery. """
lib/python/webdav/client.py
View file @
3beb18c2
"""HTTP 1.1 / WebDAV client library."""
__version__
=
'$Revision: 1.1
2
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.1
3
$'
[
11
:
-
2
]
import
sys
,
os
,
string
,
regex
,
time
,
types
import
socket
,
httplib
,
mimetools
...
...
@@ -245,10 +245,11 @@ class Resource:
'<d:lockinfo xmlns:d="DAV:">
\
n
'
\
' <d:lockscope><d:%s/></d:lockscope>
\
n
'
\
' <d:locktype><d:%s/></d:locktype>
\
n
'
\
' <d:depth>%s</d:depth>
\
n
'
\
' <d:owner>
\
n
'
\
' <d:href>%s</d:href>
\
n
'
\
' </d:owner>
\
n
'
\
'</d:lockinfo>'
%
(
scope
,
type
,
owner
)
'</d:lockinfo>'
%
(
scope
,
type
,
depth
,
owner
)
headers
[
'Content-Type'
]
=
'text/xml; charset="utf-8"'
headers
[
'Content-Length'
]
=
str
(
len
(
body
))
headers
[
'Timeout'
]
=
timeout
...
...
lib/python/webdav/common.py
View file @
3beb18c2
...
...
@@ -85,9 +85,9 @@
"""Commonly used functions for WebDAV support modules."""
__version__
=
'$Revision: 1.
9
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.
10
$'
[
11
:
-
2
]
import
string
,
time
,
urllib
import
string
,
time
,
urllib
,
re
from
Acquisition
import
aq_base
from
App.Common
import
iso8601_date
,
rfc850_date
,
rfc1123_date
...
...
@@ -122,3 +122,69 @@ def urlbase(url, ftype=urllib.splittype, fhost=urllib.splithost):
type
,
uri
=
ftype
(
url
)
host
,
uri
=
fhost
(
uri
)
return
uri
or
'/'
def
generateLockToken
():
# Generate a lock token
# XXX This is simple right now, just lifted from the original shortcut
# in Resource.dav__genlocktoken, but should be replaced by something
# better.
return
'AA9F6414-1D77-11D3-B825-00105A989226:%.03f'
%
time
.
time
()
def
tokenFinder
(
token
):
# takes a string like '<opaquelocktoken:afsdfadfadf> and returns the token
# part.
if
not
token
:
return
None
# An empty string was passed in
if
token
[
0
]
==
'['
:
return
None
# An Etag was passed in
if
token
[
0
]
==
'<'
:
token
=
token
[
1
:
-
1
]
return
token
[
string
.
find
(
token
,
':'
)
+
1
:]
### If: header handling support. IfParser returns a sequence of
### TagList objects in the order they were parsed which can then
### be used in WebDAV methods to decide whether an operation can
### proceed or to raise HTTP Error 412 (Precondition failed)
IfHdr
=
re
.
compile
(
r"(?P<resource><.+?>)?\
s*
\((?P<listitem>[^)]+)\
)
"
)
ListItem = re.compile(
r"
(
?
P
<
not
>
not
)
?
\
s
*
(
?
P
<
listitem
><
[
a
-
zA
-
Z
]
+
:[
^>
]
*>|
\
[.
*
?
\
])
",
re.I)
class TagList:
def __init__(self):
self.resource = None
self.list = []
self.NOTTED = 0
def IfParser(hdr):
out = []
i = 0
while 1:
m = IfHdr.search(hdr[i:])
if not m: break
i = i + m.end()
tag = TagList()
tag.resource = m.group('resource')
if tag.resource: # We need to delete < >
tag.resource = tag.resource[1:-1]
listitem = m.group('listitem')
tag.NOTTED, tag.list = ListParser(listitem)
out.append(tag)
return out
def ListParser(listitem):
out = []
NOTTED = 0
i = 0
while 1:
m = ListItem.search(listitem[i:])
if not m: break
i = i + m.end()
out.append(m.group('listitem'))
if m.group('not'): NOTTED = 1
return NOTTED, out
lib/python/webdav/davcmds.py
View file @
3beb18c2
This diff is collapsed.
Click to expand it.
lib/python/webdav/dtml/locknullmain.dtml
0 → 100644
View file @
3beb18c2
<dtml-var name="manage_page_header">
<dtml-var name="manage_tabs">
<p>This item is <span style="color: red">locked by WebDAV</span> as a
<strong>Lock-Null Resource</strong>. A lock-null resource is
created when a resource is locked before it is fully created,
basically reserving its name. When the owner of this resource
issues a command to either fill it with content, or turn it into a
collection (folder), that object will replace this one.</p>
<dtml-var name="manage_page_footer">
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment