Index: openacs-4/packages/file-storage/www/folder-zip-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/www/folder-zip-add.tcl,v diff -u -r1.13 -r1.14 --- openacs-4/packages/file-storage/www/folder-zip-add.tcl 5 Feb 2019 16:55:40 -0000 1.13 +++ openacs-4/packages/file-storage/www/folder-zip-add.tcl 6 Feb 2019 19:36:00 -0000 1.14 @@ -1,36 +1,49 @@ ad_page_contract { - page to add a new file to the system + Page to upload and decompress a zip file into the file storage. + @author Kevin Scaldeferri (kevin@arsdigita.com) @creation-date 6 Nov 2000 @cvs-id $Id$ + } { + file_id:naturalnum,optional,notnull - folder_id:naturalnum,optional,notnull + {folder_id:naturalnum,notnull ""} upload_file:trim,optional,notnull - return_url:localurl,optional + {return_url:localurl ""} upload_file.tmpfile:tmpfile,optional {title ""} {lock_title_p:boolean 0} } -properties { + folder_id:onevalue context:onevalue title:onevalue lock_title_p:onevalue + } -validate { + file_id_or_folder_id { - if {[info exists file_id] && $file_id ne "" - && (![info exists folder_id] || $folder_id eq "")} { + # + # Get parent folder_id from file_id, if such exists and folder_id is + # empty, and complain if the resultant folder is not valid. + # + if {[info exists file_id] && $file_id ne "" && $folder_id eq ""} { set folder_id [db_string get_folder_id { select parent_id as folder_id from cr_items where item_id=:file_id } -default ""] } - if {![info exists folder_id] || ![fs_folder_p $folder_id]} { + if {$folder_id eq "" || ![fs_folder_p $folder_id]} { ad_complain "The specified parent folder is not valid." } } + max_size -requires {upload_file} { + # + # Check if the file is larger than fs::max_upload_size. + # set n_bytes [file size ${upload_file.tmpfile}] set max_bytes [fs::max_upload_size] if { $n_bytes > $max_bytes } { @@ -39,37 +52,44 @@ } } -set user_id [ad_conn user_id] -set package_id [ad_conn package_id] -# check for write permission on the folder or item +set user_id [ad_conn user_id] +set package_id [ad_conn package_id] +set creation_ip [ad_conn peeraddr] +# Check for write permission on the folder. permission::require_permission \ -object_id $folder_id \ -party_id $user_id \ -privilege "write" if {![ad_form_new_p -key file_id]} { + # + # Check for write permission on the file if we are editing existing data, + # adding a file revision in this case, and set the context bar accordingly. + # permission::require_permission \ -object_id $file_id \ -party_id $user_id \ -privilege "write" set context [fs_context_bar_list -final "[_ file-storage.Add_Revision]" $folder_id] - } else { set context [fs_context_bar_list -final "[_ file-storage.Add_File]" $folder_id] } +# Add file_id and upload_file to the form. ad_form -name file_add -html { enctype multipart/form-data } -export { folder_id lock_title_p } -form { file_id:key {upload_file:file {label \#file-storage.Upload_a_file\#} {html "size 30"}} } -if {[info exists return_url] && $return_url ne ""} { +# Add return_url to the form if is not empty. +if {$return_url ne ""} { ad_form -extend -name file_add -form { {return_url:text(hidden) {value $return_url}} } } +# 'Lock' title if lock_title_p. if {$lock_title_p} { ad_form -extend -name file_add -form { {title:text(hidden) {value $title}} @@ -80,78 +100,96 @@ } } +# Add an explanation about the purpose of the form. if {[ad_form_new_p -key file_id]} { ad_form -extend -name file_add -form { {unpack_message:text(inform) {label "[_ file-storage.Important]"} {value "[_ file-storage.Use_this_form_to_upload_a_ZIP]"}} } } +# Rest of the form. ad_form -extend -name file_add -form {} -new_data { - - # create a new folder to hold the zip contents - # TODO make sure its name is unique? - + # + # new_data block, which unzips the file and uploads its contents to the file + # storage, creating the necessary folders. + # + # Start defining the title if it does not exist already. + # if {$title eq ""} { set title [file rootname [list [template::util::file::get_property filename $upload_file]]] } + + # + # Create a new folder to hold the zip contents, if it does not exist already. + # set parent_folder_id $folder_id - set folder_id [content::item::get_id_by_name -name $title -parent_id $folder_id] + set folder_id [content::item::get_id_by_name -name $title -parent_id $parent_folder_id] if {$folder_id eq ""} { set folder_id [content::folder::new -name $title -parent_id $parent_folder_id -label $title] } + # + # Uncompress the file. + # set unzip_binary [string trim [parameter::get -parameter UnzipBinary]] - if { $unzip_binary ne "" } { - + # + # Create temp directory to unzip. + # set unzip_path [ad_tmpnam] file mkdir $unzip_path - # save paths! get rid of -j switch --DAVEB 20050628 - catch { exec $unzip_binary -d $unzip_path ${upload_file.tmpfile} } errmsg + # + # Unzip. + # # More flexible parameter design could be: # zip {unzip -jd {out_path} {in_file}} tar {tar xf {in_file} {out_path}} tgz {tar xzf {in_file} {out_path}} + # + # save paths! get rid of -j switch --DAVEB 20050628 + # + catch { exec $unzip_binary -d $unzip_path ${upload_file.tmpfile} } errmsg + # + # Get two lists of the files to upload, with and without their full path. + # set upload_files [list] set upload_tmpfiles [list] - foreach file [ad_find_all_files "$unzip_path"] { lappend upload_files [regsub "^$unzip_path\/" $file {}] lappend upload_tmpfiles $file } - } else { - set upload_files [list [template::util::file::get_property filename $upload_file]] + # + # No unzip available, just upload the whole zip file. + # + set upload_files [list [template::util::file::get_property filename $upload_file]] set upload_tmpfiles [list [template::util::file::get_property tmp_filename $upload_file]] } + set number_upload_files [llength $upload_files] - if { [lindex $upload_files 0] eq ""} { + # + # Something is quite broken if there are no files to upload. + # + if {$number_upload_files == 0} { ad_return_complaint 1 "
  • You have to upload a file" ad_script_abort } + # + # Upload the files. + # set i 0 - set number_upload_files [llength $upload_files] - set unzip_path_list_len [llength [file split $unzip_path]] - foreach upload_file $upload_files tmpfile $upload_tmpfiles { + # + # Upload a file. + # set this_file_id $file_id - set this_title $title - # upload a new file - # if the user choose upload from the folder view - # and the file with the same name already exists - # we create a new revision - - # check if this is in a folder inside the zip and create - # the folders if they don't exist set p_f_id $folder_id - set file_paths [file split [file dirname $tmpfile]] - - # remove unzip_path portion by selecting remaining part of list - set file_paths [lrange $file_paths $unzip_path_list_len end] - + set file_paths [file split [file dirname $upload_file]] if {"." ne $file_paths && [llength $file_paths] > 0} { - # make sure every folder exists + # + # Make sure every folder exists, or create it otherwise. + # set path "" foreach p $file_paths { append path /${p} @@ -164,79 +202,88 @@ } else { set p_f_id $paths($path) } - } set upload_file [file tail $upload_file] } - - set this_folder_id $p_f_id set this_title $upload_file + set this_folder_id $p_f_id + # + # If the user choose upload from the folder view, and a file with the + # same name already exists, we create a new revision. + # + # Check for permission in the existing file in order to do so. + # set existing_item_id [fs::get_item_id -name $upload_file -folder_id $this_folder_id] - if {$existing_item_id ne ""} { - # file with the same name already exists - # in this folder, create a new revision set this_file_id $existing_item_id permission::require_permission \ -object_id $this_file_id \ -party_id $user_id \ -privilege write } + # + # Add the file. + # set rev_id [fs::add_file \ -name $upload_file \ -item_id $this_file_id \ -parent_id $this_folder_id \ -tmp_filename $tmpfile \ -creation_user $user_id \ - -creation_ip [ad_conn peeraddr] \ + -creation_ip $creation_ip \ -title $this_title \ -package_id $package_id] - file delete -- $tmpfile + # + # Increment file_id to the next value of acs_object_id_seq. + # incr i - - if {$rev_id ne ""} { - set this_file_id [db_string get_item_id { - select item_id - from cr_revisions - where revision_id = :rev_id - } -default 0] - } - if {$i < $number_upload_files} { set file_id [db_nextval "acs_object_id_seq"] } + # + # Cleanup of the tmp file. + # + file delete -- $tmpfile } + + # + # Cleanup of zip file and tmp directory. + # + file delete -- $upload_file.tmpfile if {$unzip_path ne ""} { file delete -force -- $unzip_path } - file delete -- $upload_file.tmpfile + } -edit_data { + # + # edit_data block, which just adds a revision of a file. + # fs::add_version \ -name [template::util::file::get_property filename $upload_file] \ -tmp_filename [template::util::file::get_property tmp_filename $upload_file] \ -item_id $file_id \ -creation_user $user_id \ - -creation_ip [ad_conn peeraddr] \ + -creation_ip $creation_ip \ -title $title \ -package_id $package_id } -after_submit { - - if {[info exists return_url] && $return_url ne ""} { + # + # Code to be executed after new_data or edit_data, just redirecting to + # return_url. + # + if {$return_url ne ""} { ad_returnredirect $return_url } else { ad_returnredirect [export_vars -base ./ {folder_id}] } ad_script_abort - } -set unpack_available_p [expr {[string trim [parameter::get -parameter UnzipBinary]] ne ""}] - ad_return_template # Local variables: