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'
45
def populate(self, req, ctx):
46
if not hasattr(self, 'path'):
47
# If no path specified, default to the user's home directory
48
redirectPath = util.make_path(os.path.join('files', req.user.login))
49
req.throw_redirect(util.make_path(redirectPath))
51
# Set request attributes
52
self.plugin_styles[Plugin] = ['browser.css',
55
self.plugin_scripts[Plugin] = ['browser.js',
59
req.scripts = ["/media/common/codepress/codepress.js"]
60
req.scripts_init = ["browser_init"]
62
# The page title should contain the name of the file being browsed
63
req.title = self.path.rsplit('/', 1)[-1]
65
_, localpath = studpath.url_to_local(self.path)
71
# FIXME: This isn't completely reliable! We're not inside the jail, so we
72
# can't know the type for sure. This is now only used for adding a / to the
73
# end of displayed paths, so I'm leaving this although it will often break.
74
isdir = os.path.isdir(localpath)
76
self.gen_path(req, ctx)
77
self.gen_actions(req, ctx)
79
ctx['fileservice_action'] = util.make_path(os.path.join("fileservice", req.path))
80
ctx['filename'] = cgi.escape(req.path)
82
#TODO: Move all this logic into the template
83
def gen_path(self, req, ctx):
85
href_path = util.make_path('files')
87
revision = ivle.svn.revision_from_string(
88
req.get_fieldstorage().getfirst('r'))
90
revno = revision.number
96
# Create all of the paths
97
pathlist = self.path.split("/")
99
for path_seg in pathlist:
104
nav_path = nav_path + path_seg
105
href_path = href_path + '/' + path_seg
107
new_seg['path'] = path_seg
108
new_seg['nav_path'] = nav_path
109
new_seg['href_path'] = href_path
110
if revno is not None:
111
new_seg['href_path'] += '?r=%d' % revno
113
ctx['paths'].append(new_seg)
115
def gen_actions(self, req, ctx):
117
Presents a set of links/buttons for the "actions1" row of the top bar.
118
This is always exactly the same - the JavaScript will customize it later.
120
# Set up our actions. The second field of each group is whether to disable
121
# the items by default.
122
ctx['moreactions'] = [
123
('Publishing', True, [
124
('publish', ['Publish', 'Make it so this directory can be seen by anyone on the web']),
125
('share', ['Share this file', 'Get a link to this published file, to give to friends']),
126
('submit', ['Submit', 'Submit the selected files for an assignment'])
128
('File actions', True, [
129
('rename', ['Rename', 'Change the name of this file']),
130
('delete', ['Delete', 'Delete the selected files']),
131
('copy', ['Copy', 'Prepare to copy the selected files to another directory']),
132
('cut', ['Cut', 'Prepare to move the selected files to another directory'])
134
('Directory actions', False, [
135
('paste', ['Paste', 'Paste the copied or cut files into the current directory']),
136
('newfile', ['New File', 'Open a new file for editing in the current directory']),
137
('mkdir', ['New Directory', 'Make a new subdirectory in the current directory']),
138
('upload', ['Upload File', 'Upload a file to the current directory'])
140
('Subversion', True, [
141
('svncut', ['Svn Cut', 'Prepare to move the selected files to another directory, maintaining history']),
142
('svncopy', ['Svn Copy', 'Prepare to copy the selected files to another directory, maintaining history']),
143
('svnadd', ['Add', 'Schedule the selected temporary files to be added permanently']),
144
('svnremove', ['Remove', 'Schedule the selected permanent files to be removed']),
145
('svndiff', ['Diff', 'View any changes to the selected file since its last committed state']),
146
('svnrevert', ['Revert', 'Restore the selected files back to their last committed state']),
147
('svnupdate', ['Update', 'Update your files with changes from the permanent repository']),
148
('svncommit', ['Commit', 'Commit any changes to the permanent repository']),
149
('svnresolved', ['Mark Resolved', 'Mark a conflicted file as being resolved']),
150
('svnlog', ['View Log', 'View the log of commits of the selected file']),
154
class Plugin(ViewPlugin, CookiePlugin, MediaPlugin):
156
The Plugin class for the user plugin.
158
# Magic attribute: urls
159
# Sequence of pairs/triples of
160
# (regex str, handler class, kwargs dict)
161
# The kwargs dict is passed to the __init__ of the view object
163
('files/*(path)', BrowserView),
164
('files/', BrowserView),
167
cookies = {'clipboard': None}