diff --git a/web/pgadmin/misc/file_manager/__init__.py b/web/pgadmin/misc/file_manager/__init__.py index 4a8e709..a64ee4a 100644 --- a/web/pgadmin/misc/file_manager/__init__.py +++ b/web/pgadmin/misc/file_manager/__init__.py @@ -15,6 +15,7 @@ import random import string import time from sys import platform as _platform +import config import simplejson as json from flask import render_template, Response, session, request as req, url_for @@ -403,6 +404,20 @@ class Filemanager(object): It lists all file and folders within the given directory. """ + if dir is None: + dir = "" + try: + Filemanager.check_access_permission(dir, path) + except Exception as e: + err_msg = "Error: {0}".format(str(e)) + files = { + 'Code': -1, + 'err_msg': err_msg + } + return files + + orig_path = "{0}{1}".format(dir, path) + files = {} if (_platform == "win32" and path == '/') and dir is None: drives = Filemanager._get_drives() @@ -428,9 +443,6 @@ class Filemanager(object): } return files - if dir is None: - dir = "" - orig_path = "{0}{1}".format(dir, path) user_dir = path folders_only = trans_data['folders_only'] if 'folders_only' in \ trans_data else '' @@ -447,7 +459,7 @@ class Filemanager(object): system_path = os.path.join(os.path.join(orig_path, f)) # continue if file/folder is hidden - if (is_folder_hidden(system_path) or f.startswith('.')): + if is_folder_hidden(system_path) or f.startswith('.'): continue user_path = os.path.join(os.path.join(user_dir, f)) @@ -498,6 +510,23 @@ class Filemanager(object): } return files + @staticmethod + def check_access_permission(dir, path): + if dir is None: + dir = "" + orig_path = "{0}{1}".format(dir, path) + + # This translates path with relative path notations like ./ and ../ to + # absolute path. + orig_path = os.path.abspath(orig_path) + + # Do not allow user to access outside his storage dir in server mode. + if config.SERVER_MODE is True: + if not orig_path.startswith(dir): + raise Exception( + gettext("Access denied ({})".format(orig_path))) + return True + def validate_request(self, capability): """ It validates the capability with the capabilities @@ -515,14 +544,37 @@ class Filemanager(object): path = unquote(path) if self.dir is None: self.dir = "" + + try: + Filemanager.check_access_permission(self.dir, path) + except Exception as e: + thefile = { + 'Filename': split_path(path)[-1], + 'FileType': '', + 'Path': path, + 'Error': gettext("Error: {0}".format(str(e))), + 'Code': -1, + 'Info': '', + 'Properties': { + 'Date Created': '', + 'Date Modified': '', + 'Width': '', + 'Height': '', + 'Size': '' + } + } + return thefile + orig_path = "{0}{1}".format(self.dir, path) + user_dir = path thefile = { 'Filename': split_path(orig_path)[-1], - 'File Type': '', + 'FileType': '', 'Path': user_dir, 'Error': '', 'Code': 0, + 'Info': '', 'Properties': { 'Date Created': '', 'Date Modified': '', @@ -533,13 +585,18 @@ class Filemanager(object): } if not path_exists(orig_path): - thefile['Error'] = gettext('File does not exist.') - return (encode_json(thefile), None, 'application/json') - - if split_path(user_dir)[-1] == '/': - thefile['File Type'] = 'Directory' + thefile['Error'] = gettext("'{}' file does not exist.".format( + split_path(orig_path)[-1])) + thefile['Code'] = -1 + return thefile + + if split_path(user_dir)[-1] == '/'\ + or os.path.isfile(orig_path) is False: + thefile['FileType'] = 'Directory' + thefile['Info'] = gettext("'{}' is not a regular file.".format( + split_path(orig_path)[-1])) else: - thefile['File Type'] = splitext(user_dir) + thefile['FileType'] = splitext(user_dir) created = time.ctime(os.path.getctime(orig_path)) modified = time.ctime(os.path.getmtime(orig_path)) @@ -570,6 +627,17 @@ class Filemanager(object): } dir = self.dir if self.dir is not None else '' + + try: + Filemanager.check_access_permission(dir, old) + Filemanager.check_access_permission(dir, new) + except Exception as e: + res = { + 'Error': gettext("Error: {0}".format(str(e))), + 'Code': -1 + } + return res + # check if it's dir if old[-1] == '/': old = old[:-1] @@ -622,6 +690,16 @@ class Filemanager(object): } dir = self.dir if self.dir is not None else '' + + try: + Filemanager.check_access_permission(dir, path) + except Exception as e: + res = { + 'Error': gettext("Error: {0}".format(str(e))), + 'Code': -1 + } + return res + orig_path = "{0}{1}".format(dir, path) err_msg = '' @@ -669,6 +747,15 @@ class Filemanager(object): except Exception as e: err_msg = "Error: {0}".format(e.strerror) + try: + Filemanager.check_access_permission(dir, path) + except Exception as e: + res = { + 'Error': gettext("Error: {0}".format(str(e))), + 'Code': -1 + } + return res + result = { 'Path': path, 'Name': newName, @@ -687,13 +774,19 @@ class Filemanager(object): name = unquote(name) try: orig_path = "{0}{1}".format(dir, path) + Filemanager.check_access_permission(dir, "{}{}".format(path, name)) + newName = '{0}{1}'.format(orig_path, name) if os.path.exists(newName): code = 0 else: code = 1 except Exception as e: - err_msg = "Error: {0}".format(e.strerror) + code = -1 + if hasattr(e, 'strerror'): + err_msg = "Error: {0}".format(e.strerror) + else: + err_msg = "Error: {0}".format(str(e)) result = { 'Path': path, @@ -735,6 +828,17 @@ class Filemanager(object): dir = self.dir if self.dir is not None else '' newName = name + + try: + Filemanager.check_access_permission(dir, "{}{}".format( + path, newName)) + except Exception as e: + res = { + 'Error': gettext("Error: {0}".format(str(e))), + 'Code': -1 + } + return res + if dir != "": newPath = dir + '/' + path + newName + '/' else: @@ -776,6 +880,15 @@ class Filemanager(object): } dir = self.dir if self.dir is not None else '' + + try: + Filemanager.check_access_permission(dir, "{}{}".format( + path, path)) + except Exception as e: + resp = Response(gettext("Error: {0}".format(str(e)))) + resp.headers['Content-Disposition'] = 'attachment; filename=' + name + return resp + orig_path = "{0}{1}".format(dir, path) name = path.split('/')[-1] content = open(orig_path, 'r') diff --git a/web/pgadmin/misc/file_manager/static/css/file_manager.css b/web/pgadmin/misc/file_manager/static/css/file_manager.css index ea502ac..56d9c38 100755 --- a/web/pgadmin/misc/file_manager/static/css/file_manager.css +++ b/web/pgadmin/misc/file_manager/static/css/file_manager.css @@ -15,19 +15,17 @@ top: 35px; } -#uploader h1 { +#uploader .input-path { font-size: 14px; margin: 0; - margin-left: 5px; padding: 0; display: block; float: left; text-align: left; - line-height:1.9em; - max-width: 367px; + line-height:1.6em; + width: calc(100% - 72px); text-overflow: ellipsis; overflow: hidden; - color: #999; } #uploader h1 b { diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/index.html b/web/pgadmin/misc/file_manager/templates/file_manager/index.html index 197386f..992fe5d 100755 --- a/web/pgadmin/misc/file_manager/templates/file_manager/index.html +++ b/web/pgadmin/misc/file_manager/templates/file_manager/index.html @@ -5,13 +5,14 @@