1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#!/usr/bin/python
# IVLE - Informatics Virtual Learning Environment
# Copyright (C) 2007-2008 The University of Melbourne
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Author: Thomas Conway, Will Grant
import mimetypes
import os
import sys
import StringIO
import urlparse
from optparse import OptionParser
import cjson
from ivle import (cgirequest, studpath)
from ivle import zip as zipmod
def throw_error(message):
print cjson.encode({'error': message})
sys.exit(0)
parser = OptionParser()
parser.add_option('-d', '--download', dest='download', action='store_true',
help='force download, not execution, of the paths')
(options, args) = parser.parse_args()
# Detect download mode. Download mode zips any multiple selection,
# and does not execute CGI scripts.
if options.download:
download = True
dir = os.path.dirname(args[0])
# Mangle the paths - we want the basename of their dirname in front.
paths = []
for path in args:
assert os.path.dirname(path) == dir
paths.append(os.path.join(os.path.basename(dir),
os.path.basename(path)))
dir = os.path.dirname(dir)
else:
download = False
paths = args
default_mimetype = "application/octet-stream"
zip_mimetype = "application/zip"
zipmode = False
zipbasepath = None
zipfilename = None
# If multiple paths have been specified, zip them up.
if len(paths) > 1:
zipmode = True
zipbasepath = dir
zipfilename = os.path.basename(zipbasepath)
else:
filename = paths[0]
if not os.access(filename, os.R_OK):
throw_error('not-found')
# If it's a directory, serve as a zip file
if os.path.isdir(filename):
zipmode = True
# Zip it from the perspective of its own parent.
# That way it will be a directory in the top level of the zip
# file.
if filename[-1] == os.sep: filename = filename[:-1]
splitpath = filename.rsplit(os.sep, 1)
if len(splitpath) == 1:
zipbasepath = ''
paths = [filename]
else:
zipbasepath = splitpath[0]
paths = [splitpath[1]]
zipfilename = filename
if zipmode:
# zipfilename is some filename. Strip trailing slash or extension,
# and add ".zip".
if zipfilename == '':
zipfilename = "files"
elif zipfilename[-1] == '/':
zipfilename = zipfilename[:-1]
elif '.' in zipfilename:
zipfilename = zipfilename[:zipfilename.rindex('.')]
zipfilename += ".zip"
#req.headers_out["Content-Disposition"] = ("attachment; filename=" +
# zipfilename) # TODO
zipfile = StringIO.StringIO()
zipmod.make_zip(zipbasepath, paths, zipfile)
print cjson.encode({'content': zipfile.getvalue(), 'type': zip_mimetype})
else:
print cjson.encode({'content': open(filename).read()})
|