Search code examples
perlfastcgi

CGI::Fast without tempfiles for upload


I wish to upload some relatively sensitive data to a server which should not be stored on disk in plaintext - I see it as far too easy to intercept a temporary file and copy the contents, plus there would be the issues of securely deleting the file against restores/journal entries, etc. I realise I could theoretically do this client-side, but prefer a server-side solution so an unusual browser does not mangle the upload.

Perl CGI::upload_hook() seemed like a perfect solution, with encryption being applied on arrival. Plain CGI is deprecated, but using CGI::Fast, the hook code is never reached, whether I put the call inside or outside the loop.

use Sys::Syslog;
use CGI::Fast;
sub hook {
    my ( $filename, $buffer, $bytes_read, $data ) = @_;
    syslog('notice',"Hook used!");
}

#CGI::upload_hook(\&hook,'',0); # No good here either
while (my $q = CGI::Fast->new()) {
    CGI::upload_hook(\&hook,'data',0); # No effect
    syslog('notice',"Got a request!");    
    # (Access control code cut)
    print $q->header('text/plain','200 OK');
    print (Dumper($q));
}

hook() is never called. CGI::Fast->new() does not accept such hook code in the way that CGI->new() does.


Solution

  • Once the CGI object is created, it's too late to set the hook. You can use the following:

    while (1) {
        my $q = CGI::Fast->new(\&hook, 'data', 0)
           or die("Couldn't Accept FCGI request\n");
    
        syslog('notice',"Got a request!");
        # (Access control code cut)
        print $q->header('text/plain','200 OK');
    }
    

    Note that this requires CGI::Fast version 2.15 or newer. Earlier versions of CGI::Fast interpreted the upload hook as an initializer and would skip accepting a request.