~azzar1/unity/add-show-desktop-key

1072 by matt.giuca
Renamed scripts to services.
1
#!/usr/bin/python
2
3
# IVLE - Informatics Virtual Learning Environment
4
# Copyright (C) 2007-2008 The University of Melbourne
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
20
# Author: Thomas Conway, Will Grant
1072 by matt.giuca
Renamed scripts to services.
21
22
import mimetypes
23
import os
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
24
import sys
1072 by matt.giuca
Renamed scripts to services.
25
import StringIO
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
26
from optparse import OptionParser
27
1801.1.1 by William Grant
Replace cjson with json, or simplejson if json is not available (Python <2.6)
28
try:
29
    import json
30
except ImportError:
31
    import simplejson as json
1072 by matt.giuca
Renamed scripts to services.
32
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
33
from ivle import zip as zipmod
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
34
import ivle.conf.app.server
1250 by William Grant
Unbreak serve - it was depending on the old names of a module.
35
import ivle.mimetypes
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
36
37
def determine_file_type(filename):
38
    filetype = mimetypes.guess_type(filename)[0]
39
    if filetype is None:
1791.2.4 by David Coles
Serve: Set Content-Length when serving files or zip archives
40
        filetype = ivle.mimetypes.DEFAULT_MIMETYPE
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
41
    return filetype
1072 by matt.giuca
Renamed scripts to services.
42
1099.3.5 by William Grant
Enable CGI path backtracking in serveservice.
43
def throw_error(message, extra={}):
44
    error = {'error': message}
45
    error.update(extra)
1801.1.1 by William Grant
Replace cjson with json, or simplejson if json is not available (Python <2.6)
46
    print json.dumps(error)
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
47
    sys.exit(0)
48
49
parser = OptionParser()
50
parser.add_option('-d', '--download', dest='download', action='store_true',
51
                  help='force download, not execution, of the paths')
52
(options, args) = parser.parse_args()
53
54
# Detect download mode. Download mode zips any multiple selection,
55
# and does not execute CGI scripts.
56
if options.download:
57
    download = True
1099.3.10 by William Grant
Convince serveservice not to mangle single paths when downloading.
58
    # paths is filled later.
59
else:
60
    download = False
61
    assert len(args) == 1
62
63
default_mimetype = "application/octet-stream"
64
zip_mimetype = "application/zip"
65
66
zipmode = False
67
zipbasepath = None
68
zipfilename = None
69
70
# If multiple paths have been specified, zip them up.
71
if len(args) > 1:
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
72
    # Mangle the paths - we want the basename of their dirname in front.
73
    paths = []
1099.3.12 by William Grant
Support downloading of a selection of files as a zip.
74
    dir = os.path.dirname(args[0])
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
75
    for path in args:
76
        assert os.path.dirname(path) == dir
77
        paths.append(os.path.join(os.path.basename(dir),
78
                                  os.path.basename(path)))
79
    dir = os.path.dirname(dir)
1072 by matt.giuca
Renamed scripts to services.
80
    zipmode = True
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
81
    zipbasepath = dir
1072 by matt.giuca
Renamed scripts to services.
82
    zipfilename = os.path.basename(zipbasepath)
83
else:
1099.3.10 by William Grant
Convince serveservice not to mangle single paths when downloading.
84
    paths = args
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
85
    filename = paths[0]
1099.3.5 by William Grant
Enable CGI path backtracking in serveservice.
86
    if not os.access(filename, os.F_OK):
87
        # The given path doesn't exist. CGI lets us backtrack and put the path
88
        # elements through which we pass into PATH_INFO, so we try that.
89
        while not os.access(filename, os.F_OK):
90
            filename, path_info_frag = os.path.split(filename)
91
92
        # We now have a file that exists, but is it something that we're allowed
93
        # to execute? If not, we should 404 anyway.
94
        if determine_file_type(filename) not in ivle.conf.app.server.interpreters:
95
            throw_error('not-found')
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
96
97
    # If it's a directory, serve as a zip file
1072 by matt.giuca
Renamed scripts to services.
98
    if os.path.isdir(filename):
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
99
        if not download:
