~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
28
import cjson
1072 by matt.giuca
Renamed scripts to services.
29
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
30
from ivle import zip as zipmod
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
31
import ivle.conf.app.server
1250 by William Grant
Unbreak serve - it was depending on the old names of a module.
32
import ivle.mimetypes
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
33
34
def determine_file_type(filename):
35
    filetype = mimetypes.guess_type(filename)[0]
36
    if filetype is None:
1250 by William Grant
Unbreak serve - it was depending on the old names of a module.
37
         filetype = ivle.mimetypes.DEFAULT_MIMETYPE
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
38
    return filetype
1072 by matt.giuca
Renamed scripts to services.
39
1099.3.5 by William Grant
Enable CGI path backtracking in serveservice.
40
def throw_error(message, extra={}):
41
    error = {'error': message}
42
    error.update(extra)
43
    print cjson.encode(error)
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
44
    sys.exit(0)
45
46
parser = OptionParser()
47
parser.add_option('-d', '--download', dest='download', action='store_true',
48
                  help='force download, not execution, of the paths')
49
(options, args) = parser.parse_args()
50
51
# Detect download mode. Download mode zips any multiple selection,
52
# and does not execute CGI scripts.
53
if options.download:
54
    download = True
1099.3.10 by William Grant
Convince serveservice not to mangle single paths when downloading.
55
    # paths is filled later.
56
else:
57
    download = False
58
    assert len(args) == 1
59
60
default_mimetype = "application/octet-stream"
61
zip_mimetype = "application/zip"
62
63
zipmode = False
64
zipbasepath = None
65
zipfilename = None
66
67
# If multiple paths have been specified, zip them up.
68
if len(args) > 1:
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
69
    # Mangle the paths - we want the basename of their dirname in front.
70
    paths = []
1099.3.12 by William Grant
Support downloading of a selection of files as a zip.
71
    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.
72
    for path in args:
73
        assert os.path.dirname(path) == dir
74
        paths.append(os.path.join(os.path.basename(dir),
75
                                  os.path.basename(path)))
76
    dir = os.path.dirname(dir)
1072 by matt.giuca
Renamed scripts to services.
77
    zipmode = True
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
78
    zipbasepath = dir
1072 by matt.giuca
Renamed scripts to services.
79
    zipfilename = os.path.basename(zipbasepath)
80
else:
1099.3.10 by William Grant
Convince serveservice not to mangle single paths when downloading.
81
    paths = args
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
82
    filename = paths[0]
1099.3.5 by William Grant
Enable CGI path backtracking in serveservice.
83
    if not os.access(filename, os.F_OK):
84
        # The given path doesn't exist. CGI lets us backtrack and put the path
85
        # elements through which we pass into PATH_INFO, so we try that.
86
        while not os.access(filename, os.F_OK):
87
            filename, path_info_frag = os.path.split(filename)
88
89
        # We now have a file that exists, but is it something that we're allowed
90
        # to execute? If not, we should 404 anyway.
91
        if determine_file_type(filename) not in ivle.conf.app.server.interpreters:
92
            throw_error('not-found')
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
93
94
    # If it's a directory, serve as a zip file
1072 by matt.giuca
Renamed scripts to services.
95
    if os.path.isdir(filename):
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
96
        if not download:
97
            # Not giving a directory listing - this is visible to everyone.
98
            throw_error('is-directory')
1072 by matt.giuca
Renamed scripts to services.
99
        zipmode = True
100
        # Zip it from the perspective of its own parent.
101
        # That way it will be a directory in the top level of the zip
102
        # file.
103
        if filename[-1] == os.sep: filename = filename[:-1]
104
        splitpath = filename.rsplit(os.sep, 1)
105
        if len(splitpath) == 1:
106
            zipbasepath = ''
107
            paths = [filename]
108
        else:
109
            zipbasepath = splitpath[0]
110
            paths = [splitpath[1]]
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
111
        zipfilename = filename
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
112
    else:
113
        if not download and \
114
           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.
115
            throw_error('is-executable', {'path': filename.decode('utf-8')})
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
116
1157 by William Grant
serveservice now only respects the download (black|white)lists when serving,
117
        if not download and (
118
            (ivle.conf.app.server.blacklist_served_filetypes and \
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
119
                determine_file_type(filename) in \
120
                ivle.conf.app.server.served_filetypes_blacklist) or \
121
            (ivle.conf.app.server.served_filetypes_whitelist and \
122
                determine_file_type(filename) not in \
1157 by William Grant
serveservice now only respects the download (black|white)lists when serving,
123
                ivle.conf.app.server.served_filetypes_whitelist)):
1099.3.2 by William Grant
Move more stuff from interpretservice to serveservice.
124
            throw_error('forbidden')
1072 by matt.giuca
Renamed scripts to services.
125
126
if zipmode:
127
    # zipfilename is some filename. Strip trailing slash or extension,
128
    # and add ".zip".
129
    if zipfilename == '':
130
        zipfilename = "files"
131
    elif zipfilename[-1] == '/':
132
        zipfilename = zipfilename[:-1]
133
    elif '.' in zipfilename:
134
        zipfilename = zipfilename[:zipfilename.rindex('.')]
135
    zipfilename += ".zip"
1099.3.1 by William Grant
Change serveservice's interface - it now uses a JSON-based non-CGI one.
136
    #req.headers_out["Content-Disposition"] = ("attachment; filename=" +   
137
    #    zipfilename) # TODO
1072 by matt.giuca
Renamed scripts to services.
138
    zipfile = StringIO.StringIO()
139
    zipmod.make_zip(zipbasepath, paths, zipfile)
1099.3.10 by William Grant
Convince serveservice not to mangle single paths when downloading.
140
1099.3.8 by William Grant
Change the serveservice interface to return the data outside JSON, immediately
141
    print cjson.encode({'type': zip_mimetype,
1649 by Matt Giuca
serveservice and serve: Fixed download of non-ASCII-named files, by decoding filenames in serveservice (so they aren't mangled by JSON) and re-encoding them in the response headers (as you can't put unicode strings in the HTTP response). This is, as far as I can tell, the last outstanding non-ASCII filenames bug in IVLE, so I am closing bug #523500. Hooray.
142
                        'name': zipfilename.decode('utf-8')})
1163 by William Grant
Stream files from serveservice, rather than reading the whole file in at once.
143
144
    stream = zipfile
145
    stream.seek(0)
1072 by matt.giuca
Renamed scripts to services.
146
else:
1163 by William Grant
Stream files from serveservice, rather than reading the whole file in at once.
147
1099.3.8 by William Grant
Change the serveservice interface to return the data outside JSON, immediately
148
    print cjson.encode({'type': determine_file_type(filename),
1649 by Matt Giuca
serveservice and serve: Fixed download of non-ASCII-named files, by decoding filenames in serveservice (so they aren't mangled by JSON) and re-encoding them in the response headers (as you can't put unicode strings in the HTTP response). This is, as far as I can tell, the last outstanding non-ASCII filenames bug in IVLE, so I am closing bug #523500. Hooray.
149
                        'name': os.path.basename(filename).decode('utf-8')})
1163 by William Grant
Stream files from serveservice, rather than reading the whole file in at once.
150
    stream = open(filename)
151
    
152
next = stream.read(1024)
153
while next:
154
    sys.stdout.write(next)
155
    next = stream.read(1024)