Index: openacs-4/packages/acs-templating/acs-templating.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/acs-templating.info,v
diff -u -r1.66.2.31 -r1.66.2.32
--- openacs-4/packages/acs-templating/acs-templating.info	14 Aug 2022 08:05:46 -0000	1.66.2.31
+++ openacs-4/packages/acs-templating/acs-templating.info	25 Aug 2022 11:34:50 -0000	1.66.2.32
@@ -9,7 +9,7 @@
     <implements-subsite-p>f</implements-subsite-p>
     <inherit-templates-p>t</inherit-templates-p>
 
-    <version name="5.10.1d13" url="http://openacs.org/repository/download/apm/acs-templating-5.10.1d13.apm">
+    <version name="5.10.1d14" url="http://openacs.org/repository/download/apm/acs-templating-5.10.1d14.apm">
         <owner url="http://openacs.org">OpenACS</owner>
         <summary>Templating library.</summary>
         <release-date>2021-09-15</release-date>
@@ -27,9 +27,9 @@
         <license>GPL version 2</license>
         <maturity>3</maturity>
 
-        <provides url="acs-templating" version="5.10.1d13"/>
+        <provides url="acs-templating" version="5.10.1d14"/>
         <requires url="acs-kernel" version="5.10.0"/>
-        <requires url="acs-tcl" version="5.10.0"/>
+        <requires url="acs-tcl" version="5.10.1d20"/>
 
         <callbacks>
             <callback type="before-upgrade"  proc="template::apm::before_upgrade"/>
Index: openacs-4/packages/acs-templating/catalog/acs-templating.en_US.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/catalog/acs-templating.en_US.ISO-8859-1.xml,v
diff -u -r1.25.2.10 -r1.25.2.11
--- openacs-4/packages/acs-templating/catalog/acs-templating.en_US.ISO-8859-1.xml	26 Jun 2022 11:06:13 -0000	1.25.2.10
+++ openacs-4/packages/acs-templating/catalog/acs-templating.en_US.ISO-8859-1.xml	25 Aug 2022 11:34:50 -0000	1.25.2.11
@@ -74,6 +74,7 @@
   <msg key="Invalid_email_format">Invalid email format</msg>
   <msg key="Invalid_enumeration">Invalid enumeration</msg>
   <msg key="Invalid_enumeration_duplicate_elements">Invalid enumeration. &#34;%value%&#34; does not contain unique values.</msg>
+  <msg key="Invalid_file">Invalid file</msg>
   <msg key="Invalid_filename">Invalid filename</msg>
   <msg key="Invalid_integer">Invalid integer</msg>
   <msg key="Invalid_item">Invalid item</msg>
