31
35
from ivle import (util, studpath)
36
import genshi.template
38
# url path for this app
42
"""Handler for the File Browser application."""
44
# Work out where we are browsing
46
if len(browsepath) == 0:
47
# If no path specified, default to the user's home directory
48
redirectPath = util.make_path(os.path.join(THIS_APP,req.user.login))
49
req.throw_redirect(util.make_path(redirectPath))
51
ctx = genshi.template.Context()
53
# Set request attributes
54
req.content_type = "text/html"
56
"media/browser/browser.css",
57
"media/browser/listing.css",
58
"media/browser/editor.css",
61
"media/common/json2.js",
62
"media/common/codepress/codepress.js",
63
"media/common/util.js",
64
"media/browser/browser.js",
65
"media/browser/listing.js",
66
"media/browser/editor.js",
67
"media/browser/specialhome.js",
73
req.write_html_head_foot = True # Have dispatch print head and foot
74
# The page title should contain the name of the file being browsed
75
req.title = browsepath.rsplit('/', 1)[-1]
77
_, localpath = studpath.url_to_local(browsepath)
79
req.throw_error(req.HTTP_NOT_FOUND,
80
"The path specified is invalid.")
84
# FIXME: This isn't completely reliable! We're not inside the jail, so we
85
# can't know the type for sure. This is now only used for adding a / to the
86
# end of displayed paths, so I'm leaving this although it will often break.
87
isdir = os.path.isdir(localpath)
89
gen_path(req, browsepath, ctx)
92
ctx['fileservice_action'] = util.make_path(os.path.join("fileservice", req.path))
93
ctx['filename'] = cgi.escape(req.path)
95
loader = genshi.template.TemplateLoader(".", auto_reload=True)
96
tmpl = loader.load(util.make_local_path("apps/browser/template.html"))
98
req.write(tmpl.generate(ctx).render('html')) #'xhtml', doctype='xhtml'))
100
#TODO: Move all this logic into the template
101
def gen_path(req, path, ctx):
103
href_path = util.make_path(THIS_APP)
105
revision = ivle.svn.revision_from_string(
106
req.get_fieldstorage().getfirst('r'))
108
revno = revision.number
114
# Create all of the paths
115
pathlist = path.split("/")
117
for path_seg in pathlist:
122
nav_path = nav_path + path_seg
123
href_path = href_path + '/' + path_seg
125
new_seg['path'] = path_seg
126
new_seg['nav_path'] = nav_path
127
new_seg['href_path'] = href_path
128
if revno is not None:
129
new_seg['href_path'] += '?r=%d' % revno
131
ctx['paths'].append(new_seg)
134
def gen_actions(req, ctx):
136
Presents a set of links/buttons for the "actions1" row of the top bar.
137
This is always exactly the same - the JavaScript will customize it later.
139
# Set up our actions. The second field of each group is whether to disable
140
# the items by default.
141
ctx['moreactions'] = [
142
('Publishing', True, [
143
('publish', ['Publish', 'Make it so this directory can be seen by anyone on the web']),
144
('share', ['Share this file', 'Get a link to this published file, to give to friends']),
145
('submit', ['Submit', 'Submit the selected files for an assignment'])
147
('File actions', True, [
148
('rename', ['Rename', 'Change the name of this file']),
149
('delete', ['Delete', 'Delete the selected files']),
150
('copy', ['Copy', 'Prepare to copy the selected files to another directory']),
151
('cut', ['Cut', 'Prepare to move the selected files to another directory'])
153
('Directory actions', False, [
154
('paste', ['Paste', 'Paste the copied or cut files into the current directory']),
155
('newfile', ['New File', 'Open a new file for editing in the current directory']),
156
('mkdir', ['New Directory', 'Make a new subdirectory in the current directory']),
157
('upload', ['Upload File', 'Upload a file to the current directory'])
159
('Subversion', True, [
160
('svncut', ['Svn Cut', 'Prepare to move the selected files to another directory, maintaining history']),
161
('svncopy', ['Svn Copy', 'Prepare to copy the selected files to another directory, maintaining history']),
162
('svnadd', ['Add', 'Schedule the selected temporary files to be added permanently']),
163
('svnremove', ['Remove', 'Schedule the selected permanent files to be removed']),
164
('svndiff', ['Diff', 'View any changes to the selected file since its last committed state']),
165
('svnrevert', ['Revert', 'Restore the selected files back to their last committed state']),
166
('svnupdate', ['Update', 'Update your files with changes from the permanent repository']),
167
('svncommit', ['Commit', 'Commit any changes to the permanent repository']),
168
('svnresolved', ['Mark Resolved', 'Mark a conflicted file as being resolved']),
169
('svnlog', ['View Log', 'View the log of commits of the selected file']),
38
class BrowserView(XHTMLView):
40
The view for the browser
42
template = 'template.html'
44
help = 'Filesystem/Browser'
46
def authorize(self, req):
47
return req.user is not None
49
def populate(self, req, ctx):
50
if not hasattr(self, 'path'):
51
# If no path specified, default to the user's home directory
52
redirectPath = util.make_path(os.path.join('files', req.user.login))
53
req.throw_redirect(util.make_path(redirectPath))
55
# Set request attributes
56
self.plugin_styles[Plugin] = ['browser.css',
59
self.plugin_scripts[Plugin] = ['browser.js',
63
'codepress/codepress.js']
64
req.scripts_init = ["browser_init"]
66
_, localpath = studpath.url_to_local(self.path)
72
# FIXME: This isn't completely reliable! We're not inside the jail, so we
73
# can't know the type for sure. This is now only used for adding a / to the
74
# end of displayed paths, so I'm leaving this although it will often break.
75
isdir = os.path.isdir(localpath)
77
self.gen_path(req, ctx)
78
self.gen_actions(req, ctx)
80
# The page title should contain the name of the file being browsed
81
ctx['title'] = self.path.rsplit('/', 1)[-1]
83
ctx['fileservice_action'] = util.make_path(os.path.join("fileservice", req.path))
84
ctx['filename'] = cgi.escape(req.path)
86
#TODO: Move all this logic into the template
87
def gen_path(self, req, ctx):
89
href_path = util.make_path('files')
91
revision = ivle.svn.revision_from_string(
92
req.get_fieldstorage().getfirst('r'))
94
revno = revision.number
100
# Create all of the paths
101
pathlist = self.path.split("/")
103
for path_seg in pathlist:
108
nav_path = nav_path + path_seg
109
href_path = href_path + '/' + path_seg
111
new_seg['path'] = path_seg
112
new_seg['nav_path'] = nav_path
113
new_seg['href_path'] = href_path
114
if revno is not None:
115
new_seg['href_path'] += '?r=%d' % revno
117
ctx['paths'].append(new_seg)
119
def gen_actions(self, req, ctx):
121
Presents a set of links/buttons for the "actions1" row of the top bar.
122
This is always exactly the same - the JavaScript will customize it later.
124
# Set up our actions. The second field of each group is whether to disable
125
# the items by default.
126
ctx['moreactions'] = [
127
('Publishing', True, [
128
('publish', ['Publish', 'Make it so this directory can be seen by anyone on the web']),
129
('share', ['Share this file', 'Get a link to this published file, to give to friends']),
130
('submit', ['Submit', 'Submit the selected files for an assignment'])
132
('File actions', True, [
133
('rename', ['Rename', 'Change the name of this file']),
134
('delete', ['Delete', 'Delete the selected files']),
135
('copy', ['Copy', 'Prepare to copy the selected files to another directory']),
136
('cut', ['Cut', 'Prepare to move the selected files to another directory'])
138
('Directory actions', False, [
139
('paste', ['Paste', 'Paste the copied or cut files into the current directory']),
140
('newfile', ['New File', 'Open a new file for editing in the current directory']),
141
('mkdir', ['New Directory', 'Make a new subdirectory in the current directory']),
142
('upload', ['Upload File', 'Upload a file to the current directory'])
144
('Subversion', True, [
145
('svncut', ['Svn Cut', 'Prepare to move the selected files to another directory, maintaining history']),
146
('svncopy', ['Svn Copy', 'Prepare to copy the selected files to another directory, maintaining history']),
147
('svnadd', ['Add', 'Schedule the selected temporary files to be added permanently']),
148
('svnremove', ['Remove', 'Schedule the selected permanent files to be removed']),
149
('svndiff', ['Diff', 'View any changes to the selected file since its last committed state']),
150
('svnrevert', ['Revert', 'Restore the selected files back to their last committed state']),
151
('svnupdate', ['Update', 'Update your files with changes from the permanent repository']),
152
('svncommit', ['Commit', 'Commit any changes to the permanent repository']),
153
('svnresolved', ['Mark Resolved', 'Mark a conflicted file as being resolved']),
154
('svnlog', ['View Log', 'View the log of commits of the selected file']),
158
class Plugin(ViewPlugin, CookiePlugin, MediaPlugin):
160
The Plugin class for the user plugin.
162
# Magic attribute: urls
163
# Sequence of pairs/triples of
164
# (regex str, handler class, kwargs dict)
165
# The kwargs dict is passed to the __init__ of the view object
167
('files/*(path)', BrowserView),
168
('files/', BrowserView),
173
('files', 'Files', 'Gives you access to all of your files and lets '
174
'you download, upload, edit and run them.', 'browser.png', 'files', 1)
177
cookies = {'clipboard': None}
179
help = {'Filesystem': {'Browser': 'help.html'}}