def zip(self, path, file=None, override=None, signal=False): """ Zip file or directory ``path`` to ``file`` or to ``path + '.zip'``. On not exist raise :class:`~limited.core.files.storage.FileNotExist`. """ path = self.check(path) if not self.fs.exists(path): raise FileNotExist(u"'%s' not found" % path) if file == None: file = self.available_name(path + u".zip", override=override) if signal: file_pre_change.send(self, basedir=FilePath.dirname(path)) newfile = file + u".part" try: zfile = self.fs.open(newfile, mode='wb') archive = zipfile.ZipFile(zfile, 'w', zipfile.ZIP_DEFLATED) if self.fs.isdir(path): dirname = FilePath.name(path) for abspath, name in self.fs.listfiles(path).items(): name = FilePath.join(dirname, name) archive.write(abspath, name) elif self.fs.isfile(path): archive.write(self.fs.abspath(path), FilePath.name(path)) archive.close() zfile.seek(0) self.fs.rename(newfile, FilePath.name(file)) except EnvironmentError as e: if e.errno == errno.EACCES: raise FileError(u"IOError, zip. Permission denied '%s'" % path) finally: if self.fs.exists(newfile): self.fs.remove(newfile)
def test_storage_path(self): """ Test FilePath class """ assert FilePath.join(u"path", "name") == u"path/name" assert FilePath.join(u"/path", "name") == u"/path/name" assert FilePath.join(u"/root/path", "name") == u"/root/path/name" assert FilePath.join(u"/path/", "name") == u"/path/name" assert FilePath.join(u"/path/", "/name") == u"/path/name" assert FilePath.name(u"/path/name") == u"name" assert FilePath.name(u"/path/name") == u"name" assert FilePath.name(u"/path/name/") == u"" assert FilePath.dirname(u"/path/name/") == u"/path/name" assert FilePath.dirname(u"/path/name/file") == u"/path/name" assert FilePath.dirname(u"/path/name/file.ext") == u"/path/name" assert FilePath.norm(u"root/file.ext") == u"root/file.ext" assert FilePath.norm(u"root/base/../file.ext") == u"root/file.ext" assert FilePath.norm(u"root/base/.././file.ext") == u"root/file.ext" assert FilePath.norm(u"root/base/../../file.ext") == u"file.ext" assert FilePath.norm(u"root/./file.ext") == u"root/file.ext" assert FilePath.norm(u"root/././file.ext") == u"root/file.ext"
def move(self, src, dst): """ Move file or dir from ``src`` to ``dst``. On the same directory raise :class:`~limited.core.files.storage.FileError`. On not exist for both paths raise :class:`~limited.core.files.storage.FileNotExist`. """ name = FilePath.name(src) dst = FilePath.join(dst, name) dst = self.available_name(dst) try: shutil.move(self.abspath(src), self.abspath(dst)) except EnvironmentError as e: if e.errno == errno.EACCES: raise FileError(u"IOError, move. Permission denied '%s'" % src)
def download(self, url, path, signal=True): """ Download file from ``url`` to file ``path``. The process goes to a file ``path + '.part'``. On error file will be remove. To get file name from url use :class:`~limited.core.utils.url_get_filename`. """ path = self.check(path) path = self.fs.available_name(path) newfile = path + u".part" try: # simple hook to stop File proxy access field 'name' # that is no exists if signal: file_pre_change.send(self, basedir=FilePath.dirname(path)) data = urllib.urlopen(iri_to_uri(url)) data.size = int(data.info()['Content-Length']) self.fs.save(newfile, File(data)) self.fs.rename(newfile, FilePath.name(path)) except Exception: if self.fs.exists(newfile): self.fs.remove(newfile) raise
def UploadView( request, id ): """ Files upload to POST 'h' - home id, 'p' - path, 'files' """ if request.user.is_anonymous( ) and not settings.LIMITED_ANONYMOUS: return HttpResponseRedirect( '%s?next=%s' % (settings.LOGIN_URL, request.path) ) lib_id = int( id ) path = request.POST['p'] if not FilePath.check(path, norm=True): logger.error( u"Files. Path check fail. home_id:{0}, path:{1}".format( lib_id, path ) ) return RenderError( request, u"IOError, Permission denied" ) if request.method == u"POST": file_paths = [] try: # file paths to delete them after any Exception home = get_home( request.user, lib_id ) if not home.permission.upload: raise PermissionError( u"You have no permission to upload" ) user = get_user( request.user ) storage = home.lib.getStorage( ) files = request.FILES.getlist( u'files' ) if not len( files ): messages.warning( request, u"No any files selected" ) return HttpResponseReload( request ) for file in files: if not check_file_name( file.name ): raise PermissionError( settings.LIMITED_FILES_MESSAGE.format( file.name ) ) history = History( user=user, lib=home.lib, type=History.UPLOAD, path=path ) for file in files: fool_path = FilePath.join( path, file.name ) name = storage.save( fool_path, file ) file_paths.append( name ) history.files = [FilePath.name( i ) for i in file_paths] history.save( ) if settings.LIMITED_EMAIL_NOTIFY['ENABLE']: domain = Site.objects.get_current( ).domain link = urlbilder( u"browser", lib_id, p=history.path ) libs = Home.objects.filter( lib_id=lib_id ) users = [i.user_id for i in libs] notify = MailFileNotify( ) notify.body = u"New files upload to '{0}' by user {1}\n".format(path or '/', history.user) notify.body += u"Link http://{0}{1}&hl={2}\n".format(domain, link, history.hash()) notify.files = [i.name for i in files] notify.users = users # Hack to stay in one thread and test mail.outbox notify.run( ) if settings.TEST else notify.start( ) except ObjectDoesNotExist: logger.error( u"Upload. No such file lib or you don't have permissions. home_id:{0}".format( lib_id ) ) return RenderError( request, u"No such file lib or you don't have permissions" ) except PermissionError as e: logger.info( u"Upload. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) except Exception: for file in file_paths: if storage.exists( file ): storage.remove( file ) raise return HttpResponseReload( request )
def ActionView( request, id, command ): """ Action add, delete, rename, movem link GET 'h' - home id, 'p' - path than redirect back """ if request.user.is_anonymous( ) and not settings.LIMITED_ANONYMOUS: return HttpResponseRedirect( '%s?next=%s' % (settings.LOGIN_URL, request.path) ) lib_id = int( id ) path = request.GET.get( 'p', '' ) if not FilePath.check(path, norm=True): logger.error( u"Files. Path check fail. home_id:{0}, path:{1}".format( lib_id, path ) ) return RenderError( request, u"IOError, Permission denied" ) home = get_home( request.user, lib_id ) user = get_user( request.user ) Storage = home.lib.getStorage( ) history = History( lib=home.lib ) history.path = FilePath.dirname( path ) # GET 'n' - folder name if command == u"add": try: if not home.permission.create: raise PermissionError( u"You have no permission to create new directory" ) name = request.GET['n'] # If it link - download it # No any messages on success if name.startswith( u"http://" ) or name.startswith( u"https://" ): if not home.permission.http_get: raise PermissionError( u"You have no permission to upload from url" ) filename = url_get_filename( name ) path = FilePath.join( path, filename ) #TODO: F*****g TransactionManagementError don't now how to fix # In a Thread we set signal=False to not update DB T = Thread( ) T.setView( Storage.extra.download, name, path, signal=False ) T.run( ) if settings.TEST else T.start( ) messages.success( request, u"file '%s' added for upload" % filename ) # Just create new directory else: if u'/' in name or u'\\' in name: raise FileError( u"Not supported symbols" ) if not check_file_name( name ): raise PermissionError( u"This name of directory '{0}' is not allowed for creating!".format( name ) ) dir = FilePath.join( path, name ) Storage.mkdir( dir ) messages.success( request, u"directory '%s' successfully created" % name ) #history.message = "dir '%s' created" % name #history.type = History.CREATE #history.path = dir #history.save( ) except ( PermissionError, FileError ) as e: logger.error( u"Action add. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) # Delete from FS elif command == u"delete": try: if not home.permission.delete: raise PermissionError( u'You have no permission to delete' ) Storage.remove( path ) messages.success( request, u"'%s' successfully deleted" % FilePath.name( path ) ) history.user = user history.type = History.DELETE history.files = FilePath.name( path ) history.save( ) except ( PermissionError, FileError ) as e: logger.error( u"Action delete. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) # Move to special directory elif command == u"trash": try: if not home.permission.delete: raise PermissionError( u"You have no permission to delete" ) Storage.trash.totrash( path ) messages.success( request, u"'%s' successfully moved to trash" % FilePath.name( path ) ) history.user = user history.type = History.TRASH history.files = FilePath.name( path ) history.save( ) except ( PermissionError, FileError ) as e: logger.error( u"Action trash. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) # GET 'n' - new file name elif command == u"rename": try: if not home.permission.edit: raise PermissionError( u"You have no permission to rename" ) name = request.GET['n'] if not check_file_name( name ): raise PermissionError( u"This name '{0}' is invalided!".format( name ) ) Storage.rename( path, name ) messages.success( request, u"'%s' successfully rename to '%s'" % ( FilePath.name( path ), name) ) history.user = user history.type = History.RENAME history.files = name history.save( ) except ( PermissionError, FileError ) as e: logger.error( u"Action rename. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) # GET 'p2' - new directory path elif command == u"move": try: if not home.permission.move: raise PermissionError( u"You have no permission to move" ) path2 = request.GET['p2'] if path2[0] == u'/': path2 = path2[1:] Storage.move( path, path2 ) elif path2[0] == u'.': tmp = FilePath.join( FilePath.dirname( path ), path2 ) path2 = FilePath.norm( tmp ) Storage.move( path, path2 ) else: path2 = FilePath.join( FilePath.dirname( path ), path2 ) Storage.move( path, path2 ) messages.success( request, u"'%s' successfully moved to '%s'" % ( FilePath.name( path ), path2) ) history.user = user history.type = History.MOVE history.files = FilePath.name( path ) history.path = path2 history.save( ) except ( PermissionError, FileError ) as e: logger.error( u"Action move. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) elif command == u"link": try: domain = Site.objects.get_current( ).domain link = Link.objects.find( Link.get_hash( home.lib_id, path ) ) # if exist and not expired if link: messages.success( request, u"link already exists <a href=\"http://{0}/link/{1}\">http://{0}/link/{1}<a>".format( domain, link.hash ) ) # else create new one elif home.permission.create: link = Link.objects.add( home.lib, path ) messages.success( request, u"link successfully created to '<a href=\"http://{0}/link/{1}\">http://{0}/link/{1}<a>'".format( domain, link.hash ) ) history.user = user history.type = History.LINK history.files = FilePath.name( path ) history.extra = link.hash history.path = FilePath.dirname( path ) history.save( ) else: logger.error( u"Action link. You have no permission to create links. home_id:{0}, path:{0}".format( lib_id, path ) ) raise PermissionError( u"You have no permission to create links" ) except ( PermissionError, FileError ) as e: logger.info( u"Action link. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) elif command == u"zip": try: if not home.permission.edit: raise PermissionError( u"You have no permission to zip" ) if path.endswith( u".zip" ): Storage.extra.unzip( path ) else: Storage.extra.zip( path ) except ( PermissionError, FileError ) as e: logger.info( u"Action zip. {0}. home_id:{1}, path:{2}".format( e, lib_id, path ) ) messages.error( request, e ) elif command == u"size": size = Storage.size( path, dir=True, cached=True ) size = filesizeformat( size ) return HttpResponse( size ) return HttpResponseReload( request )