Index: openacs-4/packages/acs-templating/tcl/file-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/file-procs.tcl,v
diff -u -r1.12.2.6 -r1.12.2.7
--- openacs-4/packages/acs-templating/tcl/file-procs.tcl	24 Aug 2022 08:58:59 -0000	1.12.2.6
+++ openacs-4/packages/acs-templating/tcl/file-procs.tcl	25 Aug 2022 11:34:50 -0000	1.12.2.7
@@ -25,63 +25,104 @@
     @return the list { file_name temp_file_name content_mime_type }.
 
 } {
+    #
+    # Check if these have already been converted, then return them as they are.
+    #
+    # This may happen, for instance, during the 'preview' action of a form.
+    #
     if { [ns_queryget $element_id.tmpfile] eq "" } {
-        #
-        # Ignore files when no tmpfiles are sent in the request: we
-        # can only trust tmpfiles generated by the server.
-        #
-        return [list]
-    } elseif {[ns_info name] eq "NaviServer"} {
-        #
-        # NaviServer
-        #
-        # Get the files information using 'ns_querygetall'
-        #
-        set filenames [ns_querygetall $element_id]
-        set tmpfiles  [ns_querygetall $element_id.tmpfile]
-        set types     [ns_querygetall $element_id.content-type]
+        set files [ns_querygetall $element_id]
     } else {
+        if {[ns_info name] eq "NaviServer"} {
+            #
+            # NaviServer
+            #
+            # Get the files information using 'ns_querygetall'
+            #
+            set filenames [ns_querygetall $element_id]
+            set tmpfiles  [ns_querygetall $element_id.tmpfile]
+            set types     [ns_querygetall $element_id.content-type]
+        } else {
+            #
+            # AOLserver
+            #
+            # ns_querygetall behaves differently in AOLserver, using the ns_queryget
+            # legacy version instead
+            #
+            set filenames [ns_queryget $element_id]
+            set tmpfiles  [ns_queryget $element_id.tmpfile]
+            set types     [ns_queryget $element_id.content-type]
+        }
         #
-        # AOLserver
+        # No files, get out
         #
-        # ns_querygetall behaves differently in AOLserver, using the ns_queryget
-        # legacy version instead
+        if {$filenames eq ""} {
+            return ""
+        }
         #
-        set filenames [ns_queryget $element_id]
-        set tmpfiles  [ns_queryget $element_id.tmpfile]
-        set types     [ns_queryget $element_id.content-type]
-    }
-
-    #
-    # Return the files info in a list per file
-    #
-    set files [list]
-    for {set file 0} {$file < [llength $filenames]} {incr file} {
-        set filename [lindex $filenames $file]
-        set tmpfile  [lindex $tmpfiles $file]
-        set type     [lindex $types $file]
+        # Return the files info in a list per file
         #
-        # Cleanup filenames
-        #
-        regsub -all -- {\\+} $filename {/} filename
-        regsub -all -- { +} $filename {_} filename
-        set filename [lindex [split $filename "/"] end]
-        #
-        # Append to the list of lists
-        #
-        lappend files [list $filename $tmpfile $type]
+        set files [list]
+        for {set file 0} {$file < [llength $filenames]} {incr file} {
+            set filename [lindex $filenames $file]
+            set tmpfile  [lindex $tmpfiles $file]
+            set type     [lindex $types $file]
+            #
+            # Cleanup filenames
+            #
+            regsub -all -- {\\+} $filename {/} filename
+            regsub -all -- { +} $filename {_} filename
+            set filename [lindex [split $filename "/"] end]
+            #
+            # Append to the list of lists
+            #
+            lappend files [list $filename $tmpfile $type]
+        }
     }
 
     return $files
 
 }
 
 ad_proc -public template::data::validate::file { value_ref message_ref } {
-    Our file widget can't fail 
+    Validate the values in the file widget. In particular:
+    - make sure values are a list of lists of 3 elements
+    - ensure character cleanup has been performed
+    - ensure tmpfiles are safe
 
-    @return true
+    @return boolean
 } {
-    return 1
+    upvar 2 $message_ref message $value_ref value element element
+
+    set result 1
+
+    if { ![::string is list $value] ||
+         [llength $value] != 3 ||
+         "" in $value
+     } {
+        #
+        # Value is not a list of 3 non-empty elements.
+        #
+        set result 0
+    } elseif { [regexp {(\\| )} [lindex $value 0]] } {
+        #
+        # Backslashes and spaces were supposedly cleaned up during
+        # file_transform.
+        #
+        set result 0
+    } elseif { ![security::safe_tmpfile_p [lindex $value 1]] } {
+        #
+        # The tmpfile is not safe
+        #
+        set result 0
+    }
+
+    if { !$result } {
+        set message [_ acs-templating.Invalid_file]
+        ad_log warning "They tried to sneak in invalid value '$value'"
+    }
+
+    return $result
 }
 
 ad_proc -public template::util::file::get_property {
Index: openacs-4/packages/acs-templating/tcl/test/data-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/test/data-procs.tcl,v
diff -u -r1.1.2.27 -r1.1.2.28
--- openacs-4/packages/acs-templating/tcl/test/data-procs.tcl	2 Sep 2021 16:40:51 -0000	1.1.2.27
+++ openacs-4/packages/acs-templating/tcl/test/data-procs.tcl	25 Aug 2022 11:34:50 -0000	1.1.2.28
@@ -306,13 +306,20 @@
     @author Héctor Romojaro <hector.romojaro@gmail.com>
     @creation-date 28 June 2021
 } {
-    #
-    # Currently, the file widget is assumed to never fail...
-    #
-    set file_true {my_file lalala}
+
+    set values {
+        my_file false
+        lalala false
+        {Afile /tmp/testfile text/plain} true
+        {A/file /tmp/testfile2 ""} false
+        {A/file /tmp/testfile2 a} true
+        {\\afile /tmp/testfile3 a} false
+        {afile /etc/passwd text/css} false
+    }
+
     set message ""
-    foreach value $file_true {
-        aa_true "Is $value a file?" \
+    foreach {value expected} $values {
+        aa_$expected "Is $value a file?" \
             [template::data::validate file value message]
     }
 }
Fisheye: Tag 1.1 refers to a dead (removed) revision in file `openacs-4/packages/acs-templating/tcl/test/file-procs.tcl'.
Fisheye: No comparison available.  Pass `N' to diff?