Index: openacs-4/packages/proctoring-support/lib/proctoring-upload.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/proctoring-support/lib/Attic/proctoring-upload.tcl,v diff -u -N -r1.1.2.4 -r1.1.2.5 --- openacs-4/packages/proctoring-support/lib/proctoring-upload.tcl 1 Sep 2020 11:34:53 -0000 1.1.2.4 +++ openacs-4/packages/proctoring-support/lib/proctoring-upload.tcl 6 Apr 2021 14:10:55 -0000 1.1.2.5 @@ -53,8 +53,24 @@ ad_script_abort } +# A client-side timeout might still end up being processed by the +# server. Here we make sure we do not process pictures twice for a +# specific user. +if {[::proctoring::picture_already_received_p \ + -object_id $object_id \ + -user_id $user_id \ + -file ${file.tmpfile}]} { + # We do not tell anything to the client: for what they are + # concerned, file has been received and they should go on with + # their lives. + ns_log warning "Proctoring: user $user_id tried to upload content twice, skipping silently..." + ns_return 200 text/plain OK + ad_script_abort +} + set timestamp [clock seconds] set file_path $proctoring_dir/${name}-${type}-$timestamp.$extension + file mkdir -- $proctoring_dir file rename -force -- ${file.tmpfile} $file_path Index: openacs-4/packages/proctoring-support/tcl/proctoring-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/proctoring-support/tcl/Attic/proctoring-procs.tcl,v diff -u -N -r1.1.2.8 -r1.1.2.9 --- openacs-4/packages/proctoring-support/tcl/proctoring-procs.tcl 16 Mar 2021 17:11:22 -0000 1.1.2.8 +++ openacs-4/packages/proctoring-support/tcl/proctoring-procs.tcl 6 Apr 2021 14:10:55 -0000 1.1.2.9 @@ -180,3 +180,36 @@ and (end_time is null or end_time >= cast(current_timestamp as time)) }] } + +ad_proc -private ::proctoring::picture_already_received_p { + -object_id:required + -user_id:required + -file:required +} { + Returns if the picture is the same the users sent the last time + they uploaded a proctoring file. + + @param object_id id of the proctored object + @param user_id id of the proctored user + @param file an absolute path to a file in the filesystem + + @return boolean +} { + set cache_name proctoring_checksums_cache + + # Make sure the checksum of current file is not the same as the + # one we have in the cache. + set checksum [ns_md file -digest sha1 $file] + set already_received_p false + if {[ns_cache_get $cache_name ${object_id}_${user_id} cached_checksum]} { + if {$checksum eq $cached_checksum} { + set already_received_p true + } + } + + # Update in any case the cache to renew the expiration + ns_cache_eval -force -- $cache_name ${object_id}_${user_id} set v $checksum + + return $already_received_p +} + Index: openacs-4/packages/proctoring-support/tcl/proctoring-support-init.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/proctoring-support/tcl/Attic/proctoring-support-init.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/proctoring-support/tcl/proctoring-support-init.tcl 6 Apr 2021 14:10:56 -0000 1.1.2.1 @@ -0,0 +1,19 @@ +ad_library { + Startup script for proctoring-support +} + +# This cache will store the checksum of the last picture that has been +# received on behalf of a user while proctoring a specific object. +# This is needed to implement a server-side check that detects +# pictures being sent multiple times, e.g. when a request resulting in +# a client timeout still gets processed by the server. + +set cache_name proctoring_checksums_cache +set cache_size 1MB ; # ~ 25000 40bytes sha1 entries +set cache_timeout 1ms +set cache_expires [expr {2 * 60 * 60}] ; # 2 hours + +ns_cache_create \ + -timeout $cache_timeout \ + -expires $cache_expires -- $cache_name $cache_size +