Index: openacs-4/packages/oacs-dav/oacs-dav.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/oacs-dav.info,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/oacs-dav.info 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,26 @@
+
+
+
+
+ webDAV Support
+
+ f
+ t
+
+
+ dave bauer
+ Provides services to enable webDAV access to content repository items.
+ An interface to the tDAV webDAV package. oacs-dav provides services to offer webDAV access to content repository data.
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: openacs-4/packages/oacs-dav/catalog/oacs-dav.en_US.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/catalog/oacs-dav.en_US.ISO-8859-1.xml,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/catalog/oacs-dav.en_US.ISO-8859-1.xml 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,18 @@
+
+
+
+ Disable
+ Disable Selected Folders
+ Disabled
+ Enable
+ Enable Selected Folders
+ Enabled
+ Folder Name
+ Folder URL
+ Selected Folders disabled for WebDAV support.
+ Selected Folders enabled for WebDAV support.
+ Package Name
+ Package Type
+ Status
+ WebDAV Folder Administration
+
Index: openacs-4/packages/oacs-dav/sql/oracle/oacs-dav-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/sql/oracle/oacs-dav-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/sql/oracle/oacs-dav-create.sql 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,21 @@
+--
+-- @author Dave Bauer (dave@thedesignexperience.org)
+-- @creation-date 2003-10-18
+-- @cvs-id $Id: oacs-dav-create.sql,v 1.1 2004/02/16 16:49:27 daveb Exp $
+--
+
+-- create a table to map site node_ids to cr_folders
+
+create table dav_site_node_folder_map (
+ node_id integer
+ constraint dav_site_node_folder_map_node_id_un
+ unique
+ constraint dav_side_node_folder_map_node_id_fk
+ references apm_packages,
+ folder_id integer
+ constraint dav_impls_folder_id_fk
+ references cr_folders,
+ enabled_p char(1)
+ constraint dav_site_node_folder_map_enabled_p_bl
+ check enabled_p in ('t','f')
+);
Index: openacs-4/packages/oacs-dav/sql/oracle/oacs-dav-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/sql/oracle/oacs-dav-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/sql/oracle/oacs-dav-drop.sql 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,7 @@
+--
+-- @author Dave Bauer (dave@thedesignexperience.org)
+-- @creation-date 2003-10-19
+-- @cvs-id $Id: oacs-dav-drop.sql,v 1.1 2004/02/16 16:49:27 daveb Exp $
+--
+
+drop table dav_site_node_folder_map
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/sql/postgresql/oacs-dav-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/sql/postgresql/oacs-dav-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/sql/postgresql/oacs-dav-create.sql 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,22 @@
+--
+-- @author Dave Bauer (dave@thedesignexperience.org)
+-- @creation-date 2003-09-14
+-- @cvs-id $Id: oacs-dav-create.sql,v 1.1 2004/02/16 16:49:27 daveb Exp $
+--
+
+-- create a table to map site node_ids to cr_folders
+
+create table dav_site_node_folder_map (
+ node_id integer
+ constraint dav_site_node_folder_map_node_id_un
+ unique
+ constraint dav_side_node_folder_map_node_id_fk
+ references site_nodes,
+ folder_id integer
+ constraint dav_impls_folder_id_fk
+ references cr_folders,
+ enabled_p boolean
+);
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/sql/postgresql/oacs-dav-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/sql/postgresql/oacs-dav-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/sql/postgresql/oacs-dav-drop.sql 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,8 @@
+--
+-- @author Dave Bauer (dave@thedesignexperience.org)
+-- @creation-date 2003-09-28
+-- @cvs-id $Id:
+--
+
+drop table dav_site_node_folder_map;
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/oacs-dav-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/oacs-dav-init.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/oacs-dav-init.tcl 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,42 @@
+#
+
+ad_library {
+
+ setup filters
+
+ @author Dave Bauer (dave@thedesignexperience.org)
+ @creation-date 2003-12-18
+ @cvs-id $Id: oacs-dav-init.tcl,v 1.1 2004/02/16 16:49:27 daveb Exp $
+
+}
+
+set prefix [parameter::get \
+ -package_id [apm_package_id_from_key "oacs-dav"] \
+ -parameter "WebDAV URL Prefix" \
+ -default "/dav"]
+
+set url "${prefix}/*"
+set filter_url "${prefix}*"
+ns_register_filter preauth GET ${filter_url} oacs_dav::authorize
+ns_register_filter preauth PUT ${filter_url} oacs_dav::authorize
+ns_register_filter preauth MKCOL ${filter_url} oacs_dav::authorize
+ns_register_filter preauth COPY ${filter_url} oacs_dav::authorize
+ns_register_filter preauth MOVE ${filter_url} oacs_dav::authorize
+ns_register_filter preauth PROPFIND ${filter_url} oacs_dav::authorize
+ns_register_filter preauth PROPPATCH ${filter_url} oacs_dav::authorize
+ns_register_filter preauth DELETE ${filter_url} oacs_dav::authorize
+ns_register_filter preauth LOCK ${filter_url} oacs_dav::authorize
+ns_register_filter preauth UNLOCK ${filter_url} oacs_dav::authorize
+
+ns_log notice "OACS-DAV preauth filters loaded on $filter_url"
+
+ns_register_proc GET ${url} oacs_dav::handle_request
+ns_register_proc COPY ${url} oacs_dav::handle_request
+ns_register_proc PUT ${url} oacs_dav::handle_request
+ns_register_proc DELETE ${url} oacs_dav::handle_request
+ns_register_proc PROPFIND ${url} oacs_dav::handle_request
+ns_register_proc PROPPATCH ${url} oacs_dav::handle_request
+ns_register_proc MKCOL ${url} oacs_dav::handle_request
+ns_register_proc MOVE ${url} oacs_dav::handle_request
+ns_register_proc LOCK ${url} oacs_dav::handle_request
+ns_register_proc UNLOCK ${url} oacs_dav::handle_request
Index: openacs-4/packages/oacs-dav/tcl/oacs-dav-install-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/oacs-dav-install-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/oacs-dav-install-procs.tcl 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,205 @@
+#
+
+ad_library {
+
+ Setup procs to run at package install, should be run only once.
+
+ @author Dave Bauer (dave@thedesignexperience.org)
+ @creation-date 2003-09-11
+ @cvs-id $Id: oacs-dav-install-procs.tcl,v 1.1 2004/02/16 16:49:27 daveb Exp $
+
+}
+
+namespace eval oacs_dav::install {}
+
+ad_proc -private oacs_dav::install::package_install {} {
+ setup DAV service contracts
+} {
+ db_transaction {
+ create_service_contracts
+ register_implementation
+ }
+}
+
+ad_proc -private oacs_dav::install::package_uninstall {} {
+ clean up for package uninstall
+} {
+ db_transaction {
+ delete_service_contracts
+ unregister_implementation
+ }
+}
+
+# this is far from complete or even known to be going in the
+# right direction
+
+# somehow we need to get identication information from the
+# user and send back status of permission allowed or denied
+
+# look at the DAV spec to get an idea of what inputs and
+# outputs these methods have
+
+ad_proc -private oacs_dav::install::create_service_contracts {
+} {
+ create service contract for DAV methods
+} {
+ oacs_dav::install::create_dav_sc
+ oacs_dav::install::create_dav_put_type_sc
+}
+
+ad_proc -private oacs_dav::install::create_dav_sc {
+} {
+ create dav service contract spec
+} {
+ set contract_name "dav"
+ set dav_spec {
+ description "implements DAV methods"
+ operations {
+ get {
+ description "DAV GET Method"
+ output { content:string }
+ }
+ put {
+ description "DAV PUT Method"
+ output { response:string }
+ }
+ propfind {
+ description "DAV PROPFIND Method"
+ output {
+ response:string
+ }
+ }
+ delete {
+ description "DAV DELETE Method"
+ output {
+ response:string
+ }
+ }
+ mkcol {
+ description "DAV MKCOL Method"
+ output {
+ response:string
+ }
+ }
+ copy {
+ description "DAV Copy Method"
+ output {
+ response:string
+ }
+ }
+ move {
+ description "DAV Move Method"
+ output {
+ response:string
+ }
+ }
+ proppatch {
+ description "DAV PROPATCH Method"
+ output {
+ response:string
+ }
+ }
+ lock {
+ description "DAV LOCK Method"
+ output {
+ response:string
+ }
+ }
+ unlock {
+ description "DAV UNLOCK Method"
+ output {
+ response:string
+ }
+ }
+ }
+ }
+
+
+ acs_sc::contract::new_from_spec \
+ -spec [concat [list name $contract_name] $dav_spec ]
+}
+
+ad_proc -private oacs_dav::install::create_dav_put_type_sc {
+} {
+ create dav_put_type service contract
+} {
+ set contract_name "dav_put_type"
+ set dav_spec {
+ description "returns content type to use for PUT operation"
+ operations {
+ get_type {
+ description "DAV PUT Content Type"
+ output { content_type:string }
+ }
+ }
+ }
+
+ acs_sc::contract::new_from_spec \
+ -spec [concat [list name $contract_name] $dav_spec ]
+
+}
+
+ad_proc -private oacs_dav::install::delete_service_contracts {
+} {
+ remove service contracts on uninstall
+} {
+ acs_sc::contract::delete -name dav
+ acs_sc::contract::delete -name dav_put_type
+}
+
+ad_proc -private oacs_dav::install::register_implementation {
+} {
+ add default content repository service contract
+ implementation
+} {
+
+ set spec {
+ name "content_revision"
+ aliases {
+ get oacs_dav::impl::content_revision::get
+ put oacs_dav::impl::content_revision::put
+ propfind oacs_dav::impl::content_revision::propfind
+ delete oacs_dav::impl::content_revision::delete
+ mkcol oacs_dav::impl::content_revision::mkcol
+ proppatch oacs_dav::impl::content_revision::proppatch
+ copy oacs_dav::impl::content_revision::copy
+ move oacs_dav::impl::content_revision::move
+ lock oacs_dav::impl::content_revision::lock
+ unlock oacs_dav::impl::content_revision::unlock
+ }
+ contract_name {dav}
+ owner [oacs_dav::package_key]
+ }
+
+ acs_sc::impl::new_from_spec -spec $spec
+
+ set spec {
+ name "content_folder"
+ aliases {
+ get oacs_dav::impl::content_folder::get
+ put oacs_dav::impl::content_folder::put
+ propfind oacs_dav::impl::content_folder::propfind
+ delete oacs_dav::impl::content_folder::delete
+ mkcol oacs_dav::impl::content_folder::mkcol
+ proppatch oacs_dav::impl::content_folder::proppatch
+ copy oacs_dav::impl::content_folder::copy
+ move oacs_dav::impl::content_folder::move
+ lock oacs_dav::impl::content_folder::lock
+ unlock oacs_dav::impl::content_folder::unlock
+ }
+ contract_name {dav}
+ owner [oacs_dav::package_key]
+ }
+
+ acs_sc::impl::new_from_spec -spec $spec
+
+}
+
+
+ad_proc -private oacs_dav::install::unregister_implementation {
+} {
+ remove default service contract implementation
+} {
+ acs_sc::impl::delete -contract_name dav -impl_name content_folder
+ acs_sc::impl::delete -contract_name dav -impl_name content_revision
+}
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/oacs-dav-procs-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/oacs-dav-procs-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/oacs-dav-procs-oracle.xql 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,242 @@
+
+
+ oracle8.1.6
+
+
+ select content_item.get_id(
+ name => :item_name,
+ root_folder_id => :parent_id,
+ resolve_index_p => 'f')
+
+
+
+
+
+ select nvl (cr.content_length,4096) as content_length,
+ nvl (cr.mime_type,'*/*') as mime_type,
+ to_char(timezone('GMT',o.creation_date) :: timestamptz ,'YYYY-MM-DD"T"HH:MM:SS.MS"Z"') as creation_date,
+ to_char(timezone('GMT',o.last_modified) :: timestamptz ,'Dy, DD Mon YYYY HH:MM:SS TZ') as last_modified,
+ ci1.item_id,
+ case when ci1.item_id=ci2.item_id then '' else ci1.name end as name,
+ content_item.get_path(ci1.item_id,:folder_id) as item_uri,
+ case when o.object_type='content_folder' then 1 else 0 end
+ as collection_p
+ from (
+ select * from cr_items
+ connect by prior item_id=parent_id
+ start with item_id=:item_id
+ ) ci1,
+ cr_revisions,
+ acs_objects o
+ where
+ ci1.live_revision(+) = cr.revision_id,
+ and exists (select 1
+ from acs_object_party_privilege_map m
+ where m.object_id = ci1.item_id
+ and m.party_id = :user_id
+ and m.privilege = 'read')
+
+
+
+
+
+ select
+ ci.item_id,
+ ci.name,
+ content_item__get_path(ci.item_id,:folder_id) as item_uri,
+ coalesce(cr.mime_type,'*/*') as mime_type,
+ cr.content_length,
+ to_char(timezone('GMT',o.creation_date) :: timestamptz ,'YYYY-MM-DD"T"HH:MM:SS.MS"Z"') as creation_date,
+ to_char(timezone('GMT',o.last_modified) :: timestamptz ,'Dy, DD Mon YYYY HH:MM:SS TZ') as last_modified
+ from cr_items ci,
+ acs_objects o,
+ cr_revisions cr
+ where
+ ci.item_id=:item_id
+ and ci.item_id = o.object_id
+ and cr.revision_id=ci.live_revision
+
+
+
+
+
+ select content_folder.new(
+ name => :new_folder_name,
+ label => :label,
+ description => :description,
+ parent_id => :parent_id,
+ context_id => :parent_id,
+ new_folder_id => NULL,
+ creation_date => current_timestamp,
+ creation_user => :user_id,
+ creation_ip => :peer_addr
+ )
+
+
+
+
+
+ select content_folder.copy (
+ folder_id => :copy_folder_id,
+ target_folder_id => :new_parent_folder_id,
+ creation_user => :user_id,
+ creation_ip => :peer_addr,
+ name => :new_name
+ )
+
+
+
+
+
+ select content_folder.move (
+ folder_id => :move_folder_id,
+ target_folder_id => :new_parent_folder_id,
+ name => :new_name
+ )
+
+
+
+
+
+ select content_folder.rename (
+ folder_id => :move_folder_id,
+ name => :new_name,
+ label => NULL,
+ description => NULL
+ )
+
+
+
+
+
+ select content_item.move (
+ item_id => :item_id,
+ target_folder_id => :new_parent_folder_id,
+ name => :new_name
+ )
+
+
+
+
+
+ select content_item.rename (
+ item_id => :item_id,
+ name => :new_name
+ )
+
+
+
+
+
+ select content_item.copy (
+ item_id => :copy_item_id,
+ target_id => :new_parent_folder_id,
+ creation_user => :user_id,
+ creation_ip => :peer_addr,
+ name => :new_name
+ )
+
+
+
+
+
+ select content_item.delete(
+ item_id => :dest_item_id
+ )
+
+
+
+
+
+ select content_item.delete(
+ item_id => :dest_item_id
+ )
+
+
+
+
+
+ select content_item.delete (
+ item_id => :item_id
+ )
+
+
+
+
+
+ select content_folder.delete (
+ folder_id => :item_id,
+ cascade_p => 't'
+ )
+
+
+
+
+
+
+ select content_item.get_id(
+ name=> :parent_name,
+ root_folder_id => :root_folder_id,
+ resolve_index_p => 'f')
+
+
+
+
+
+ select content_item.get_id(
+ name => :new_name,
+ root_folder_id => :new_parent_folder_id,
+ resolve_index_p => 'f')
+
+
+
+
+
+ select content_item.get_id(
+ name => :new_name,
+ root_folder_id => :new_parent_folder_id,
+ resolve_index_p => 'f')
+
+
+
+
+
+ select content_folder.delete(
+ folder_id => :dest_item_id,
+ cascade_p => 't');
+
+
+
+
+
+ select content_folder.delete(
+ folder_id => :dest_item_id,
+ cascade_p => 't');
+
+
+
+
+
+ select content_item.get_id(
+ name => :new_name,
+ root_folder_id => :new_parent_folder_id,
+ resolve_index_p => 'f')
+
+
+
+
+
+ select content_item.get_id(
+ name => :new_name,
+ root_folder_id => :new_parent_folder_id,
+ resolve_index_p => 'f')
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/oacs-dav-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/oacs-dav-procs-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/oacs-dav-procs-postgresql.xql 16 Feb 2004 16:49:27 -0000 1.1
@@ -0,0 +1,223 @@
+
+
+ postgresql7.1
+
+
+
+ select content_item__get_id(:item_name,:parent_id,'f')
+
+
+
+
+
+ select coalesce (cr.content_length,4096) as content_length,
+ coalesce(cr.mime_type,'*/*') as mime_type,
+ to_char(timezone('GMT',o.creation_date) :: timestamptz ,'YYYY-MM-DD"T"HH:MM:SS.MS"Z"') as creation_date,
+ to_char(timezone('GMT',o.last_modified) :: timestamptz ,'Dy, DD Mon YYYY HH:MM:SS TZ') as last_modified,
+ ci1.item_id,
+ case when ci1.item_id=ci2.item_id then '' else ci1.name end as name,
+ content_item__get_path(ci1.item_id,:folder_id) as item_uri,
+ case when o.object_type='content_folder' then 1 else 0 end
+ as collection_p
+ from cr_items ci1 left join cr_revisions cr on ci1.live_revision = cr.revision_id,
+ cr_items ci2,
+ acs_objects o
+ where ci1.tree_sortkey between ci2.tree_sortkey and
+ tree_right(ci2.tree_sortkey)
+ and ci2.item_id=:folder_id
+ and ci1.item_id = o.object_id
+ and (tree_level(ci1.tree_sortkey) - tree_level(ci2.tree_sortkey))
+ <= :depth :: integer
+ and exists (select 1
+ from acs_object_party_privilege_map m
+ where m.object_id = ci1.item_id
+ and m.party_id = :user_id
+ and m.privilege = 'read')
+
+
+
+
+
+ select
+ ci.item_id,
+ ci.name,
+ content_item__get_path(ci.item_id,:folder_id) as item_uri,
+ coalesce(cr.mime_type,'*/*') as mime_type,
+ cr.content_length,
+ to_char(timezone('GMT',o.creation_date) :: timestamptz ,'YYYY-MM-DD"T"HH:MM:SS.MS"Z"') as creation_date,
+ to_char(timezone('GMT',o.last_modified) :: timestamptz ,'Dy, DD Mon YYYY HH:MM:SS TZ') as last_modified
+ from cr_items ci,
+ acs_objects o,
+ cr_revisions cr
+ where
+ ci.item_id=:item_id
+ and ci.item_id = o.object_id
+ and cr.revision_id=ci.live_revision
+ and exists (select 1
+ from acs_object_party_privilege_map m
+ where m.object_id = ci.item_id
+ and m.party_id = :user_id
+ and m.privilege = 'read')
+
+
+
+
+
+ select content_folder__new(
+ :new_folder_name,
+ :label,
+ :description,
+ :parent_id,
+ :parent_id,
+ NULL,
+ current_timestamp,
+ :user_id,
+ :peer_addr
+ )
+
+
+
+
+
+ select content_folder__copy (
+ :copy_folder_id,
+ :new_parent_folder_id,
+ :user_id,
+ :peer_addr,
+ :new_name
+ )
+
+
+
+
+
+ select content_folder__move (
+ :move_folder_id,
+ :new_parent_folder_id,
+ :new_name
+ )
+
+
+
+
+
+ select content_folder__rename (
+ :move_folder_id,
+ :new_name,
+ NULL,
+ NULL
+ )
+
+
+
+
+
+ select content_item__move (
+ :item_id,
+ :new_parent_folder_id,
+ :new_name
+ )
+
+
+
+
+
+ select content_item__rename (
+ :item_id,
+ :new_name
+ )
+
+
+
+
+
+ select content_item__copy (
+ :copy_item_id,
+ :new_parent_folder_id,
+ :user_id,
+ :peer_addr,
+ :new_name
+ )
+
+
+
+
+
+ select content_item__delete(:dest_item_id)
+
+
+
+
+
+ select content_item__delete(:dest_item_id)
+
+
+
+
+
+ select content_item__delete (
+ :item_id
+ )
+
+
+
+
+
+ select content_folder__delete (
+ :item_id,
+ 't'
+ )
+
+
+
+
+
+
+ select content_item__get_id(:parent_name,:root_folder_id,'f')
+
+
+
+
+
+ select content_item__get_id(:new_name,:new_parent_folder_id,'f')
+
+
+
+
+
+ select content_item__get_id(:new_name,:new_parent_folder_id,'f')
+
+
+
+
+
+ select content_folder__delete(:dest_item_id,'t');
+
+
+
+
+
+ select content_folder__delete(:dest_item_id,'t');
+
+
+
+
+
+ select content_item__get_id(:new_name,:new_parent_folder_id,'f')
+
+
+
+
+
+ select content_item__get_id(:new_name,:new_parent_folder_id,'f')
+
+
+
+
+
Index: openacs-4/packages/oacs-dav/tcl/oacs-dav-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/oacs-dav-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/oacs-dav-procs.tcl 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,1028 @@
+# /packages/oacs-dav/tcl/oacs-dav-procs.tcl
+ns_log notice "Loading oacs-dav-procs.tcl"
+ad_library {
+
+ Support for tDAV tcl webDAV implemenation
+
+ @author Dave Bauer (dave@thedesignexperience.org)
+ @creation-date 2003-09-11
+ @cvs-id $Id: oacs-dav-procs.tcl,v 1.1 2004/02/16 16:49:28 daveb Exp $
+
+}
+
+namespace eval oacs_dav {}
+
+
+ad_proc oacs_dav::set_user_id {} {
+ set user_id based on authentication header
+} {
+
+ # should be something like "Basic 29234k3j49a"
+ set a [ns_set get [ns_conn headers] Authorization]
+ if {[string length $a]} {
+ ns_log notice "TDAV auth_check authentication info $a"
+ # get the second bit, the base64 encoded bit
+ set up [lindex [split $a " "] 1]
+ # after decoding, it should be user:password; get the username
+ set user [lindex [split [ns_uudecode $up] ":"] 0]
+ set password [lindex [split [ns_uudecode $up] ":"] 1]
+ ns_log notice "ACS VERSION [ad_acs_version]"
+ switch -glob -- [ad_acs_version] {
+ "5.0*" {
+ ns_log debug "TDAV 5.0 authentication"
+ array set auth [auth::authenticate \
+ -username $user \
+ -password $password]
+ if {![string equal $auth(auth_status) "ok"]} {
+ array set auth [auth::authenticate \
+ -email $user \
+ -password $password]
+ if {![string equal $auth(auth_status) "ok"]} {
+ ns_log debug "TDAV 5.0 auth status $auth(auth_status)"
+ ns_returnunauthorized
+ return 0
+ }
+
+ }
+ ns_log notice "TDAV: auth_check openacs 5.0 user_id= $auth(user_id)"
+ ad_conn -set user_id $auth(user_id)
+ return
+ }
+ default {
+ # for 4.6:
+ ns_log debug "TDAV 4.6 authentication"
+ set email [string tolower $user]
+ if {[db_0or1row user_login_user_id_from_email {
+ select user_id, member_state, email_verified_p
+ from cc_users
+ where email = :email}] } {
+
+ if {[ad_check_password $user_id $password]} {
+ ns_log notice "TDAV setting user_id $user_id"
+ ad_conn -set user_id $user_id
+ ad_conn -set untrusted_user_id $user_id
+ return
+ }
+
+ }
+ ns_log notice "TDAV: openacs user/password not matched"
+ ns_returnunauthorized
+ return
+
+ }
+ }
+ } else {
+ # no authenticate header, anonymous visitor
+ ad_conn -set user_id 0
+ ad_conn -set untrusted_user_id 0
+ }
+}
+
+ad_proc oacs_dav::authorize { args } {
+ check is user_id has permission to perform the WebDAV method on
+ the URI
+} {
+ ns_log notice "OACS-DAV running oacs_dav::authorize"
+ # set common data for all requests
+ oacs_dav::conn_setup
+
+ set method [string tolower [oacs_dav::conn method]]
+ set item_id [oacs_dav::conn item_id]
+ set user_id [oacs_dav::conn user_id]
+ set folder_id [oacs_dav::conn folder_id]
+ ns_log notice "OACS-DAV oacs_dav::authorize user_id $user_id method $method item_id $item_id"
+ set authorized_p 0
+ # if item doesn't exist don't bother checking....
+ if {[empty_string_p $item_id]} {
+ if {![string equal $method "put"] && ![string equal $method "mkcol"]} {
+ ns_log notice "oacs_dav::authorize file not found!!!!!"
+ ns_return 404 text/plain "File Not Found"
+ return filter_return
+ }
+ }
+ switch $method {
+ put -
+ mkcol {
+ set authorized_p [permission::permission_p \
+ -object_id $folder_id \
+ -party_id $user_id \
+ -privilege "create"]
+ }
+ delete {
+ set authorized_p [permission::permission_p \
+ -object_id $item_id \
+ -party_id $user_id \
+ -privilege "delete"]
+ }
+ lock -
+ unlock -
+ proppatch {
+ set authorized_p [permission::permission_p \
+ -object_id $item_id \
+ -party_id $user_id \
+ -privilege "write"]
+ }
+ copy -
+ move {
+ set authorized_p [expr [permission::permission_p \
+ -object_id $item_id \
+ -party_id $user_id \
+ -privilege "read"] && \
+ [permission::permission_p \
+ -object_id [oacs_dav::conn dest_parent_id ] \
+ -party_id $user_id \
+ -privilege "create"]]
+
+ }
+ propfind -
+ get {
+ # default for GET PROPFIND
+ set authorized_p [permission::permission_p \
+ -object_id $item_id \
+ -party_id $user_id \
+ -privilege "read"]
+ }
+ }
+ if {![string equal $authorized_p 1]} {
+ ns_returnunauthorized
+ return filter_return
+ }
+ return filter_ok
+}
+
+ad_proc -public oacs_dav::conn {
+ args
+} {
+ shared data for WebDAV requests
+} {
+ global tdav_conn
+ set flag [lindex $args 0]
+ if { [string index $flag 0] != "-" } {
+ set var $flag
+ set flag "-get"
+ } else {
+ set var [lindex $args 1]
+ }
+ switch -- $flag {
+ -set {
+ set value [lindex $args 2]
+ set tdav_conn($var) $value
+ return $value
+ }
+ -get {
+ if { [info exists tdav_conn($var)] } {
+ return $tdav_conn($var)
+ } else {
+ return [ad_conn $var]
+ }
+ }
+ }
+}
+
+ad_proc -public oacs_dav::register_folder {
+ {-enabled_p "t"}
+ folder_id
+ node_id
+} {
+ add a uri to dav support
+ @param folder_id
+ @param node_id
+ Register a root WebDAV enabled folder for a site node_id
+ All requests that resolve to this site node id will be checked for
+ WebDAV content using this folder as the root. Only one folder per
+ node_id can be registered.
+} {
+
+ db_transaction {
+ db_dml add_folder ""
+ } on_error {
+ ns_log error "OACS-DAV Failed attempt to add folder_id $folder_id as a WebDAV enabled folder for node_id $node_id. One folder is already registered"
+ error "Only one folder per node_id may be registered."
+ }
+}
+
+ad_proc -public oacs_dav::unregister_folder {
+ folder_id
+ node_id
+} {
+ remove a uri from dav support
+ @param folder_id
+ @param node_id
+} {
+ db_dml remove_folder ""
+}
+
+ad_proc -public oacs_dav::item_parent_folder_id {
+ uri
+} {
+ get the folder_id of the parent of an item
+ from the uri
+ @param uri
+ @returns parent_folder_id or empty string if folder does not exist
+} {
+ ns_log notice "OACS-DAV:item parent folder_id uri $uri"
+ array set sn [oacs_dav::request_site_node $uri]
+ set node_id $sn(node_id)
+ set root_folder_id [oacs_dav::request_folder_id $node_id]
+ set urlv [split [string trimright [string range $uri [string length $sn(url)] end] "/"] "/"]
+ if {[llength $urlv] >1} {
+ set parent_name [join [lrange $urlv 0 [expr [llength $urlv] -2 ] ] "/" ]
+ } else {
+ set parent_name "/"
+ }
+ ns_log debug "parent_folder_id urlv $urlv parent_name $parent_name uri $uri"
+ if {[string equal [string trimright $parent_name "/"] [string trimright $sn(url) "/"]]} {
+ # content_item__get_id can't resolve "/"
+ # because it strips the leading and trailing /
+ # from the url you pass in, and cr_items.name of the folder
+ # is not and empty string
+ set parent_id $root_folder_id
+ } else {
+ set parent_id [db_exec_plsql get_parent_folder_id ""]
+ }
+ return $parent_id
+}
+
+ad_proc -public oacs_dav::conn_setup {} {
+ Setup oacs_dav::conn, authenticate user
+} {
+ ad_conn -reset
+ set uri [ns_conn url]
+ set oacs_dav_package_id [apm_package_id_from_key "oacs-dav"]
+ set dav_url_regexp "^[parameter::get -package_id $oacs_dav_package_id -parameter "WebDAV URL Prefix" -default "/dav"]"
+ set uri [regsub $dav_url_regexp $uri {}]
+ oacs_dav::conn -set uri $uri
+ set method [ns_conn method]
+ oacs_dav::set_user_id
+ ns_log notice "OACS-DAV conn_setup uri $uri method $method user_id [oacs_dav::conn user_id]"
+ array set sn [oacs_dav::request_site_node $uri]
+ set node_id [oacs_dav::conn -set node_id $sn(node_id)]
+ set package_id [oacs_dav::conn -set package_id $sn(package_id)]
+ set folder_id [oacs_dav::conn -set folder_id [oacs_dav::request_folder_id [oacs_dav::conn node_id]]]
+ set urlv [oacs_dav::conn -set urlv [split [string trimright $uri "/"] "/"]]
+
+ if {[catch {[oacs_dav::conn destination]} destination]} {
+ set destination [oacs_dav::conn -set destination [ns_set iget [ns_conn headers] Destination]]
+ }
+ regsub {http://[^/]+/} $destination {/} dest
+ ns_log notice "DEST = $dest"
+ set dest [regsub $dav_url_regexp $dest {}]
+ oacs_dav::conn -set destination $dest
+ if {![empty_string_p $dest]} {
+ oacs_dav::conn -set dest_parent_id [oacs_dav::item_parent_folder_id $dest]
+ }
+
+ # we need item_id and content_type
+ # we should use content::init but that has caching and I don't
+ # have time to resolve the issues that raises right now
+ # a full-featured, consistently used tcl api for CR will fix that
+ if {[llength $urlv] > 2} {
+ set parent_url [join [lrange $urlv 0 [expr [llength $urlv] -2 ] ] "/" ]
+ } else {
+ set parent_url "/"
+ }
+ ns_log debug "handle request parent_url $parent_url length urlv [llength $urlv] urlv $urlv"
+ set item_name [lindex $urlv end]
+ if {[empty_string_p $item_name]} {
+ # for propget etc we need the name of the folder
+ # the last element in urlv for a folder is an empty string
+ set item_name [lindex [split [string trimleft $parent_url "/"] "/"] end]
+ }
+ oacs_dav::conn -set item_name $item_name
+ ns_log debug "handle request parent_url $parent_url length urlv [llength $urlv] urlv $urlv item_name $item_name"
+ set parent_id [oacs_dav::item_parent_folder_id $uri]
+
+ set item_id [oacs_dav::conn -set item_id [db_exec_plsql get_item_id ""]]
+ ns_log notice "OACS-DAV uri $uri parent_url $parent_url folder_id $folder_id"
+ if {[string equal [string trimright $uri "/"] [string trimright $sn(url) "/"]]} {
+ set item_id [oacs_dav::conn -set item_id $folder_id]
+ }
+
+ ns_log notice "OACS-DAV setup conn item_id $item_id"
+}
+
+ad_proc -public oacs_dav::handle_request { uri method args } {
+ dispatch request to the proper service contract implmentation
+} {
+
+ set uri [ns_conn url]
+ set method [string tolower [ns_conn method]]
+ns_log debug "oacs_dav::handle_request method=$method uri=$uri"
+ set item_id [oacs_dav::conn item_id]
+ set folder_id [oacs_dav::conn folder_id]
+ set package_id [oacs_dav::conn package_id]
+ set node_id [oacs_dav::conn node_id]
+ set package_key [apm_package_key_from_id $package_id]
+
+ ns_log debug "DAV item_id is $item_id"
+ if {[empty_string_p $item_id]} {
+ ns_log debug "DAV: item_id is empty"
+ # set this to null if nothing exists, only valid on PUT or MKCOL
+ # to create a new item, otherwise we bail
+ # item for URI does not exist
+ # ask package what content type to use
+ switch -- $method {
+ mkcol {
+ set content_type "content_folder"
+ }
+ put {
+ if {![acs_sc_binding_exists_p dav_put_type $package_key]} {
+ set content_type "content_revision"
+ } else {
+ set content_type [acs_sc_call dav_put_type get_type "" $package_key]
+ }
+
+ }
+ default {
+ # return a 404 or other error
+ ns_log notice "DAV:handle request Item not found method $method URI $uri"
+ ns_return 404 text/html "File Not Found"
+ return
+ }
+ }
+
+ } else {
+ # get content type of existing item
+ set content_type \
+ [oacs_dav::conn -set content_type \
+ [db_string get_content_type "" -default "content_revision"]]
+ }
+ # use content type
+ # i think we should walk up the object type hierarchy up to
+ # content_revision if we don't find an implementation
+ # implementation name is content_type
+
+ if {![acs_sc_binding_exists_p dav $content_type]} {
+ # go up content_type hierarchy
+ # we do the query here to avoid running the query
+ # when the implementation for the content_type does
+ # exist
+
+ #FIXME: write the query etc
+ set content_type "content_revision"
+ }
+
+ oacs_dav::conn -set content_type $content_type
+
+ # probably should catch this
+
+ ns_log debug "oacs_dav::handle_request method $method uri $uri item_id $item_id folder_id $folder_id package_id $package_id node_id $node_id content_type $content_type args $args"
+
+ set response [acs_sc_call dav $method "" $content_type]
+
+ # here the sc impl might return us some data,
+ # then we would probably have to send that to tDAV for processing
+ns_log debug "DAV: response is $response"
+
+ tdav::respond $response
+}
+
+ad_proc -public oacs_dav::request_site_node { uri } {
+ resolves uri to a site node_id
+} {
+ # if you want to serve up DAV content at a different URL
+ # you still need to mount a package in the site-map
+ # might change later when we figure out how to actually use it
+ ns_log notice "OACS-DAV!! uri $uri"
+# if {[empty_string_p $uri]} {
+# set uri [ns_conn url]
+# }
+ set sn [site_node::get -url $uri]
+ return $sn
+}
+
+ad_proc -public oacs_dav::request_folder_id { node_id } {
+ resolves a node_id to a DAV enabled folder_id
+ @param node_id site node_id of request
+ @returns folder_id, or empty string if no folder exists
+ in dav_package_folder_map for this node_id
+} {
+ return [db_string get_folder_id "" -default ""]
+}
+
+namespace eval oacs_dav::impl::content_folder {}
+
+# this is probably going away, is there such thing as "source"
+# of a folder/collection?
+
+ad_proc oacs_dav::impl::content_folder::get {} {
+ GET DAV method for content folders
+ can't get a folder
+} {
+
+ # return something
+ # if its just a plain file, and a GET then do we need to send anything
+ # extra or just the file?
+ return [list 409]
+}
+
+ad_proc oacs_dav::impl::content_folder::mkcol {} {
+ MKCOL DAV method for generic content folder
+ @author Dave Bauer
+} {
+ set uri [oacs_dav::conn uri]
+ set user_id [oacs_dav::conn user_id]
+ set peer_addr [oacs_dav::conn peeraddr]
+ set item_id [oacs_dav::conn item_id]
+ set fname [oacs_dav::conn item_name]
+ set parent_id [oacs_dav::item_parent_folder_id $uri]
+ if {[empty_string_p $parent_id]} {
+ return [list 409]
+ }
+ if { ![empty_string_p $item_id]} {
+ return [list 405]
+ }
+
+ # probably have to revisit setting content_types allowed
+ # and permissions, but inheriting from the parent seems
+ # reasonable
+
+ db_transaction {
+ set new_folder_name $fname
+ set label $fname
+ set description $fname
+ set new_folder_id [db_exec_plsql create_folder ""]
+ set response [list 201]
+ } on_error {
+ set response [list 500]
+ }
+
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_folder::copy {} {
+ COPY DAV method for generic content folder
+} {
+ set package_id [oacs_dav::conn package_id]
+ set user_id [oacs_dav::conn user_id]
+ set peer_addr [oacs_dav::conn peeraddr]
+ set copy_folder_id [oacs_dav::conn item_id]
+ set overwrite [oacs_dav::conn overwrite]
+ set target_uri [oacs_dav::conn destination]
+ set new_parent_folder_id [oacs_dav::conn dest_parent_id]
+ set durlv [split [string trimright $target_uri "/"] "/"]
+ set new_name [lindex $durlv end]
+ set uri [oacs_dav::conn uri]
+ # check that destination exists and is WebDAV enabled
+ # when depth is 0 copy just the folder
+ # when depth is 1 copy contents
+ns_log notice "DAV Folder Copy dest $target_uri parent_id $new_parent_folder_id"
+ if {[empty_string_p $new_parent_folder_id]} {
+ return [list 409]
+ }
+
+ set dest_item_id [db_string get_dest_id ""]
+ if {![empty_string_p $dest_item_id]} {
+ ns_log notice "DAV Folder Copy Folder Exists item_id $dest_item_id overwrite $overwrite"
+ if {![string equal -nocase $overwrite "T"]} {
+ return [list 412]
+ } elseif {![permission::permission_p \
+ -object_id $dest_item_id \
+ -party_id $user_id \
+ -privilege "write"]} {
+ ns_returnunauthorized
+ }
+ # according to the spec copy with overwrite means
+ # delete then copy
+ if {![string equal "unlocked" [tdav::check_lock $target_uri]]} {
+ return [list 423]
+ }
+ db_exec_plsql delete_for_copy ""
+ }
+
+ db_transaction {
+ db_exec_plsql copy_folder ""
+ } on_error {
+ return [list 500]
+ }
+ set response [list 201]
+ tdav::copy_props $uri $target_uri
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_folder::move {} {
+ MOVE DAV method for generic content folder
+} {
+ set package_id [oacs_dav::conn package_id]
+ set user_id [oacs_dav::conn user_id]
+ set peer_addr [oacs_dav::conn peeraddr]
+ set uri [oacs_dav::conn uri]
+ set target_uri [oacs_dav::conn destination]
+ set move_folder_id [oacs_dav::conn item_id]
+ set item_name [oacs_dav::conn item_name]
+ set new_parent_folder_id [oacs_dav::conn dest_parent_id]
+ set cur_parent_folder_id [oacs_dav::item_parent_folder_id $uri]
+ set turlv [split [string trimright $target_uri "/"] "/"]
+ set new_name [lindex $turlv end]
+ set overwrite [oacs_dav::conn overwrite]
+
+ if {[empty_string_p $new_parent_folder_id]} {
+ set response [list 412]
+ return $response
+ }
+
+ set dest_item_id [db_string get_dest_id ""]
+ ns_log debug "@DAV@@ folder move new_name $new_name dest_id $dest_item_id new_folder_id $new_parent_folder_id"
+ if {![empty_string_p $dest_item_id]} {
+ ns_log notice "DAV Folder Move Folder Exists item_id $dest_item_id overwrite $overwrite"
+ if {![string equal -nocase $overwrite "T"]} {
+ return [list 412]
+ } elseif {![permission::permission_p \
+ -object_id $dest_item_id \
+ -party_id $user_id \
+ -privilege "write"]} {
+ ns_returnunauthorized
+ }
+ # according to the spec copy with overwrite means
+ # delete then copy
+ if {![string equal "unlocked" [tdav::check_lock $target_uri]]} {
+ return [list 423]
+ }
+
+
+ db_exec_plsql delete_for_move ""
+ ns_log debug "CONTEXT IDS [db_list get_ids "select object_id from acs_objects where context_id=:dest_item_id"]"
+ }
+ # don't let anyone move root DAV folders in the
+ # dav_site_node_folder_map
+ if {![string equal [db_string site_node_folder ""] 0]} {
+ return [list 403]
+ }
+
+ db_transaction {
+
+ if {![string equal $cur_parent_folder_id $new_parent_folder_id]} {
+ ns_log debug "@@DAV@@ move folder $move_folder_id"
+ db_exec_plsql move_folder ""
+ } elseif {![empty_string_p $new_name]} {
+ ns_log debug "@@DAV@@ move folder rename $move_folder_id to $new_name"
+ db_exec_plsql rename_folder ""
+ }
+ set response [list 204]
+ } on_error {
+ return [list 500]
+ }
+ tdav::copy_props $uri $target_uri
+ tdav::delete_props $uri
+ tdav::remove_lock $uri
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_folder::delete {} {
+ DELETE DAV method for generic content folder
+} {
+ set package_id [oacs_dav::conn package_id]
+ set user_id [oacs_dav::conn user_id]
+ set peer_addr [oacs_dav::conn peeraddr]
+ set item_id [oacs_dav::conn item_id]
+ set uri [oacs_dav::conn uri]
+
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ return [list 423]
+ }
+ if {[catch {db_exec_plsql delete_folder ""} errmsg]} {
+ ns_log error "content_folder::delete $errmsg"
+ set response [list 500]
+# ns_log debug "CONTEXT IDS [db_list get_ids "select object_id from acs_objects where context_id=:item_id"]"
+ } else {
+ set response [list 204]
+ tdav::delete_props $uri
+ tdav::remove_lock $uri
+ }
+
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_folder::propfind {} {
+ PROPFIND DAV method for generic content folder
+} {
+ set user_id [oacs_dav::conn user_id]
+ set depth [oacs_dav::conn depth]
+ set folder_uri [ad_url][ad_conn url]
+ # if client didn't put a / on folder_uri go ahead and tack it on
+ if {![string match */ $folder_uri]} {
+ append folder_uri "/"
+ }
+ if {[empty_string_p $depth]} {
+ set depth 0
+ }
+
+ set prop_req [oacs_dav::conn prop_req]
+ set folder_id [oacs_dav::conn item_id]
+
+ # append the properties into response
+ set all_properties [list]
+ db_foreach get_properties "" {
+ set name $name
+ set etag "1f9a-400-3948d0f5"
+ set properties [list]
+ # is "D" the namespace??
+ lappend properties [list "D" "getcontentlength"] $content_length
+
+ ns_log debug "DAVEB item_id $item_id folder_id $folder_id $item_uri"
+ if {$item_id == $folder_id} {
+ set item_uri ""
+ }
+
+ lappend properties [list "D" "getcontenttype"] $mime_type
+ # where do we get an etag from?
+ lappend properties [list "D" "getetag"] $etag
+ lappend properties [list "D" "getlastmodified"] $last_modified
+ lappend properties [list "D" "creationdate"] $creation_date
+ if {$collection_p} {
+ lappend properties [list "D" "resourcetype"] "D:collection"
+ } else {
+ lappend properties [list "D" "resourcetype"] ""
+ }
+
+ # according to Todd's example
+ # resourcetype for a folder(collection) is
+ # and getcontenttype is */*
+ foreach i [tdav::get_user_props ${folder_uri}${item_uri} $depth $prop_req] {
+ lappend properties $i
+ }
+ lappend all_properties [list ${folder_uri}${item_uri} $collection_p $properties]
+ }
+
+ set response [list 207 $all_properties]
+
+ return $response
+
+
+}
+
+ad_proc oacs_dav::impl::content_folder::proppatch {} {
+ PROPPATCH DAV method for generic content folder
+ user-properties are stored in the filesystem by tDAV
+ this doesn't do anything until tDAV allows storage of
+ user properties in the database
+} {
+ set uri [oacs_dav::conn uri]
+
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ return [list 423]
+ }
+
+ set response [tdav::update_user_props $uri [oacs_dav::conn prop_req]]
+ return [list 207 $response]
+}
+
+ad_proc oacs_dav::impl::content_folder::lock {} {
+ LOCK DAV method for generic content folder
+} {
+ set uri [oacs_dav::conn uri]
+ set owner [oacs_dav::conn lock_owner]
+ set scope [oacs_dav::conn lock_scope]
+ set type [oacs_dav::conn lock_type]
+
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ set ret_code 423
+
+ set response [list $ret_code]
+ } else {
+ set depth [tdav::conn depth]
+ set token [tdav::set_lock $uri $depth $type $scope $owner]
+ set ret_code 200
+ set response [list $ret_code [list depth $depth token $token timeout "" owner $owner scope $scope type $type]]
+ }
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_folder::unlock {} {
+ UNLOCK DAV method for generic content folder
+} {
+ set uri [oacs_dav::conn uri]
+
+ if {![string equal unlocked [tdav::check_lock_for_unlock $uri]]} {
+ set ret_code 423
+ set body "Resource is locked."
+ } else {
+ ns_log notice "tdav::check_lock_for_unlock = [tdav::check_lock_for_unlock $uri]]"
+ tdav::remove_lock $uri
+ set ret_code 204
+ set body ""
+ }
+
+ return [list $ret_code $body]
+}
+
+namespace eval oacs_dav::impl::content_revision {}
+
+ad_proc oacs_dav::impl::content_revision::get {} {
+ GET DAV method for generic content revision
+ @author Dave Bauer
+ @param uri
+} {
+
+ set item_id [oacs_dav::conn item_id]
+
+ #should return the DAV content for the content item
+ #for now we always get live/latest revision
+
+ cr_write_content -item_id $item_id
+}
+
+ad_proc oacs_dav::impl::content_revision::put {} {
+ PUT DAV method for generic content revision
+ @author Dave Bauer
+} {
+ set user_id [oacs_dav::conn user_id]
+ set item_id [oacs_dav::conn item_id]
+ set root_folder_id [oacs_dav::conn folder_id]
+ set uri [oacs_dav::conn uri]
+
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ return [list 423]
+ }
+
+ set tmp_filename [oacs_dav::conn tmpfile]
+ set tmp_size [file size $tmp_filename]
+ # authenticate that user has write privilege
+
+ # we need to calculate parent_id from the URI
+ # it might not be the root DAV folder for the package
+ # check for folder or not
+ set urlv [split [oacs_dav::conn uri] "/"]
+
+ set name [oacs_dav::conn item_name]
+ set parent_id [oacs_dav::item_parent_folder_id $uri]
+ if {[empty_string_p $parent_id]} {
+ set response [list 409]
+ return $response
+ }
+
+ ns_log debug "oacs_dav::impl::content_revision::put parent_id=$parent_id item_id=:item_id root_folder_id=:root_folder_id name=$name"
+
+ # create new item if necessary
+ db_transaction {
+ set mime_type [cr_filename_to_mime_type $name]
+ if {[empty_string_p $item_id]} {
+ # this won't really work very nicely if we support
+ # abstract url type names... maybe chop off the extension
+ # when we name the object?
+
+ set revision_id [cr_import_content \
+ -storage_type file \
+ $parent_id \
+ $tmp_filename \
+ $tmp_size \
+ $mime_type \
+ $name]
+ } else {
+ set revision_id [cr_import_content \
+ -item_id $item_id \
+ -storage_type file \
+ $parent_id \
+ $tmp_size \
+ $tmp_filename \
+ $mime_type \
+ $name]
+ }
+ db_dml set_live_revision ""
+
+ set response [list 201]
+ } on_error {
+ set response [list 500]
+ }
+
+ # at least we need to return the http_status
+ return $response
+
+}
+
+ad_proc oacs_dav::impl::content_revision::propfind {} {
+ PROPFIND DAV method for generic content revision
+ @author Dave Bauer
+} {
+ set user_id [oacs_dav::conn user_id]
+ set item_id [oacs_dav::conn item_id]
+ set folder_id [oacs_dav::conn folder_id]
+ set uri [oacs_dav::conn uri]
+
+ set depth [oacs_dav::conn depth]
+ set prop_req [oacs_dav::conn prop_req]
+ # find the values
+ db_1row get_properties ""
+ set etag "1f9a-400-3948d0f5"
+ set properties [list]
+ # is "D" the namespace??
+ lappend properties [list "D" "getcontentlength"] $content_length
+# lappend properties [list "D" "uri"] $item_uri
+ lappend properties [list "D" "getcontenttype"] $mime_type
+ # where do we get an etag from?
+ lappend properties [list "D" "getetag"] $etag
+ lappend properties [list "D" "getlastmodified"] $last_modified
+ lappend properties [list "D" "creationdate"] $creation_date
+ lappend properties [list "D" "resourcetype"] ""
+
+ foreach i [tdav::get_user_props ${uri} $depth $prop_req] {
+ lappend properties $i
+ }
+
+ set response [list 207 [list [list $uri "" $properties]]]
+
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_revision::proppatch {} {
+ PROPPATCH DAV method for generic content revision
+ We store all user properties in the filesystem using tDAV for now
+ So this is just a stub until we can get everything stored in the
+ database.
+ @author Dave Bauer
+} {
+ # get the properties out of the list
+ set uri [oacs_dav::conn uri]
+
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ return [list 423]
+ }
+
+ # set the values
+ set response [tdav::update_user_props $uri [oacs_dav::conn prop_req]]
+ # return results
+ return [list 207 $response]
+}
+
+ad_proc oacs_dav::impl::content_revision::delete {} {
+ DELETE DAV method for generic content revision
+ @author Dave Bauer
+} {
+ set package_id [oacs_dav::conn package_id]
+ set user_id [oacs_dav::conn user_id]
+ set peer_addr [oacs_dav::conn peeraddr]
+ set item_id [oacs_dav::conn item_id]
+ set uri [oacs_dav::conn uri]
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ return [list 423]
+ }
+ if {[catch {db_exec_plsql delete_item ""} errmsg]} {
+ set response [list 500]
+ } else {
+ set response [list 204]
+ tdav::delete_props $uri
+ tdav::remove_lock $uri
+ }
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_revision::copy {} {
+ COPY DAV method for generic content revision
+ @author Dave Bauer
+} {
+ set package_id [oacs_dav::conn package_id]
+ set user_id [oacs_dav::conn user_id]
+ set peer_addr [oacs_dav::conn peeraddr]
+ set uri [oacs_dav::conn uri]
+ # check for write permission on target folder
+ set target_uri [oacs_dav::conn destination]
+ set copy_item_id [oacs_dav::conn item_id]
+ set overwrite [oacs_dav::conn overwrite]
+ set turlv [split $target_uri "/"]
+ set new_name [lindex $turlv end]
+ set new_parent_folder_id [oacs_dav::conn dest_parent_id]
+ if {[empty_string_p $new_parent_folder_id]} {
+ return [list 409]
+ }
+ set dest_item_id [db_string get_dest_id ""]
+ if {![empty_string_p $dest_item_id]} {
+
+ if {![string equal -nocase $overwrite "T"]} {
+ return [list 412]
+ } elseif {![permission::permission_p \
+ -object_id $dest_item_id \
+ -party_id $user_id \
+ -privilege "write"]} {
+ ns_returnunauthorized
+ }
+ # according to the spec copy with overwrite means
+ # delete then copy
+ ns_log notice "oacs_dav::revision::copy checking for lock on target"
+ if {![string equal "unlocked" [tdav::check_lock $target_uri]]} {
+ return [list 423]
+ }
+
+ db_exec_plsql delete_for_copy ""
+ set response [list 204]
+ } else {
+ set response [list 201]
+ }
+
+ db_transaction {
+ set item_id [db_exec_plsql copy_item ""]
+ db_dml set_live_revision ""
+ } on_error {
+ return [list 500]
+ }
+ tdav::copy_props $uri $target_uri
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_revision::move {} {
+ MOVE DAV method for generic content revision
+ @author Dave Bauer
+} {
+
+ set package_id [oacs_dav::conn package_id]
+ set user_id [oacs_dav::conn user_id]
+ set peer_addr [oacs_dav::conn peeraddr]
+ set item_id [oacs_dav::conn item_id]
+ set item_name [oacs_dav::conn item_name]
+ set uri [tdav::conn url]
+ set target_uri [oacs_dav::conn destination]
+ set cur_parent_folder_id [oacs_dav::conn folder_id]
+ set new_parent_folder_id [oacs_dav::conn dest_parent_id]
+ set turlv [split $target_uri "/"]
+ set new_name [lindex $turlv end]
+ set overwrite [oacs_dav::conn overwrite]
+ if {[empty_string_p $new_parent_folder_id]} {
+ return [list 409]
+ }
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ return [list 423]
+ }
+ set dest_item_id [db_string get_dest_id ""]
+ if {![empty_string_p $dest_item_id]} {
+
+ if {![string equal -nocase $overwrite "T"]} {
+ return [list 412]
+ } elseif {![permission::permission_p \
+ -object_id $dest_item_id \
+ -party_id $user_id \
+ -privilege "write"]} {
+ return [list 401]
+ }
+ if {![string equal "unlocked" [tdav::check_lock $target_uri]]} {
+ return [list 423]
+ }
+
+ db_exec_plsql delete_for_move ""
+ set response [list 204]
+ } else {
+ set response [list 201]
+ }
+
+ db_transaction {
+ if {![string equal $cur_parent_folder_id $new_parent_folder_id]} {
+ db_exec_plsql move_item ""
+ } elseif {![empty_string_p $new_name] } {
+ db_exec_plsql rename_item ""
+ }
+ } on_error {
+ return [list 500]
+ }
+ tdav::copy_props $uri $target_uri
+ tdav::delete_props $uri
+ tdav::remove_lock $uri
+ return $response
+}
+
+
+ad_proc oacs_dav::impl::content_revision::mkcol {} {
+ MKCOL DAV method for generic content revision
+ @author Dave Bauer
+} {
+ # not allowed to create a collection inside a resource
+ # return some sort of error
+ set response [list 405]
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_revision::lock {} {
+ LOCK DAV method for generic content revision
+} {
+ set uri [oacs_dav::conn uri]
+ set owner [oacs_dav::conn lock_owner]
+ set scope [oacs_dav::conn lock_scope]
+ set type [oacs_dav::conn lock_type]
+
+ if {![string equal "unlocked" [tdav::check_lock $uri]]} {
+ set ret_code 423
+
+ set response [list $ret_code]
+ } else {
+ set depth [tdav::conn depth]
+ set token [tdav::set_lock $uri $depth $type $scope $owner]
+ set ret_code 200
+ set response [list $ret_code [list depth $depth token $token timeout "" owner $owner scope $scope type $type]]
+ }
+ return $response
+}
+
+ad_proc oacs_dav::impl::content_revision::unlock {} {
+ UNLOCK DAV method for generic content revision
+} {
+ set uri [oacs_dav::conn uri]
+
+ if {![string equal unlocked [tdav::check_lock_for_unlock $uri]]} {
+ set ret_code 423
+ set body "Resource is locked."
+ } else {
+ ns_log notice "tdav::check_lock_for_unlock = [tdav::check_lock_for_unlock $uri]]"
+ tdav::remove_lock $uri
+ set ret_code 204
+ set body ""
+ }
+
+ return [list $ret_code $body]
+}
Index: openacs-4/packages/oacs-dav/tcl/oacs-dav-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/oacs-dav-procs.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/oacs-dav-procs.xql 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,57 @@
+
+
+
+
+ insert into dav_site_node_folder_map
+ (folder_id, node_id, enabled_p)
+ values
+ (:folder_id, :node_id, :enabled_p)
+
+
+
+
+
+ delete from dav_site_node_folder_map
+ where folder_id=:folder_id
+ and node_id=:node_id
+
+
+
+
+
+ select folder_id from dav_site_node_folder_map
+ where node_id=:node_id and enabled_p = 't'
+
+
+
+
+
+ select content_type from cr_items where item_id=:item_id
+
+
+
+
+
+ update cr_items set live_revision=:revision_id
+ where item_id=(select item_id from cr_revisions
+ where revision_id=:revision_id)
+
+
+
+
+
+ select count(*) from dav_site_node_folder_map
+ where folder_id=:move_folder_id
+
+
+
+
+
+ update cr_items set live_revision=latest_revision
+ where item_id=:item_id
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/test.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/test.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/test.html 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1 @@
+TEST
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/test1.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/test1.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/test1.html 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1 @@
+TEST
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/test/__test_file.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/test/__test_file.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/test/__test_file.html 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,8 @@
+
+
+ Test Dav File
+
+
+ This is the test of OpenACS WebDAV support.
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs-postgresql.xql 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ postgresql7.1
+
+
+
+ select content_folder__new (
+ '__test_folder',
+ '__test_folder',
+ NULL,
+ NULL
+ )
+
+
+
+
+ select
+ content_folder__register_content_type(:folder_id,'content_revision','t')
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs.tcl 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,106 @@
+#
+
+ad_library {
+
+ Test procedures for oacs-dav
+
+ @author Dave Bauer (dave@thedesignexperience.org)
+ @creation-date 2003-09-14
+ @cvs-id $Id: oacs-dav-procs.tcl,v 1.1 2004/02/16 16:49:28 daveb Exp $
+
+}
+
+aa_register_case oacs_dav_sc_create {
+ test creation of DAV service contract
+} {
+ aa_run_with_teardown \
+ -rollback \
+ -test_code {
+
+ aa_true "DAV Service contract created" [expr [db_0or1row get_dav_sc ""]]
+ set sc_ops [db_list get_dav_ops ""]
+ set valid_ops [list get put mkcol copy propfind proppatch move delete]
+ foreach op_name $valid_ops {
+ aa_true "$op_name operation created" [expr [lsearch $sc_ops $op_name] > -1]
+ }
+
+ aa_true "DAV put_type Service contract created" [expr [db_0or1row get_dav_pt_sc ""]]
+ aa_true "get_type operation created" [expr [db_0or1row get_dav_pt_op ""]]
+ }
+}
+
+aa_register_case oacs_dav_put {
+ test generic cr_revision PUT
+} {
+ aa_run_with_teardown \
+ -rollback \
+ -test_code {
+ array set sn [site_node::get -url "/"]
+ set package_id $sn(package_id)
+ set name "__test_file.html"
+ oacs_dav::conn -set item_name $name
+ set uri "/${name}"
+ set item_id ""
+ oacs_dav::conn -set method "PUT"
+ oacs_dav::conn -set item_id $item_id
+ oacs_dav::conn -set url $uri
+ oacs_dav::conn -set urlv $name
+ oacs_dav::conn -set tmpfile "[acs_root_dir]/packages/oacs-dav/tcl/test/$name"
+ # we probably want to create a bunch of files in the filesystem
+ # and test mime type and other attributes to make sure the
+ # content gets in the database
+ set fd [open [oacs_dav::conn tmpfile] r]
+ set orig_content [read $fd]
+ close $fd
+ set folder_id [db_exec_plsql create_test_folder ""]
+ aa_log "Folder Created $folder_id package_id $package_id"
+ oacs_dav::conn -set folder_id $folder_id
+ db_exec_plsql register_content_type ""
+ oacs_dav::register_folder $folder_id $sn(node_id)
+ set response [oacs_dav::impl::content_revision::put]
+ aa_log "Response was $response"
+ set new_item_id [db_string item_exists "" -default ""]
+ aa_log "Item_id=$new_item_id"
+ aa_true "Content Item Created" [expr ![empty_string_p $new_item_id]]
+ set revision_id [db_string revision_exists "" -default ""]
+ aa_trute "Content Revision Created" [expr ![empty_string_p $revision_id]]
+ set cr_filename "[cr_fs_path]/[db_string get_content_filename ""]"
+ aa_true "Content Attribute Set" [string equal [file size [oacs_dav::conn tmpfile]] [file size $cr_filename]]
+
+ }
+
+}
+
+aa_register_case oacs_dav_mkcol {
+ test generic content folder creation
+} {
+ aa_run_with_teardown \
+ -rollback \
+ -test_code {
+ array set sn [site_node::get -url "/"]
+ set package_id $sn(package_id)
+ set name "__test_folder1/__test_folder2"
+ set uri "/"
+ oacs_dav::conn -set item_id ""
+ oacs_dav::conn -set url $uri
+ oacs_dav::conn -set extra_url $name
+ oacs_dav::conn -set urlv [split $uri "/"]
+ oacs_dav::conn -set package_id $package_id
+ set parent_folder_id [db_string get_parent_folder "" -default "-100"]
+ oacs_dav::conn -set folder_id $parent_folder_id
+ oacs_dav::register_folder $parent_folder_id $sn(node_id)
+ foreach fname [split $name "/"] {
+ set uri "$uri${fname}/"
+ oacs_dav::conn -set item_name $fname
+ oacs_dav::conn -set url $uri
+ oacs_dav::conn -set extra_url $fname
+ oacs_dav::conn -set urlv [split $uri "/"]
+ aa_log "name $fname uri $uri"
+ set response [oacs_dav::impl::content_folder::mkcol]
+ set new_folder_id [db_string folder_exists "" -default ""]
+ aa_true "Content Folder $fname created" [expr ![empty_string_p $new_folder_id]]
+ }
+
+ }
+
+}
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/tcl/test/oacs-dav-procs.xql 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+ select * from acs_sc_contracts where contract_name='dav'
+
+
+
+
+
+ select * from acs_sc_contracts where contract_name='dav_put_type'
+
+
+
+
+
+
+ select operation_name from acs_sc_operations where contract_name='dav'
+
+
+
+
+
+ select operation_name from acs_sc_operations where
+ contract_name='dav_put_type'
+ and operation_name='get_type'
+
+
+
+
+
+ select item_id from cr_items where name=:name
+ and parent_id=:folder_id
+
+
+
+
+
+ select revision_id from cr_revisions
+ where item_id=:new_item_id
+
+
+
+
+
+ select content from cr_revisions where revision_id=:revision_id
+
+
+
+
+
+ select item_id from cr_items where name=:name
+ and parent_id=:folder_id
+
+
+
+
+
+ select folder_id from cr_folders where package_id=:package_id
+
+
+
+
+
+ select item_id
+ from cr_items
+ where name=:fname
+ and content_type='content_folder'
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/index.vuh
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/index.vuh,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/index.vuh 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,9 @@
+#
+#
+# Redirect to administration
+#
+# @author Dave Bauer (dave@thedesignexperience.org)
+# @creation-date 2004-02-16
+# @cvs-id $Id: index.vuh,v 1.1 2004/02/16 16:49:28 daveb Exp $
+
+ad_returnredirect "admin/"
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/admin/disable.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/admin/disable.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/admin/disable.tcl 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,28 @@
+#
+
+ad_page_contract {
+
+ WebDAV disable folders
+
+ @author Dave Bauer (dave@thedesignexperience.org)
+ @creation-date 2004-02-15
+ @cvs-id $Id: disable.tcl,v 1.1 2004/02/16 16:49:28 daveb Exp $
+} {
+ folder_id:integer,multiple
+} -properties {
+} -validate {
+} -errors {
+}
+
+permission::require_permission \
+ -party_id [ad_conn user_id] \
+ -object_id [ad_conn package_id ] \
+ -privilege "admin"
+
+foreach id $folder_id {
+
+ db_dml disable_folder ""
+
+}
+util_user_message -message [_ oacs-dav.Folders_Disabled]
+ad_returnredirect "."
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/admin/disable.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/admin/disable.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/admin/disable.xql 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+ update dav_site_node_folder_map
+ set enabled_p = 'f'
+ where folder_id=:id
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/admin/enable.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/admin/enable.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/admin/enable.tcl 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,28 @@
+#
+
+ad_page_contract {
+
+ WebDAV enable folders
+
+ @author Dave Bauer (dave@thedesignexperience.org)
+ @creation-date 2004-02-15
+ @cvs-id $Id: enable.tcl,v 1.1 2004/02/16 16:49:28 daveb Exp $
+} {
+ folder_id:integer,multiple
+} -properties {
+} -validate {
+} -errors {
+}
+
+permission::require_permission \
+ -party_id [ad_conn user_id] \
+ -object_id [ad_conn package_id ] \
+ -privilege "admin"
+
+foreach id $folder_id {
+
+ db_dml enable_folder ""
+
+}
+util_user_message -message [_ oacs-dav.Folders_Enabled]
+ad_returnredirect "."
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/admin/enable.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/admin/enable.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/admin/enable.xql 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+ update dav_site_node_folder_map
+ set enabled_p = 't'
+ where folder_id=:id
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/admin/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/admin/index.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/admin/index.adp 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,5 @@
+
+ @title@
+ @context@
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/admin/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/admin/index.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/admin/index.tcl 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,47 @@
+# packages/oacs-dav/www/admin/index.tcl
+
+ad_page_contract {
+
+ Administer webdav enabled folders
+
+ @author Dave Bauer (dave@thedesignexperience.org)
+ @creation-date 2004-02-15
+ @cvs-id $Id: index.tcl,v 1.1 2004/02/16 16:49:28 daveb Exp $
+} {
+
+} -properties {
+ title
+ context
+} -validate {
+} -errors {
+}
+
+permission::require_permission \
+ -party_id [ad_conn user_id] \
+ -object_id [ad_conn package_id ] \
+ -privilege "admin"
+set bulk_actions [list "[_ oacs-dav.Enable]" "enable" "[_ oacs-dav.Enable_Folders]" "[_ oacs-dav.Disable]" "disable" "[_ oacs-dav.Disable_Folders]" ]
+template::list::create \
+ -name folders \
+ -multirow folders \
+ -key folder_id \
+ -bulk_actions $bulk_actions \
+ -elements {
+ package_key {label {[_ oacs-dav.Package_Type]}}
+ package_name { label {[_ oacs-dav.Package_Name]} }
+ label { label {[_ oacs-dav.Folder_Name]} }
+ folder_url { label {[_ oacs-dav.Folder_URL]} }
+ status { label {[_ oacs-dav.Status]} }
+ }
+
+db_multirow -extend {folder_url package_key package_name status} folders get_folders {} {
+ array set sn [site_node::get -node_id $node_id]
+ set folder_url $sn(url)
+ set package_key $sn(package_key)
+ set package_name $sn(instance_name)
+ set status [string map -nocase [list t [_ oacs-dav.Enabled] f [_ oacs-dav.Disabled] ] $enabled_p]
+}
+
+set title [_ oacs-dav.WebDAV_Folder_Administration]
+set context $title
+ad_return_template
Index: openacs-4/packages/oacs-dav/www/admin/index.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/admin/index.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/admin/index.xql 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+ select cf.folder_id,
+ cf.label,
+ sn.node_id,
+ sn.enabled_p
+ from cr_folders cf,
+ dav_site_node_folder_map sn
+ where cf.folder_id=sn.folder_id
+
+
+
+
\ No newline at end of file
Index: openacs-4/packages/oacs-dav/www/doc/index.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/oacs-dav/www/doc/index.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/oacs-dav/www/doc/index.html 16 Feb 2004 16:49:28 -0000 1.1
@@ -0,0 +1,73 @@
+
+
+ OpenACS WebDAV Support
+
+
+
+ OpenACS WebDAV Support
+ Introduction
+ This package implements a WebDAV interface to the OpenACS
+ Content Repository. In addition to generic access to content
+ items, there is a service-contract interface so packages can
+ define custom handlers for WebDAV methods for objects that belong
+ to that package.
+
+ How it Works
+ OpenACS WebDAV Support requires the tDAV AOLserver module to
+ implement most of the WebDAV protocol. OpenACS WebDAV Support just
+ provides and interface between tDAV and the Content Repository
+
+ Each content_type that requires a custom handler much implement
+ the dav service contract. Each content type should
+ implement the dav service contract with the implementation name the same as the content_type. This includes operations
+ for every WebDAV method. Some operations do not make sense for
+ certian object types. Specifically, content_items, which are
+ mapped to WebDAV resources, should not perform a MKCOL (make
+ collection) method. Likewise, a content_folder, or WebDAV
+ collection, should not allow a PUT method. In addition to the
+ dav service contract is a helper contract to allow
+ packages to set the initial content_type for new items created
+ through WebDAV. Each package should implement the
+ dav_put_type service contract with the implementation
+ named the same as the package key.
+ Each package instance that will allow WebDAV access should
+ register a package_id and folder_id for the root content_folder
+ that corresponds with the URI of the package's mount point using oacs_dav::register_folder.
+
+ Dispatching Requests
+ A preauth filter is registered for all WebDAV methods. This
+ calls oacs_dav::authorize which will set oacs_dav::conn user_id to
+ the OpenACS user_id or 0 is the request is not authenticated. This
+ filter also calls oacs_dav::setup_conn sets up the basic
+ information needed to authorize the request. If authorization
+ fails a 401 HTTP response is returned requesting authentication
+ information. If authorization is successful the filter returns
+ filter_ok and the tdav::filter* filter for the method is called.
+ The tdav::filter* commands setup global information for each
+ method that is independent of the storage type. After this filter
+ runs, the request is handled by the registered procedure for
+ OpenACS oacs_dav::handle_request.
+ oacs_dav::handle_request determines the package_id that should
+ handle the URI. This is based on the standard OpenACS site_node
+ Tcl API. After the package is found, the root folder for that
+ package is retreived from the dav_package_folder_map table. Using
+ the folder_id, and the URI of the request, the
+ content_item__get_id pl/sql(plpgsql) procedure is
+ called to find the item_id for the request. If no item_id is found
+ and the requested method is PUT, a new item should be created. If
+ the method is not PUT, a 404 error should be returned.
+
+
+ oacs_dav::handle_request will call the service contract
+implemenation for the content_type of the item. If the request is a
+PUT, first the dav_put_type service contract for the package_key of
+the request is called. For file-storage this returns
+"file_storage_object" so items created by PUT are created as
+file_storage_objects instead of generic content_revisions.
+
+The service contract implementation for each operation must return
+the response data in the format required by tDAV. The documentation
+for the tdav::respond::* procedures named for each method describe
+what is required.
+
+