Hi,

PFA for RM1911

Feature added: Allow user add file/folder path directly in input field.
Other improvements like clean up after file manager is closed.

-- 
*Harshal Dhumal*
*Software Engineer*

EnterpriseDB India: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
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 @@
 </head>
 <body>
 <div class="file_manager">
-    <form id="uploader" method="post" class='col-xs-12'>
+    <div id="uploader" class='col-xs-12'>
         <div class="btn-group filemanager-path-group col-sm-7 col-xs-12" role="group">
             <button name="home" type="button" value="Home" title="Home" class="fa fa-home btn home"><span></span>
             </button>
             <button name="level-up" type="button" title="Back" value="LevelUp" class="btn fa fa-level-up level-up"
                     disabled><span></span></button>
-            <h1 title=''></h1>
+            <input class='input-path' title='' type="text"/>
+
         </div>
         <div class="btn-group filemanager-btn-group" role="group">
             <div class="uploadresponse"></div>
@@ -29,7 +30,7 @@
             <button class="ON fa fa-th btn grid" type="button" title="View as grid"><span></span></button>
             <button type="button" class="btn fa fa-list list" title="View as Table"><span></span></button>
         </div>
-    </form>
+    </div>
     <div class="fileinfo">
     <span class="activity">
       <img src="{{ url_for('browser.static', filename='css/aciTree/image/load-root.gif') }}">
diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager.js b/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager.js
index 473a05f..164c2fa 100644
--- a/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager.js
+++ b/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager.js
@@ -81,6 +81,7 @@ define([
           return {
             main: function(params) {
               // Set title and button name
+              var self = this;
               if (_.isUndefined(params['dialog_title'])) {
                 params['dialog_title'] = 'Storage manager';
               }
@@ -96,6 +97,9 @@ define([
               renderStoragePanel(params);
               this.elements.dialog.style.minWidth = '630px';
               this.show();
+              $($container.find('.file_manager')).on('enter-key', function() {
+                $($(self.elements.footer).find('.file_manager_ok')).trigger('click')
+              });
             },
             settings: {
               label: undefined
@@ -133,19 +137,18 @@ define([
             },
             callback: function(closeEvent) {
               if (closeEvent.button.text == "{{ _('Select') }}") {
-                if($('.fileinfo').data('view') == 'grid') {
-                  sel_file = $('.fileinfo').find('#contents li.selected p span').attr('title');
-                } else {
-                  sel_file = $('.fileinfo tbody tr.selected td p span').attr('title');
-                }
-                var newFile = $('.currentpath').val() + sel_file;
+                var newFile = $('.storage_dialog #uploader .input-path').val();
 
                 pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:storage_dialog', newFile);
+                var innerbody = $(this.elements.body).find('.storage_content')
+                $(innerbody).find('*').off();
+                innerbody.remove();
+                removeTransId(trans_id);
               } else if (closeEvent.button.text == "{{ _('Cancel') }}") {
-                if (removeTransId(trans_id)) {
-                  this.destroy();
-                  return;
-                }
+                var innerbody = $(this.elements.body).find('.storage_content')
+                $(innerbody).find('*').off();
+                innerbody.remove();
+                removeTransId(trans_id);
               }
             },
             build: function() {
@@ -195,6 +198,7 @@ define([
           return {
             main: function(params) {
               // Set title and button name
+              var self = this;
               if (_.isUndefined(params['dialog_title'])) {
                 params['dialog_title'] = 'Select file';
               }
@@ -210,6 +214,9 @@ define([
               renderStoragePanel(params);
               this.elements.dialog.style.minWidth = '630px';
               this.show();
+              $($container.find('.file_manager')).on('enter-key', function() {
+                $($(self.elements.footer).find('.file_manager_ok')).trigger('click')
+              });
             },
             settings: {
               label: undefined
@@ -249,20 +256,18 @@ define([
             },
             callback: function(closeEvent) {
               if (closeEvent.button.text == "{{ _('Select') }}") {
-                if($('.fileinfo').data('view') == 'grid') {
-                  sel_file = $('.fileinfo').find('#contents li.selected  p span').attr('title');
-                } else {
-                  sel_file = $('.fileinfo tbody tr.selected td p span').attr('title');
-                }
-                var newFile = $('.currentpath').val() + sel_file;
+                var newFile = $('.storage_dialog #uploader .input-path').val();
 
                 pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:select_file', newFile);
+                var innerbody = $(this.elements.body).find('.storage_content')
+                $(innerbody).find('*').off();
+                innerbody.remove();
                 removeTransId(trans_id);
               } else if (closeEvent.button.text == "{{ _('Cancel') }}") {
-                if (removeTransId(trans_id)) {
-                  this.destroy();
-                  return;
-                }
+                var innerbody = $(this.elements.body).find('.storage_content')
+                $(innerbody).find('*').off();
+                innerbody.remove();
+                removeTransId(trans_id);
               }
             },
             build: function() {
@@ -311,6 +316,7 @@ define([
           // Dialog property
           return {
             main: function(params) {
+              var self = this;
               // Set title and button name
               if (_.isUndefined(params['dialog_title'])) {
                 params['dialog_title'] = 'Select folder';
@@ -327,6 +333,9 @@ define([
               renderStoragePanel(params);
               this.elements.dialog.style.minWidth = '630px';
               this.show();
+              $($container.find('.file_manager')).on('enter-key', function() {
+                $($(self.elements.footer).find('.file_manager_ok')).trigger('click')
+              });
             },
             settings: {
               label: undefined
@@ -366,20 +375,18 @@ define([
             },
             callback: function(closeEvent) {
               if (closeEvent.button.text == "{{ _('Select') }}") {
-                if($('.fileinfo').data('view') == 'grid') {
-                  sel_file = $('.fileinfo').find('#contents li.selected p span').attr('title');
-                } else {
-                  sel_file = $('.fileinfo tbody tr.selected td p span').attr('title');
-                }
-                var newFile = $('.currentpath').val() + sel_file;
+                var newFile = $('.storage_dialog #uploader .input-path').val();
 
                 pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:select_folder', newFile);
+                var innerbody = $(this.elements.body).find('.storage_content')
+                $(innerbody).find('*').off();
+                innerbody.remove();
                 removeTransId(trans_id);
               } else if (closeEvent.button.text == "{{ _('Cancel') }}") {
-                if (removeTransId(trans_id)) {
-                  this.destroy();
-                  return;
-                }
+                var innerbody = $(this.elements.body).find('.storage_content')
+                $(innerbody).find('*').off();
+                innerbody.remove();
+                removeTransId(trans_id);
               }
             },
             build: function() {
@@ -427,7 +434,8 @@ define([
           // Dialog property
           return {
             main: function(params) {
-              var trans_id;
+              var self = this,
+                  trans_id;
               // Set title and button name
               if (_.isUndefined(params['dialog_title'])) {
                 params['dialog_title'] = 'Create file';
@@ -444,6 +452,9 @@ define([
               renderStoragePanel(params);
               this.elements.dialog.style.minWidth = '630px';
               this.show();
+              $($container.find('.file_manager')).on('enter-key', function() {
+                $($(self.elements.footer).find('.file_manager_ok')).trigger('click')
+              });
             },
             settings: {
               label: undefined
@@ -485,8 +496,7 @@ define([
                 $('.replace_file, .fm_dimmer').show();
                 $('.replace_file .btn_yes').click(function(self) {
                   $('.replace_file, .fm_dimmer').hide();
-                  var selected_item = $('.allowed_file_types .create_input input[type="text"]').val(),
-                      newFile = $('.currentpath').val() + selected_item;
+                  var newFile = $('.storage_dialog #uploader .input-path').val()
 
                   pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:create_file', newFile);
                   $('.file_manager_create_cancel').trigger('click');
@@ -496,11 +506,13 @@ define([
                 });
             },
             is_file_exist: function() {
-              var selected_item = $('.allowed_file_types .create_input input[type="text"]').val(),
+              var full_path  = $('.storage_dialog #uploader .input-path').val(),
+                  path = full_path.substr(0, full_path.lastIndexOf('/') + 1),
+                  selected_item = full_path.substr(full_path.lastIndexOf('/') + 1),
                   is_exist = false;
 
               var file_data = {
-                'path': $('.currentpath').val(),
+                'path': path,
                 'name': selected_item,
                 'mode': 'is_file_exist'
               };
@@ -525,22 +537,23 @@ define([
             },
             callback: function(closeEvent) {
               if (closeEvent.button.text == "{{ _('Create') }}") {
-                var selected_item = $('.allowed_file_types .create_input input[type="text"]').val();
-                var newFile = $('.currentpath').val() + selected_item;
+                var newFile = $('.storage_dialog #uploader .input-path').val();
 
-                if(!_.isUndefined(selected_item) && selected_item !== '' && this.is_file_exist()) {
+                if(!_.isUndefined(newFile) && newFile !== '' && this.is_file_exist()) {
                   this.replace_file();
                   closeEvent.cancel = true;
-                }
-                else {
+                } else {
                   pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:create_file', newFile);
+                  var innerbody = $(this.elements.body).find('.storage_content')
+                  $(innerbody).find('*').off();
+                  innerbody.remove();
                   removeTransId(trans_id);
                 }
               } else if (closeEvent.button.text == "{{ _('Cancel') }}") {
-                if (removeTransId(trans_id)) {
-                  this.destroy();
-                  return;
-                }
+                var innerbody = $(this.elements.body).find('.storage_content')
+                $(innerbody).find('*').off();
+                innerbody.remove();
+                removeTransId(trans_id);
               }
             },
             build: function() {
diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/js/utility.js b/web/pgadmin/misc/file_manager/templates/file_manager/js/utility.js
index f1a5ef4..d37abfa 100755
--- a/web/pgadmin/misc/file_manager/templates/file_manager/js/utility.js
+++ b/web/pgadmin/misc/file_manager/templates/file_manager/js/utility.js
@@ -188,7 +188,7 @@ var hideButtons = function() {
  * to the path specified. Called on initial page load and
  * whenever a new directory is selected.
  */
-var setUploader = function(path) {
+var setUploader = function(path, type) {
   $('.storage_dialog #uploader').find('a').remove();
   $('.storage_dialog #uploader').find('b').remove();
 
@@ -213,15 +213,20 @@ var setUploader = function(path) {
   Object.keys(split_path).forEach(function (i) {
     file_path += split_path[i] + '/';
   });
-  $('.storage_dialog #uploader h1').html(file_path);
+
+  if (type == 'file' && file_path.charAt(file_path.length - 1) == '/') {
+    file_path = file_path.substring(0, file_path.length - 1);
+    path = file_path.substr(0, file_path.lastIndexOf('/') + 1);
+  }
+  $('.storage_dialog #uploader .input-path').val(file_path);
 
   $('.currentpath').val(path);
   if ($('.storage_dialog #uploader h1 span').length === 0) {
     $('<span>'+lg.current_folder+'</span>').appendTo($('.storage_dialog #uploader h1'));
   }
 
-  $('.storage_dialog #uploader h1').attr('title', display_string);
-  $('.storage_dialog #uploader h1').attr('data-path', display_string);
+  $('.storage_dialog #uploader .input-path').attr('title', display_string);
+  $('.storage_dialog #uploader .input-path').attr('data-path', display_string);
 
   // create new folder
   $('.create').unbind().click(function() {
@@ -414,7 +419,6 @@ var enable_disable_btn = function() {
     $('.file_manager').find('button.download').prop('disabled', true);
     $('.file_manager').find('button.rename').prop('disabled', true);
     if ($grid_file.length > 0) {
-      $('.create_input input[type="text"]').val('');
       $('.file_manager_ok').addClass('disabled');
     }
   } else {
@@ -424,14 +428,13 @@ var enable_disable_btn = function() {
     $('.file_manager').find('button.download').prop('disabled', true);
     $('.file_manager').find('button.rename').prop('disabled', true);
     if ($list_file.length > 0) {
-      $('.create_input input[type="text"]').val('');
       $('.file_manager_ok').addClass('disabled');
     }
   }
 
   $('.delete_item').hide();
   // clear address bar
-  $('.file_manager #uploader h1').show();
+  $('.file_manager #uploader .input-path').show();
   $('.file_manager #uploader .show_selected_file').remove();
 };
 
@@ -580,11 +583,12 @@ var getDetailView = function(path) {
  */
 var getFileInfo = function(file) {
   // Update location for status, upload, & new folder functions.
-  var currentpath = file.substr(0, file.lastIndexOf('/') + 1);
-  setUploader(currentpath);
+  var currentpath = file;
+  setUploader(currentpath, 'file');
 
   // Retrieve the data & populate the template.
-  var d = new Date(); // to prevent IE cache issues
+  var d = new Date(), // to prevent IE cache issues
+    is_file_valid =  false;
   var post_data = {
         'path': file,
         'mode': 'getinfo'
@@ -599,8 +603,8 @@ var getFileInfo = function(file) {
     async: false,
     success: function(resp) {
       var data = resp.data.result;
-
       if (data.Code === 0) {
+        $('.file_manager_ok').removeClass('disabled');
         var properties = '';
         if (
           data.Properties.Size || parseInt(data.Properties.Size)==0
@@ -611,11 +615,18 @@ var getFileInfo = function(file) {
         }
         data.Capabilities = capabilities;
         bindToolbar(data);
+        if (data.FileType != 'Directory') {
+          is_file_valid = true;
+        } else {
+          alertify.error(data.Info);
+        }
       } else {
+        $('.file_manager_ok').addClass('disabled');
         alertify.error(data.Error);
       }
     }
   });
+  return is_file_valid;
 };
 
 /*
@@ -623,11 +634,12 @@ var getFileInfo = function(file) {
  * creates a list view.
  */
 var getFolderInfo = function(path, file_type) {
+  $('.storage_dialog #uploader .input-path').prop('disabled', true);
   if (!file_type) {
     file_type = '';
   }
   // Update location for status, upload, & new folder functions.
-  setUploader(path);
+  setUploader(path, 'dir');
 
   // set default selected file type
   if (file_type === '') {
@@ -672,6 +684,7 @@ var getFolderInfo = function(path, file_type) {
     contentType: "application/json; charset=utf-8",
     async: false,
     success: function(resp) {
+      $('.storage_dialog #uploader .input-path').prop('disabled', false);
       var result = '',
           data = resp.data.result;
 
@@ -1038,15 +1051,11 @@ var getFolderInfo = function(path, file_type) {
           if (path.lastIndexOf("/") == path.length - 1) {
             $('.file_manager_ok').addClass('disabled');
 
-            var $create_input = $('.create_input input[type="text"]');
-
             $('.file_manager button.delete, .file_manager button.rename').attr('disabled', 'disabled');
             $('.file_manager button.download').attr('disabled', 'disabled');
 
             getFolderInfo(path);
-            if ($create_input.length != 0 && $create_input.val() != '') {
-              $('.file_manager_ok').removeClass('disabled');
-            }
+
           } else {
             getFileInfo(path);
           }
@@ -1076,7 +1085,7 @@ var getFolderInfo = function(path, file_type) {
                 'disabled', 'disabled'
               );
               // set selected folder name in breadcrums
-              $('.file_manager #uploader h1').hide();
+              $('.file_manager #uploader .input-path').hide();
               $('.file_manager #uploader .show_selected_file').remove();
               $('<span class="show_selected_file">'+path+'</span>').appendTo(
                 '.file_manager #uploader .filemanager-path-group'
@@ -1097,13 +1106,6 @@ var getFolderInfo = function(path, file_type) {
               $('.file_manager #uploader .show_selected_file').remove();
             }
 
-            if (
-              config.options.dialog_type == 'create_file' &&
-              is_protected == undefined
-            ) {
-              $('.create_input input[type="text"]').val(file_name);
-              $('.file_manager_ok, .file_manager_create').removeClass('disabled');
-            }
             getFileInfo(path);
           }
         });
@@ -1127,7 +1129,7 @@ var getFolderInfo = function(path, file_type) {
               $('.file_manager button.delete, .file_manager button.rename').removeAttr('disabled');
 
               // set selected folder name in breadcrums
-              $('.file_manager #uploader h1').hide();
+              $('.file_manager #uploader .input-path').hide();
               $('.file_manager #uploader .show_selected_file').remove();
               $('<span class="show_selected_file">'+path+'</span>').appendTo(
                 '.file_manager #uploader .filemanager-path-group'
@@ -1137,20 +1139,13 @@ var getFolderInfo = function(path, file_type) {
             if (has_capability(data_cap, 'select_file') && is_protected == undefined) {
               $(this).parent().find('tr.selected').removeClass('selected');
               $('td:first-child', this).parent().addClass('selected');
-              $('.file_manager_ok').removeClass('disabled');
               $('.file_manager button.delete, .file_manager button.download, .file_manager button.rename').removeAttr(
                 'disabled'
               );
               // set selected folder name in breadcrums
               $('.file_manager #uploader .show_selected_file').remove();
             }
-            if (
-              config.options.dialog_type == 'create_file' &&
-              is_protected == undefined
-            ) {
-              $('.create_input input[type="text"]').val(file_name);
-              $('.file_manager_ok, .file_manager_create').removeClass('disabled');
-            }
+
             getFileInfo(path);
           }
         });
@@ -1174,13 +1169,17 @@ var getFolderInfo = function(path, file_type) {
         });
 
       }
+      input_object.set_cap(data_cap);
+    },
+    error: function() {
+      $('.storage_dialog #uploader .input-path').prop('disabled', false);
     }
   });
 };
 
 // Enable/Disable level up button
 var enab_dis_level_up = function() {
-  $('.file_manager #uploader h1').show();
+  $('.file_manager #uploader .input-path').show();
   $('.show_selected_file').remove();
 
   setTimeout(function() {
@@ -1235,6 +1234,7 @@ var fileRoot = config.options.fileRoot,
  * Get localized messages from file
  * through culture var or from URL
  */
+
 var lg = [],
     enjs = '{{ url_for("file_manager.index") }}' + "en.js",
     lgf = loadData(enjs);
@@ -1292,23 +1292,6 @@ if (
   });
 }
 
-if (config.options.dialog_type == 'create_file') {
-  var create_file_html = '<div class="create_input">'+
-      '<span>Filename:</span>'+
-      '<input type="text" name="new_filename" class="fm_create_input form-control" />'+
-    '</div>';
-
-  $('.create_mode_dlg').find('.allowed_file_types').prepend(create_file_html);
-  $('.create_input input[type="text"]').on('keypress, keydown', function() {
-    var input_text_len = $(this).val().length;
-    if (input_text_len > 0 ) {
-      $('.file_manager_ok').removeClass('disabled');
-    } else {
-      $('.file_manager_ok').addClass('disabled');
-    }
-  });
-}
-
 /*---------------------------------------------------------
   Item Actions - Object events
 ---------------------------------------------------------*/
@@ -1406,14 +1389,84 @@ $('.file_manager .list').click(function() {
 });
 
 // Provide initial values for upload form, status, etc.
-setUploader(fileRoot);
-
-$('#uploader').attr('action', fileConnector);
+setUploader(fileRoot, 'dir');
 
 var data = {
   'Capabilities': capabilities
 };
 
+function InputObject() {
+  this.init= function(cap) {
+    var self = this,
+        check_obj = function(path, check) {
+          var path = decodeURI(path);
+
+          if (path.lastIndexOf('/') == path.length - 1) {
+            if (
+              has_capability(self.data_cap, 'select_folder')
+            ) {
+              $('.file_manager_ok').removeClass('disabled');
+              $('.file_manager button.delete, .file_manager button.rename').removeAttr(
+                'disabled', 'disabled'
+              );
+              $('.file_manager button.download').attr(
+                'disabled', 'disabled'
+              );
+              // set selected folder name in breadcrums
+              $('.file_manager #uploader .input-path').hide();
+              $('.file_manager #uploader .show_selected_file').remove();
+              $('<span class="show_selected_file">'+path+'</span>').appendTo(
+                '.file_manager #uploader .filemanager-path-group'
+              );
+            } else {
+              $('.file_manager_ok').addClass('disabled');
+            }
+          } else {
+            if (
+              has_capability(self.data_cap, 'select_file')
+            ) {
+              $('.file_manager_ok').removeClass('disabled');
+              $('.file_manager button.delete, .file_manager button.download, .file_manager button.rename').removeAttr(
+                'disabled'
+              );
+              // set selected folder name in breadcrums
+              $('.file_manager #uploader .show_selected_file').remove();
+            }
+
+            if(check) {
+              if (config.options.dialog_type == 'create_file') {
+                $('.file_manager').trigger('enter-key');
+                return;
+              }
+              if(config.options.dialog_type == 'select_file') {
+                var file_status = getFileInfo(path);
+                if (file_status) {
+                  $('.file_manager').trigger('enter-key');
+                }
+              }
+            }
+          }
+        };
+
+    self.data_cap = cap;
+
+    $('.storage_dialog #uploader .input-path').keyup(function(e) {
+      if(e.keyCode == 13) {
+        e.stopPropagation();
+        check_obj($(this).val(), true);
+        return;
+      }
+      check_obj($(this).val(), false);
+    });
+  }
+  this.set_cap = function(cap) {
+    this.data_cap = cap;
+  }
+}
+
+var input_object = new InputObject()
+input_object.init(data);
+
 // Upload file
 if (has_capability(data, 'upload')) {
   Dropzone.autoDiscover = false;
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index 4e1efd5..ec10459 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -8,8 +8,6 @@
 ##########################################################################
 
 """A blueprint module implementing the sqleditor frame."""
-MODULE_NAME = 'sqleditor'
-
 import simplejson as json
 import os
 import pickle
@@ -26,7 +24,9 @@ from pgadmin.utils.ajax import make_json_response, bad_request, \
 from pgadmin.utils.driver import get_driver
 from pgadmin.utils.sqlautocomplete.autocomplete import SQLAutoComplete
 
-from config import PG_DEFAULT_DRIVER
+from config import PG_DEFAULT_DRIVER, SERVER_MODE
+
+MODULE_NAME = 'sqleditor'
 
 # import unquote from urlib for python2.x and python3.x
 try:
@@ -1267,6 +1267,17 @@ def save_file():
             storage_manager_path,
             unquote(file_data['file_name'].lstrip('/'))
         )
+
+    try:
+        # Do not allow user to access outside his storage dir in server mode.
+        if SERVER_MODE is True:
+            orig_path = os.path.abspath(file_path)
+            if not orig_path.startswith(storage_manager_path):
+                raise Exception(
+                    gettext("Access denied ({})".format(orig_path)))
+    except Exception as e:
+        return internal_server_error(errormsg=str(e))
+
     file_content = file_data['file_content']
 
     # write to file
-- 
Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to