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

« back to all changes in this revision

Viewing changes to services/serveservice

  • Committer: mattgiuca
  • Date: 2007-12-10 23:58:10 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:24
src: Added basic directory hierarchy and dummy code for top-level dispatch
    module.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
20
 
# Author: Thomas Conway, Will Grant
21
 
 
22
 
import mimetypes
23
 
import os
24
 
import sys
25
 
import StringIO
26
 
from optparse import OptionParser
27
 
 
28
 
try:
29
 
    import json
30
 
except ImportError:
31
 
    import simplejson as json
32
 
 
33
 
from ivle import zip as zipmod
34
 
import ivle.conf.app.server
35
 
import ivle.mimetypes
36
 
 
37
 
def determine_file_type(filename):
38
 
    filetype = mimetypes.guess_type(filename)[0]
39
 
    if filetype is None:
40
 
         filetype = ivle.mimetypes.DEFAULT_MIMETYPE
41
 
    return filetype
42
 
 
43
 
def throw_error(message, extra={}):
44
 
    error = {'error': message}
45
 
    error.update(extra)
46
 
    print json.dumps(error)
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
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:
72
 
    # Mangle the paths - we want the basename of their dirname in front.
73
 
    paths = []
74
 
    dir = os.path.dirname(args[0])
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)
80
 
    zipmode = True
81
 
    zipbasepath = dir
82
 
    zipfilename = os.path.basename(zipbasepath)
83
 
else:
84
 
    paths = args
85
 
    filename = paths[0]
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')
96
 
 
97
 
    # If it's a directory, serve as a zip file
98
 
    if os.path.isdir(filename):
99
 
        if not download:
100
 
            # Not giving a directory listing - this is visible to everyone.
101
 
            throw_error('is-directory')
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]]
114
 
        zipfilename = filename
115
 
    else:
116
 
        if not download and \
117
 
           determine_file_type(filename) in ivle.conf.app.server.interpreters:
118
 
            throw_error('is-executable', {'path': filename.decode('utf-8')})
119
 
 
120
 
        if not download and (
121
 
            (ivle.conf.app.server.blacklist_served_filetypes and \
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 \
126
 
                ivle.conf.app.server.served_filetypes_whitelist)):
127
 
            throw_error('forbidden')
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"
139
 
    #req.headers_out["Content-Disposition"] = ("attachment; filename=" +   
140
 
    #    zipfilename) # TODO
141
 
    zipfile = StringIO.StringIO()
142
 
    zipmod.make_zip(zipbasepath, paths, zipfile)
143
 
 
144
 
    print json.dumps({'type': zip_mimetype,
145
 
                      'name': zipfilename.decode('utf-8')})
146
 
 
147
 
    stream = zipfile
148
 
    stream.seek(0)
149
 
else:
150
 
 
151
 
    print json.dumps({'type': determine_file_type(filename),
152
 
                      'name': os.path.basename(filename).decode('utf-8')})
153
 
    stream = open(filename)
154
 
 
155
 
next = stream.read(1024)
156
 
while next:
157
 
    sys.stdout.write(next)
158
 
    next = stream.read(1024)