def rename(self, oldpath, newpath): oldpath = self._realpath(oldpath) newpath = self._realpath(newpath) try: os.rename(oldpath, newpath) except OSError, e: return SFTPServer.convert_errno(e.errno)
def list_folder(self, path): """ List contents of a folder. """ self.log.debug('list_folder({0!r})'.format(path)) rpath = self._realpath(path) if not self.user.is_sysop and self._is_uploaddir(path): return [] try: out = [] if path == u'/': out.append(self._dummy_dir_stat()) elif flagged_dirname in path: self.flagged = self.user.get('flaggedfiles', set()) for fname in self.flagged: rname = fname attr = SFTPAttributes.from_stat(os.stat(rname)) attr.filename = fname[fname.rindex('/') + 1:] out.append(attr) return out flist = os.listdir(rpath) for fname in flist: attr = SFTPAttributes.from_stat( os.stat(os.path.join(rpath, fname))) attr.filename = fname out.append(attr) return out except OSError as err: return SFTPServer.convert_errno(err.errno)
def lstat(self, path): path = self._realpath(path) try: return SFTPAttributes.from_stat(os.lstat(path)) except OSError: e = sys.exc_info()[1] return SFTPServer.convert_errno(e.errno)
def stat(self): """ Stat the file descriptor. """ self.log.debug('stat') try: return SFTPAttributes.from_stat(os.fstat(self.readfile.fileno())) except OSError as err: return SFTPServer.convert_errno(err.errno)
def rmdir(self, path): path = self._realpath(path) try: os.rmdir(path) except OSError as e: return SFTPServer.convert_errno(e.errno) return SFTP_OK
def chattr(self, path, attr): path = self._realpath(path) try: SFTPServer.set_file_attr(path, attr) except OSError as e: return SFTPServer.convert_errno(e.errno) return SFTP_OK
def rmdir(self, path): path = self._realpath(path) try: os.rmdir(path) except OSError: e = sys.exc_info()[1] return SFTPServer.convert_errno(e.errno) return SFTP_OK
def chattr(self, attr): # python doesn't have equivalents to fchown or fchmod, so we have to # use the stored filename mutter('Changing permissions on %s to %s', self.filename, attr) try: SFTPServer.set_file_attr(self.filename, attr) except OSError, e: return SFTPServer.convert_errno(e.errno)
def chattr(self, attr): # python doesn't have equivalents to fchown or fchmod, so we have to # use the stored filename try: SFTPServer.set_file_attr(self.filename, attr) return SFTP_OK except OSError as e: return SFTPServer.convert_errno(e.errno)
def mkdir(self, path, attr): path = self._realpath(path) try: os.mkdir(path) if attr is not None: SFTPServer.set_file_attr(path, attr) except OSError, e: return SFTPServer.convert_errno(e.errno)
def stat(self): """ This method performs the stat attributes return path SFTPAttributes or error """ try: return SFTPAttributes.from_stat(os.fstat(self.readfile.fileno())) except OSError, e: return SFTPServer.convert_errno(e.errno)
def rename(self, oldpath, newpath): oldpath = self._realpath(oldpath) newpath = self._realpath(newpath) try: os.rename(oldpath, newpath) except OSError: e = sys.exc_info()[1] return SFTPServer.convert_errno(e.errno) return SFTP_OK
def open(self, path, flags, attr): """ Up/download the given path. """ self.log.debug('lstat({0!r}, {1!r}, {2!r})' .format(path, flags, attr)) path = self._realpath(path) if (flags & os.O_CREAT and (uploads_dirname not in path and not self.user.is_sysop) or (uploads_dirname in path and os.path.exists(path))): return SFTP_PERMISSION_DENIED try: binary_flag = getattr(os, 'O_BINARY', 0) flags |= binary_flag filedesc = os.open(path, flags, self.mode) except OSError as err: return SFTPServer.convert_errno(err.errno) if (flags & os.O_CREAT) and (attr is not None): attr._flags &= ~attr.FLAG_PERMISSIONS SFTPServer.set_file_attr(path, attr) if flags & os.O_WRONLY: if flags & os.O_APPEND: fstr = 'ab' else: fstr = 'wb' elif flags & os.O_RDWR: if flags & os.O_APPEND: fstr = 'a+b' else: fstr = 'r+b' else: # O_RDONLY (== 0) fstr = 'rb' try: openfile = os.fdopen(filedesc, fstr) except OSError as err: return SFTPServer.convert_errno(err.errno) fobj = X84SFTPHandle(flags, user=self.user) fobj.filename = path fobj.readfile = openfile fobj.writefile = openfile if path in self.flagged: self.flagged.remove(path) self.user['flaggedfiles'] = self.flagged return fobj
def rmdir(self, path): if not self.user.is_sysop or flagged_dirname in path: return SFTP_PERMISSION_DENIED self.log.debug('rmdir({0!r})'.format(path)) path = self._realpath(path) try: os.rmdir(path) except OSError as err: return SFTPServer.convert_errno(err.errno) return SFTP_OK
def rename(self, oldpath, newpath): oldpath = self._realpath(oldpath) newpath = self._realpath(newpath) if os.path.exists(newpath): return SFTP_FAILURE try: os.rename(oldpath, newpath) except OSError as e: return SFTPServer.convert_errno(e.errno) return SFTP_OK
def readlink(self, path): """ This method reads symbolic links. path - path to be read return SFTP_OK or error """ path = self._realpath(path) try: symlink = os.readlink(path) except OSError, e: return SFTPServer.convert_errno(e.errno)
def rmdir(self, path): """ This method deletes the given folder path - folder path to be deleted return SFTP_OK or error """ path = self._realpath(path) try: os.rmdir(path) except OSError, e: return SFTPServer.convert_errno(e.errno)
def remove(self, path): """ This method deletes the given path to file path - file path return SFTP_OK or error """ path = self._realpath(path) try: os.remove(path) except OSError, e: return SFTPServer.convert_errno(e.errno)
def chattr(self, attr): if not self.user.is_sysop: return SFTP_PERMISSION_DENIED self.log.debug('chattr ({0!r})'.format(attr)) # python doesn't have equivalents to fchown or fchmod, so we have to # use the stored filename try: SFTPServer.set_file_attr(self.filename, attr) return SFTP_OK except OSError as err: return SFTPServer.convert_errno(err.errno)
def symlink(self, target_path, path): path = self._realpath(path) if (len(target_path) > 0) and (target_path[0] == '/'): # absolute symlink target_path = os.path.join(self.ROOT, target_path[1:]) try: os.symlink(target_path, path) except OSError as e: return SFTPServer.convert_errno(e.errno) return SFTP_OK
def rename(self, oldpath, newpath): if not self.user.is_sysop or flagged_dirname in path: return SFTP_PERMISSION_DENIED self.log.debug('rename({0!r}, {1!r})'.format(oldpath, newpath)) oldpath = self._realpath(oldpath) newpath = self._realpath(newpath) try: os.rename(oldpath, newpath) except OSError as err: return SFTPServer.convert_errno(err.errno) return SFTP_OK
def lstat(self, path): """ This method performs the lstat attributes for the given path path - file/folder path return lstat SFTPAttributes or error """ path = self._realpath(path) try: return SFTPAttributes.from_stat(os.lstat(path)) except OSError, e: return SFTPServer.convert_errno(e.errno)
def open(self, path, flags, attr): path = self._realpath(path) try: binary_flag = getattr(os, 'O_BINARY', 0) flags |= binary_flag mode = getattr(attr, 'st_mode', None) if mode is not None: fd = os.open(path, flags, mode) else: # os.open() defaults to 0777 which is # an odd default mode for files fd = os.open(path, flags, 1638) # 0666 except OSError: e = sys.exc_info()[1] return SFTPServer.convert_errno(e.errno) if (flags & os.O_CREAT) and (attr is not None): attr._flags &= ~attr.FLAG_PERMISSIONS SFTPServer.set_file_attr(path, attr) if flags & os.O_WRONLY: if flags & os.O_APPEND: fstr = 'ab' else: fstr = 'wb' elif flags & os.O_RDWR: if flags & os.O_APPEND: fstr = 'a+b' else: fstr = 'r+b' else: # O_RDONLY (== 0) fstr = 'rb' try: f = os.fdopen(fd, fstr) except OSError: e = sys.exc_info()[1] return SFTPServer.convert_errno(e.errno) fobj = StubSFTPHandle(flags) fobj.filename = path fobj.readfile = f fobj.writefile = f return fobj
def list_folder(self, path): path = self._realpath(path) try: out = [] flist = os.listdir(path) for fname in flist: attr = SFTPAttributes.from_stat(os.stat(os.path.join(path, fname))) attr.filename = fname out.append(attr) return out except OSError as e: return SFTPServer.convert_errno(e.errno)
def mkdir(self, path, attr): if not self.user.is_sysop or flagged_dirname in path: return SFTP_PERMISSION_DENIED self.log.debug('mkdir({0!r}, {1!r})'.format(path, attr)) path = self._realpath(path) try: os.mkdir(path) if attr is not None: SFTPServer.set_file_attr(path, attr) except OSError as err: return SFTPServer.convert_errno(err.errno) return SFTP_OK
def chattr(self, path, attr): """ This method changes the attributes of a given path path - the path attr - file attributes to be set return SFTP_OK or error """ path = self._realpath(path) try: SFTPServer.set_file_attr(path, attr) except OSError, e: return SFTPServer.convert_errno(e.errno)
def open(self, path, flags, attr): path = self._realpath(path) try: flags |= getattr(os, 'O_BINARY', 0) if getattr(attr, 'st_mode', None): fd = os.open(path, flags, attr.st_mode) else: # os.open() defaults to 0777 which is # an odd default mode for files fd = os.open(path, flags, 0666) except OSError, e: return SFTPServer.convert_errno(e.errno)
def rename(self, oldpath, newpath): """ This method renames oldpath into newpath oldpath - old file path newpath - new file path return SFTP_OK or error """ oldpath = self._realpath(oldpath) newpath = self._realpath(newpath) try: os.rename(oldpath, newpath) except OSError, e: return SFTPServer.convert_errno(e.errno)
def chattr(self, attr): """ This method performs the stat attributes for the given path path - file/folder path return path SFTPAttributes or error """ # python doesn't have equivalents to fchown or fchmod, so we have to # use the stored filename try: SFTPServer.set_file_attr(self.filename, attr) return SFTP_OK except OSError, e: return SFTPServer.convert_errno(e.errno)
def open(self, path, flags, attr): path = self._realpath(path) try: binary_flag = getattr(os, "O_BINARY", 0) flags |= binary_flag mode = getattr(attr, "st_mode", None) if mode is not None: fd = os.open(path, flags, mode) else: # os.open() defaults to 0777 which is # an odd default mode for files fd = os.open(path, flags, o666) except OSError as e: return SFTPServer.convert_errno(e.errno) if (flags & os.O_CREAT) and (attr is not None): attr._flags &= ~attr.FLAG_PERMISSIONS SFTPServer.set_file_attr(path, attr) if flags & os.O_WRONLY: if flags & os.O_APPEND: fstr = "ab" else: fstr = "wb" elif flags & os.O_RDWR: if flags & os.O_APPEND: fstr = "a+b" else: fstr = "r+b" else: # O_RDONLY (== 0) fstr = "rb" try: f = os.fdopen(fd, fstr) except OSError as e: return SFTPServer.convert_errno(e.errno) fobj = StubSFTPHandle(flags) fobj.filename = path fobj.readfile = f fobj.writefile = f return fobj
def rmdir(self, path): return SFTPServer.convert_errno(errno.E_ACCES)
def chattr(self, path, attr): return SFTPServer.convert_errno(errno.E_ACCES)
def list_folder(self, path): self.opt.o("sftpserver", 'list', path) try: return self.docker_client.listdir_attr(path) except IOError as e: return SFTPServer.convert_errno(e.errno)
def stat(self, path): self.opt.o("sftpserver", 'stat', path) try: return self.docker_client.stat(path) except IOError as e: return SFTPServer.convert_errno(e.errno)
def list_folder(self, path): logging.debug(repr(path)) out = [] try: cursor = self.mysql_conn.cursor() logging.debug("list_folder PATH: {}".format(path)) if path == "/": # This is the root path. Print a list of projects. query = """SELECT p.projectid,UNIX_TIMESTAMP(MAX(r.release_date)) FROM project_membership p JOIN project_files f ON(f.projectid = p.projectid) JOIN project_release r ON(r.releaseid = f.releaseid) WHERE p.userid=%s GROUP BY p.projectid""" cursor.execute(query, (self.userid, )) for (projectid, m_time) in cursor: attr = self._dir_attr(m_time) project = self.arv.groups().get(uuid=projectid).execute() filename = "{} ({})".format(project['name'], projectid) attr.filename = filename logging.debug("Folder attrs: {}".format(str(attr))) out.append(attr) else: parts = path.strip("/").split("/", 3) logging.debug("list_folder PARTS: {}".format(repr(parts))) parts[0] = self._get_project_id(parts[0]) logging.debug("Project ID:{}".format(parts[0])) self._is_allowed(parts[0]) if len(parts) == 1: # If there is only one part to the path then list the datatypes for the collection # Perhaps may change this to a release view? Will need to decide how to make paths within the project unique. query = """SELECT f.type,UNIX_TIMESTAMP(MAX(r.release_date)) FROM project_files f JOIN project_release r ON(f.releaseid = r.releaseid) WHERE f.projectid=%s GROUP BY f.type ORDER BY f.type""" cursor.execute(query, (str(parts[0]), )) for (filetype, mtime) in cursor: attr = self._dir_attr(mtime) attr.filename = filetype out.append(attr) else: # Otherwise find the subpath and files pathquery = "/" + ("/".join(parts[2:]) + "/" if len(parts) > 2 else "") # First check if this a real directory query = """SELECT COUNT(filename) FROM project_files WHERE projectid=%s AND type=%s AND filepath=%s""" cursor.execute(query, (str(parts[0]), str(parts[1]), pathquery)) row = cursor.fetchone() if row is None: raise OSError(errno.ENOENT, "No such directory") # First find the subdirectories and list them query = """SELECT SUBSTRING_INDEX(SUBSTR(f.filepath, LENGTH(%s)+1),'/',1) as subpath, UNIX_TIMESTAMP(MAX(r.release_date)) FROM project_files f JOIN project_release r ON(f.releaseid = r.releaseid) WHERE f.projectid=%s AND f.type=%s AND f.filepath LIKE %s AND LENGTH(f.filepath) > LENGTH(%s) GROUP BY subpath ORDER BY f.filepath""" cursor.execute(query, (pathquery, str( parts[0]), str(parts[1]), pathquery + '%', pathquery)) logging.debug(cursor.statement) for (dirname, mtime) in cursor: attr = self._dir_attr(mtime) attr.filename = dirname out.append(attr) logging.debug("DIR: {}".format(str(attr))) # Then find the files and list those query = """SELECT f.filename, UNIX_TIMESTAMP(r.release_date), f.fileid FROM project_files f JOIN project_release r ON (f.releaseid = r.releaseid) WHERE f.projectid=%s AND f.type=%s AND f.filepath=%s""" cursor.execute(query, (str(parts[0]), str(parts[1]), pathquery)) for (filename, mtime, fileid) in cursor: file_parts = fileid.split('/', 1) arv_file = self._get_file(file_parts[0], file_parts[1]) attr = self._file_attr(mtime) attr.filename = os.path.basename(filename) attr.st_size = arv_file.size() out.append(attr) logging.debug("FILE: {}".format(str(attr))) cursor.close() return out except OSError as e: return SFTPServer.convert_errno(e.errno)
def lstat(self, path): path = self._realpath(path) try: return SFTPAttributes.from_stat(os.lstat(path)) except OSError, e: return SFTPServer.convert_errno(e.errno)
def stat(self): try: return SFTPAttributes.from_stat(os.fstat(self.readfile.fileno())) except OSError, e: return SFTPServer.convert_errno(e.errno)
def readlink(self, path): path = self._realpath(path) try: symlink = os.readlink(path) except OSError, e: return SFTPServer.convert_errno(e.errno)
def chattr(self, path, attr): path = self._realpath(path) try: SFTPServer.set_file_attr(path, attr) except OSError, e: return SFTPServer.convert_errno(e.errno)
def rmdir(self, path): path = self._realpath(path) try: os.rmdir(path) except OSError, e: return SFTPServer.convert_errno(e.errno)
def open(self, path, flags, attr): path = self._realpath(path) try: fd = os.open(path, flags) except OSError, e: return SFTPServer.convert_errno(e.errno)
def _SFTPHandle_stat(self): try: return paramiko.SFTPAttributes.from_stat(os.fstat(self.readfile.fileno())) except OSError as e: return SFTPServer.convert_errno(e.errno)
def rename(self, oldpath, newpath): return SFTPServer.convert_errno(errno.E_ACCES)
def stat(self, path): try: if path == "/": cursor = self.mysql_conn.cursor() query = """SELECT UNIX_TIMESTAMP(MAX(r.release_date)) FROM project_membership p JOIN project_files f ON(f.projectid = p.projectid) JOIN project_release r ON(r.releaseid = f.releaseid) WHERE p.userid=%s""" cursor.execute(query, (self.userid, )) row = cursor.fetchone() return self._dir_attr(row[0]) else: logging.debug("stat PATH: {}".format(path)) parts = str(path).strip("/").split("/", 2) if parts[len(parts) - 1] == "..": parts.pop() parts[0] = self._get_project_id(parts[0]) logging.debug("stat PARTS: {}".format(repr(parts))) cursor = self.mysql_conn.cursor() # First check if this is a file if len(parts) > 2: parts[2] = '/' + parts[2] query = """SELECT UNIX_TIMESTAMP(r.release_date) FROM project_files f JOIN project_release r ON(r.releaseid = f.releaseid) WHERE f.projectid=%s AND f.type=%s AND CONCAT(f.filepath,f.filename)=%s""" cursor.execute(query, (parts[0], parts[1], parts[2])) row = cursor.fetchone() if cursor.with_rows and row is not None: # this is a file. Return a file attr attr = self._file_attr(row[0]) logging.debug("STAT: {}".format(repr(attr))) cursor.close() return attr logging.debug("STAT: is directory") query = """SELECT UNIX_TIMESTAMP(MAX(r.release_date)) FROM project_files f JOIN project_release r ON(r.releaseid = f.releaseid) WHERE f.projectid=%s""" if len(parts) == 3: logging.debug(repr(parts)) query = query + " AND f.type=%s AND f.filepath=%s" if not parts[2].endswith('/'): parts[2] = parts[2] + "/" cursor.execute(query, (parts[0], parts[1], parts[2])) elif len(parts) > 1: query = query + " AND f.type=%s" cursor.execute(query, (parts[0], parts[1])) else: cursor.execute(query, (parts[0], )) row = cursor.fetchone() logging.debug("STAT return: {} {}".format( repr(cursor.statement), repr(row))) if cursor.with_rows and row[0] is not None: mtime = row[0] cursor.close() return self._dir_attr(mtime) else: cursor.close() raise OSError(errno.ENOENT, "No such file or directory") except OSError as e: return SFTPServer.convert_errno(e.errno)
if flags & os.O_APPEND: fstr = 'ab' else: fstr = 'wb' elif flags & os.O_RDWR: if flags & os.O_APPEND: fstr = 'a+b' else: fstr = 'r+b' else: # O_RDONLY (== 0) fstr = 'rb' try: f = os.fdopen(fd, fstr) except OSError, e: return SFTPServer.convert_errno(e.errno) fobj = StubSFTPHandle(flags) fobj.filename = path fobj.readfile = f fobj.writefile = f return fobj def remove(self, path): path = self._realpath(path) try: os.remove(path) except OSError, e: return SFTPServer.convert_errno(e.errno) return SFTP_OK def rename(self, oldpath, newpath):
class SFTPInterface (SFTPServerInterface): def __init__(self, server): self.server = server self.user = server.user self.shares = {} self.shares_accessed = set() self.modified_date = {} for share in Share.user_queryset(self.user,include_stats=False): self.shares[share.slug_or_id] = share#{'path':share.get_realpath()} # print 'user' # print self.user # self.ROOT = root def session_ended(self): SFTPServerInterface.session_ended(self) Share.objects.filter(id__in=list(self.shares_accessed)).update(last_data_access=timezone.now()) def _get_share(self,path): parts = path.split(os.path.sep) if len(parts) < 2: print 'bad length' raise PermissionDenied("Received an invalid path: %s"%path) if not self.shares.has_key(parts[1]) and self.user.id == -1: #Anonymous users don't yet have a dictionary of shares. try: share = Share.get_by_slug_or_id(parts[1]) self.shares[share.slug_or_id] = share except: pass if not self.shares.has_key(parts[1]): print 'no share exists' print path raise PermissionDenied("Share does not exist: %s"%path[1]) return self.shares[parts[1]] def _path_modified(self,path): share = self._get_share(path) previous_date = self.modified_date.get(share.id,None) current_date = timezone.now() if not previous_date or (current_date-previous_date).seconds > SFTP_UPDATE_SHARE_MODIFIED_DATE_FREQUENCY_SECONDS: self.modified_date[share.id] = current_date Share.objects.filter(id=share.id,updated__lt=current_date).update(updated=current_date) def _get_bioshare_path_permissions(self,path): share = self._get_share(path) self.shares_accessed.add(share.id) permissions = share.get_user_permissions(self.user) # print permissions return permissions def _get_path_permissions(self,path): permissions = self._get_bioshare_path_permissions(path) #translate # PERMISSION_VIEW = 'view_share_files' # PERMISSION_DELETE = 'delete_share_files' # PERMISSION_DOWNLOAD = 'download_share_files' # PERMISSION_WRITE = 'write_to_share' # PERMISSION_LINK_TO_PATH = 'link_to_path' # PERMISSION_ADMIN return permissions def _realpath(self, path): # print 'realpath' # print path parts = path.split(os.path.sep) share = self._get_share(path) realpath = os.path.realpath(os.path.join(share.get_realpath(),os.path.sep.join(parts[2:]))) if not paths_contain(settings.DIRECTORY_WHITELIST,realpath): raise PermissionDenied("Encountered a path outside the whitelist") return realpath # print self.ROOT + self.canonicalize(path) # return self.ROOT + self.canonicalize(path) @sftp_response def list_shares(self): # print "LIST SHARES" if self.user.id == -1: return [] try: out = [] for id,share in self.shares.iteritems(): try: # print id attr = paramiko.SFTPAttributes.from_stat(os.stat(share.get_realpath())) attr.filename = id out.append(attr) except Exception, e: pass #directory may be missing return out except OSError as e: return SFTPServer.convert_errno(e.errno)
def stat(self, path): path = self._realpath(path) try: return paramiko.SFTPAttributes.from_stat(os.stat(path)) except OSError as e: return SFTPServer.convert_errno(e.errno)