downloading cgi advice

Chris Liechti cliechti at gmx.net
Thu May 9 21:04:17 EDT 2002


Jeff Shipman <shippy at nmt.edu> wrote in news:3CDAFA76.9050508 at nmt.edu:

> I've got a cgi which handles downloading
> files to a person's computer. Files of
> type .tar.gz and .exe go through this CGI.
> These are some snippets I have from the
> program:
> 
>     # Determine size of file
>     try:
>        s = os.stat(BASEDIR+'/'+loc)

use os.path.join for a platform independant, secure join of paths.

depending of where you get "loc" from, this can be a security hole here.
you should make sure that you don't have any '..' in the string as 
otherwise one could access all files on the server.

one possibility is that you calculate the path using os.path.join and then
check it with os.path.commonprefix if its still in your BASEDIR. (assuming 
BASEDIR is an absolute path, call os.path.abspath on it otherwise)

>        size = int(s[6])
>     except OSError:
>        errmsg('Couldn\'t stat() file!')
>     except:
>        errmsg('Unexpected error while calling stat()!')
> 
> 
>     # Initiate download
>     logline = 'Host: %s - Initiating download for file %s of %d bytes.' \
>               % (gethost(), loc, size)
>     log(logline)
>     print 'Content-disposition: attachment; filename=%s\n'\
>           'Content-type: application/octet-stream\n'\
>           'Content-length: %d\n' % (loc, size)

you do have an empty line here to mark the end of headers. i just would 
spell it out more visible (you know when you later come back to the script 
and chage something...)

>     try:
>        file = open(BASEDIR+'/'+loc, 'rb')
>     except:
>        errmsg('Couldn\'t access download file!')

this message probaly gets a screwed look or gets downloaded because you've 
already sent the headers for the download but you probably won't get that 
message at all beacuse the stat above make sure that the file is there.  
(except an other proccess is writing to the file, which would cause an 
error)

>     sys.stdout.write(file.read(size))

this works of course, but it can get very resource intensive as you're 
loading the entire file into memory. you should consider reading in blocks  
and call sys.stdout.flush() often.

>     file.close()
> 
> This seems to work fine, but I'm just wanting
> to make sure that I'm not doing anything that
> could be wrong here.
> 
> Thanks in advance for any advice!

HTH
chris



-- 
Chris <cliechti at gmx.net>




More information about the Python-list mailing list