100
            # Not giving a directory listing - this is visible to everyone.
101
            throw_error('is-directory')
1072 by matt.giuca
Renamed scripts to services.
102
        zipmode = True
103
        # Zip it from the perspective of its own parent.
104
        # That way it will be a directory in the top level of the zip
105
        # file.
106
        if filename[-1] == os.sep: filename = filename[:-1]
107
        splitpath = filename.rsplit(os.sep, 1)
108
        if len(splitpath) == 1:
109
            zipbasepath = ''
110
            paths = [filename]
111
        else:
112
            zipbasepath = splitpath[0]
113
            paths = [splitpath[1]]
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
114
        zipfilename = filename
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
115
    else:
116
        if not download and \
117
           determine_file_type(filename) in ivle.conf.app.server.interpreters:
1647 by Matt Giuca
serveservice: When throwing an is-executable error, decode the unicode filename as UTF-8 to avoid JSON badly encoding, and then it getting double-encoded later. Serving non-ASCII filenames as Python scripts now works.
118
            throw_error('is-executable', {'path': filename.decode('utf-8')})
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
119
1157 by William Grant
serveservice now only respects the download (black|white)lists when serving,
120
        if not download and (
121
            (ivle.conf.app.server.blacklist_served_filetypes and \
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
122
                determine_file_type(filename) in \
123
                ivle.conf.app.server.served_filetypes_blacklist) or \
124
            (ivle.conf.app.server.served_filetypes_whitelist and \
125
                determine_file_type(filename) not in \
1157 by William Grant
serveservice now only respects the download (black|white)lists when serving,
126
                ivle.conf.app.server.served_filetypes_whitelist)):
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
127
            throw_error('forbidden')
1072 by matt.giuca
Renamed scripts to services.
128
129
if zipmode:
130
    # zipfilename is some filename. Strip trailing slash or extension,
131
    # and add ".zip".
132
    if zipfilename == '':
133
        zipfilename = "files"
134
    elif zipfilename[-1] == '/':
135
        zipfilename = zipfilename[:-1]
136
    elif '.' in zipfilename:
137
        zipfilename = zipfilename[:zipfilename.rindex('.')]
138
    zipfilename += ".zip"
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
139
    #req.headers_out["Content-Disposition"] = ("attachment; filename=" +   
140
    #    zipfilename) # TODO
1072 by matt.giuca
Renamed scripts to services.
141
    zipfile = StringIO.StringIO()
142
    zipmod.make_zip(zipbasepath, paths, zipfile)
1099.3.10 by William Grant
Convince serveservice not to mangle single paths when downloading.
143
1801.1.1 by William Grant
Replace cjson with json, or simplejson if json is not available (Python <2.6)
144
    print json.dumps({'type': zip_mimetype,
1791.2.10 by David Coles
Merge from trunk
145
                      'name': zipfilename.decode('utf-8'),
146
                      'size': len(zipfile.getvalue()),
147
                      })
1163 by William Grant
Stream files from serveservice, rather than reading the whole file in at once.
148
149
    stream = zipfile
150
    stream.seek(0)
1072 by matt.giuca
Renamed scripts to services.
151
else:
1163 by William Grant
Stream files from serveservice, rather than reading the whole file in at once.
152
1801.1.1 by William Grant
Replace cjson with json, or simplejson if json is not available (Python <2.6)
153
    print json.dumps({'type': determine_file_type(filename),
1791.2.10 by David Coles
Merge from trunk
154
                      'name': os.path.basename(filename).decode('utf-8'),
155
                      'size': os.path.getsize(filename),
156
                      })
1163 by William Grant
Stream files from serveservice, rather than reading the whole file in at once.
157
    stream = open(filename)
1801.1.1 by William Grant
Replace cjson with json, or simplejson if json is not available (Python <2.6)
158
1163 by William Grant
Stream files from serveservice, rather than reading the whole file in at once.
159
next = stream.read(1024)
160
while next:
161
    sys.stdout.write(next)
162
    next = stream.read(1024)