Commit e7d35b4d authored by asseldonk's avatar asseldonk
Browse files

filebrowser: disable sharing, fix #2013, #2016

parent 74fdf545
......@@ -14,7 +14,7 @@
}
.dropdown-menu {
margin-top: 4px;
.glyphicon {
.glyphicon {
margin-right: 10px;
}
}
......@@ -46,7 +46,7 @@
color: @gray-dark;
&:hover {
color: @gray-base !important;
}
}
}
> .bookmark-name {
margin-right: 10px;
......@@ -55,13 +55,13 @@
color: @body-bg;
&:hover {
color: @gray-base !important;
}
}
}
> .bookmark-glyphicon-remove {
color: @body-bg;
&:hover {
color: @gray-base !important;
}
}
}
}
}
......
......@@ -18,7 +18,11 @@
<input type="checkbox" class="file-selection-checkbox"/></span></div>
<div class="icon"><span data-bind="icon"></span></div>
<div class="name"><span class="completename"><span data-bind="root" class="filename-root"></span><span data-bind="ext" class="filename-ext"></span></span></div>
<div class="edit-tools hidden-xs"><a href="#" class="edit-rename"><i class="glyphicon glyphicon-pencil"></i><span class="hidden-sm hidden-xs">Rename</span></a><a href="#" class="edit-download"><i class="glyphicon glyphicon-download"></i><span class="hidden-sm hidden-xs">Download</span></a><a href="#" class="edit-share"><i class="glyphicon glyphicon-link"></i><span class="hidden-sm hidden-xs">Share</span></a><a href="#" class="edit-remove"><i class="glyphicon glyphicon-remove"></i><span class="hidden-sm hidden-xs">Remove</span></a></div>
<div class="edit-tools hidden-xs"><a href="#" class="edit-rename"><i class="glyphicon glyphicon-pencil"></i><span class="hidden-sm hidden-xs">Rename</span></a><a href="#" class="edit-download"><i class="glyphicon glyphicon-download"></i><span class="hidden-sm hidden-xs">Download</span></a>
<!-- a.edit-share(href="#")-->
<!-- i.glyphicon.glyphicon-link-->
<!-- span.hidden-sm.hidden-xs Share--><a href="#" class="edit-remove"><i class="glyphicon glyphicon-remove"></i><span class="hidden-sm hidden-xs">Remove</span></a>
</div>
<div class="size hidden-sm hidden-xs"><span data-bind="size"></span><span data-bind="sizeSuffix"></span></div>
<div class="time hidden-xs"><span data-bind="mtime"></span></div>
<div class="file-properties options">
......
......@@ -30,9 +30,9 @@
a.edit-download(href="#")
i.glyphicon.glyphicon-download
span.hidden-sm.hidden-xs Download
a.edit-share(href="#")
i.glyphicon.glyphicon-link
span.hidden-sm.hidden-xs Share
// a.edit-share(href="#")
// i.glyphicon.glyphicon-link
// span.hidden-sm.hidden-xs Share
a.edit-remove(href="#")
i.glyphicon.glyphicon-remove
span.hidden-sm.hidden-xs Remove
......
......@@ -127,7 +127,6 @@ var FileBaseView = Class.extend({
// to do: fortran and targz
var extension = (self.FileBase.helper.strExtension(name) || "").toLowerCase();
var extensionCapital = (self.FileBase.helper.strExtension(name) || "");
console.log(extensionCapital);
if (availableIcons.indexOf(extension) >= 0) {
src = iconPrefix + extension;
// take correct icon for precompiled fortran files
......
......@@ -53,7 +53,7 @@ class FileSystem(object):
self.watchservice = WatchService()
self._userid = userid
self._workspaceid = workspaceid
def __del__(self):
self.close()
......@@ -73,7 +73,7 @@ class FileSystem(object):
def close(self):
if self.watchservice:
self.watchservice.stop()
def get_mime_type(self, filepath):
filepath = self.expand(filepath)
mime, encoding = guess_type(filepath)
......@@ -145,7 +145,7 @@ class FileSystem(object):
# excluded by filters?
if filter and bool(filter.search(elem)) != reverse:
continue
root, ext = os.path.splitext(elem)
info = {
'name': elem,
......@@ -348,17 +348,33 @@ class FileSystem(object):
fullsrc.split(os.sep)[-1], path)
fulltarget = os.path.join(path, target)
if os.path.isdir(fullsrc):
shutil.copytree(fullsrc, fulltarget)
if cut:
shutil.rmtree(fullsrc)
orig_target = fullsrc.split(os.sep)[-1]
orig_fulltarget = os.path.join(path, orig_target)
if fullsrc != orig_fulltarget:
if os.path.isdir(fullsrc):
shutil.copytree(fullsrc, fulltarget)
if cut:
shutil.rmtree(fullsrc)
else:
shutil.copy2(fullsrc, fulltarget)
if cut:
os.remove(fullsrc)
else:
shutil.copy2(fullsrc, fulltarget)
if cut:
os.remove(fullsrc)
fulltarget_temp = orig_fulltarget + "~temp"
if os.path.isdir(fullsrc):
shutil.copytree(fullsrc, fulltarget_temp)
if cut:
shutil.rmtree(fullsrc)
shutil.move(fulltarget_temp, orig_fulltarget)
else:
shutil.copy2(fullsrc, fulltarget_temp)
if cut:
os.remove(fullsrc)
shutil.move(fulltarget_temp, orig_fulltarget)
def save_file(self, path, content, force=True, binary=False,
utf8=False, window_id=None, view_id=None, watch_id=None):
utf8=False, window_id=None, view_id=None, watch_id=None):
path = self.expand(path)
# check if file already exists
if os.path.exists(path) and not force:
......@@ -374,29 +390,30 @@ class FileSystem(object):
f.write(content)
mtime = os.path.getmtime(path)
except Exception as e:
mtime = 0
mtime = 0
# inline watch
if window_id and view_id and watch_id:
watch_error = self.watch(path, window_id, view_id, watch_id)
else:
watch_error = ""
return json.dumps({
"mtime": os.path.getmtime(path),
"success": mtime > 0 and self.checkPermissions(path), #save is not successful, if file not writable
"watch_error": watch_error,
# save is not successful, if file not writable
"success": mtime > 0 and self.checkPermissions(path),
"watch_error": watch_error,
"path": path
})
def get_file(self, path, binary=False,
utf8=False, window_id=None, view_id=None, watch_id=None):
utf8=False, window_id=None, view_id=None, watch_id=None):
# inline watch
if window_id and view_id and watch_id:
watch_error = self.watch(path, window_id, view_id, watch_id)
else:
watch_error = ""
# actual function
path = self.expand(path)
try:
......@@ -404,15 +421,15 @@ class FileSystem(object):
content = f.read()
if utf8:
content = content.decode('utf8')
#new: check for writing rights
# new: check for writing rights
writable = self.checkPermissions(path)
mtime = os.path.getmtime(path)
except Exception as e:
mtime = 0
mtime = 0
content = ""
writable = None
return json.dumps({
"content": content,
"mtime": mtime,
......@@ -422,7 +439,7 @@ class FileSystem(object):
})
def checkPermissions(self, path):
return os.access(path, os.W_OK)
return os.access(path, os.W_OK)
def save_file_content(self, filename, content,
path=None, force=True, append=False):
......@@ -532,10 +549,11 @@ class FileSystem(object):
path = self.expand(path)
if not os.path.exists(path):
return "The file does not exist"
self.watchservice.subscribe((window_id, view_id, watch_id), path, pattern, reverse)
self.watchservice.subscribe(
(window_id, view_id, watch_id), path, pattern, reverse)
return ""
def unwatch(self, window_id, view_id, watch_id=None):
self.watchservice.unsubscribe((window_id, view_id, watch_id))
return ""
......@@ -545,10 +563,10 @@ class FileSystem(object):
request_dict = json.loads(request)
config = ConfigParser.ConfigParser()
config.read([FileSystem.GLOBAL_WORKSPACE_CONF,
self.expand(FileSystem.PRIVATE_WORKSPACE_CONF)])
self.expand(FileSystem.PRIVATE_WORKSPACE_CONF)])
if self.exists(FileSystem.PRIVATE_WORKSPACE_CONF):
mtime = self.get_mtime(FileSystem.PRIVATE_WORKSPACE_CONF)
self._watch_workspaceini()
self._watch_workspaceini()
else:
mtime = -1
if not isinstance(request_dict, dict):
......@@ -566,31 +584,35 @@ class FileSystem(object):
if config.has_option(section, name):
data[section][name] = config.get(section, name)
elif fail_on_missing:
raise Exception('workspace.ini is missing the option "%s" in section [%s] ' % (name, section))
raise Exception(
'workspace.ini is missing the option "%s" in section [%s] ' % (name, section))
elif fail_on_missing:
raise Exception('workspace.ini is missing the section [%s]' % section)
raise Exception(
'workspace.ini is missing the section [%s]' % section)
return json.dumps({
"content": data,
"success": True,
"mtime": mtime
})
})
except Exception as e:
return json.dumps({
"content": "",
"success": False,
"error": str(e)
})
})
def set_workspaceini(self, request):
try:
request_dict = json.loads(request)
if not isinstance(request_dict, dict):
raise Exception('Given values to be set in workspace.ini in wrong format')
raise Exception(
'Given values to be set in workspace.ini in wrong format')
config = ConfigParser.ConfigParser()
config.read(self.expand(FileSystem.PRIVATE_WORKSPACE_CONF))
for section, options in request_dict.iteritems():
if not isinstance(options, dict):
raise Exception('Given values to be set in workspace.ini in wrong format')
raise Exception(
'Given values to be set in workspace.ini in wrong format')
if not config.has_section(section):
config.add_section(section)
for name, value in options.iteritems():
......@@ -604,9 +626,12 @@ class FileSystem(object):
def _watch_workspaceini(self):
if self.exists(FileSystem.PRIVATE_WORKSPACE_CONF, 'f'):
self.watchservice.subscribe((self._userid, self._workspaceid), FileSystem.PRIVATE_WORKSPACE_CONF)
self.watchservice.subscribe(
(self._userid, self._workspaceid), FileSystem.PRIVATE_WORKSPACE_CONF)
class WatchService(object):
def __init__(self):
self.subscriber_buffer = []
self.subscribers = {}
......@@ -616,76 +641,79 @@ class WatchService(object):
self.run = True
self.thread = Thread(target=self._worker)
self.thread.start()
def subscribe(self, id, path, pattern=None, reverse=False):
if not path:
return self.unsubscribe(id)
path = os.path.expanduser(os.path.expandvars(path)).encode('utf8')
with self.lock:
if id not in self.subscribers:
WatchSubscriber(self, id)
self.subscribers[id].update(path, pattern, reverse)
def unsubscribe(self, id):
with self.lock:
if hasattr(id, '__contains__') and None in id:
for subscriber in self.subscribers.values():
if False not in map(lambda e,c: c is None or e == c, subscriber.id, id):
if False not in map(lambda e, c: c is None or e == c, subscriber.id, id):
subscriber.destroy()
elif id in self.subscribers:
self.subscribers[id].destroy()
def stop(self):
self.run = False
def _worker(self):
while self.run:
events = self.monitor.read_events(0.05)
if events:
with self.lock:
for event in events:
if event.action_name in ['delete self','move self']:
if event.action_name in ['delete self', 'move self']:
kind = 'vanish'
elif event.action_name == 'modify':
kind = 'modify'
elif event.watch.isdir and event.action_name in ['create','delete','move from','move to']:
elif event.watch.isdir and event.action_name in ['create', 'delete', 'move from', 'move to']:
kind = 'change'
else:
kind = None
if kind:
if not event.watch.isdir:
if os.path.exists(event.watch.path):
event.watch.mtime = os.path.getmtime(event.watch.path)
event.watch.mtime = os.path.getmtime(
event.watch.path)
else:
event.watch.mtime = -1
for subscriber in event.watch.subscribers[:]:
subscriber.process(kind, event.name)
if self.subscriber_buffer:
with self.lock:
for subscriber in self.subscriber_buffer[:]:
subscriber.flush(False)
for subscriber in self.subscribers.items():
subscriber.destroy()
self.monitor.remove_all_watches()
self.monitor.close()
class WatchSubscriber(object): # this should never be instanced manually
class WatchSubscriber(object): # this should never be instanced manually
EVENT_DELAYS = {
'change': [1.0,0.1],
'modify': [1.0,0.2]
'change': [1.0, 0.1],
'modify': [1.0, 0.2]
}
def __init__(self, service, id):
if not isinstance(service, WatchService):
raise TypeError("No valid WatchService instance was provided")
if id in service.subscribers:
raise RuntimeError("There is already a subscriber with this id: "+str(id))
raise RuntimeError(
"There is already a subscriber with this id: " + str(id))
self.id = id
self.service = service
self.service.subscribers[self.id] = self
......@@ -693,7 +721,7 @@ class WatchSubscriber(object): # this should never be instanced manually
self.pattern = None
self.reverse = None
self.event_buffer = {}
def destroy(self):
self.unbind()
if self in self.service.subscriber_buffer:
......@@ -702,22 +730,24 @@ class WatchSubscriber(object): # this should never be instanced manually
del self.service
del self.watch
del self.event_buffer
def process(self, event, subject=""):
if self.watch.isdir and subject and self.pattern and bool(self.pattern.search(subject)) != self.reverse:
return
if event in WatchSubscriber.EVENT_DELAYS:
now = time()
if event in self.event_buffer:
self.event_buffer[event][1] = now + WatchSubscriber.EVENT_DELAYS[event][1]
self.event_buffer[event][1] = now + \
WatchSubscriber.EVENT_DELAYS[event][1]
else:
self.event_buffer[event] = [now + delay for delay in WatchSubscriber.EVENT_DELAYS[event]] #first & last event
self.event_buffer[event] = [
now + delay for delay in WatchSubscriber.EVENT_DELAYS[event]] # first & last event
if self not in self.service.subscriber_buffer:
self.service.subscriber_buffer.append(self)
else:
self.emit(event)
def flush(self, force=False):
now = time()
for event, delays in self.event_buffer.items():
......@@ -728,7 +758,7 @@ class WatchSubscriber(object): # this should never be instanced manually
self.service.subscriber_buffer.remove(self)
def emit(self, event):
if len(self.id) == 3: # window_id, view_id, watch_id
if len(self.id) == 3: # window_id, view_id, watch_id
data = {
'event': event,
'path': self.watch.path,
......@@ -736,15 +766,16 @@ class WatchSubscriber(object): # this should never be instanced manually
}
if not self.watch.isdir:
data['mtime'] = self.watch.mtime
vispa.remote.send_topic("extension.%s.socket.watch" % self.id[1], window_id=self.id[0], data=data)
elif len(self.id) == 2: # userid, workspaceid
vispa.remote.send_topic(
"extension.%s.socket.watch" % self.id[1], window_id=self.id[0], data=data)
elif len(self.id) == 2: # userid, workspaceid
vispa.remote.send_topic('workspace.ini_modified', user_id=self.id[0], data={
"workspaceId": self.id[1],
"mtime": self.watch.mtime
})
elif hasattr(self.id, '__call__'):
self.id(event, self)
def update(self, path, pattern="", reverse=False):
self.bind(path)
if self.watch.isdir and pattern:
......@@ -754,14 +785,14 @@ class WatchSubscriber(object): # this should never be instanced manually
else:
self.pattern = None
self.reverse = None
def bind(self, path):
if self.watch:
if self.watch.path == path:
return
else:
self.unbind()
if path not in self.service.watches:
if not os.path.exists(path):
raise IOError("File to be watched does not exist: %s" % path)
......@@ -778,22 +809,23 @@ class WatchSubscriber(object): # this should never be instanced manually
self.service.watches[path] = watch
else:
watch = self.service.watches[path]
self.watch = watch
if self not in watch.subscribers:
watch.subscribers.append(self)
def unbind(self):
if not self.watch:
return
self.watch.subscribers.remove(self)
if len(self.watch.subscribers) == 0:
del self.service.watches[self.watch.path]
self.service.monitor.remove_watch(self.watch)
self.watch = None
def string_compare(a, b):
if a == b:
return 0
......@@ -802,6 +834,7 @@ def string_compare(a, b):
else:
return -1
def file_compare(a, b):
if not a.startswith('.') and not b.startswith('.'):
return string_compare(a, b)
......@@ -811,3 +844,5 @@ def file_compare(a, b):
return 1
elif not a.startswith('.') and b.startswith('.'):
return -1
h('.') and b.startswith('.'):
return -1
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment