Hi Dave,

Please find updated attached patch for RM1911 (V2)

-- 
*Harshal Dhumal*
*Software Engineer*

EnterpriseDB India: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

On Mon, Nov 21, 2016 at 7:48 PM, Dave Page <dp...@pgadmin.org> wrote:

> Hi
>
> On Sat, Nov 19, 2016 at 5:57 PM, Harshal Dhumal
> <harshal.dhu...@enterprisedb.com> wrote:
> > 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.
>
> I did a quick check on Mac, in server mode and immediately hit problems:
>
> - [Screenshot 1]: I typed in "/Foo2" to navigate into the Foo2
> directory. a) it didn't navigate as expected, and b) it gave me a very
> non-user friendly error message.
>
> Fixed.

> - [Screenshot 2]: I typed in "foo2.sql". It added the leading /
> automatically, then gave the error dpagefoo2.sql does not exist.
>
> Fixed.

> Then on Windows in desktop mode:
>
> - [Screenshot 3]: I typed in "C:\Users\dpage" (which does exist) and
> got the error shown.
>
> Fixed.

> - [Screenshot 4]: I typed in "\\172.16.253.235\data" (which does
> exist) and got the error shown.
>
Fixed.

>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: 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..74f37fc 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
@@ -244,12 +245,12 @@ class Filemanager(object):
             {
                 'Error': gettext('No permission to operate on \
                                   specified path.'),
-                'Code': -1
+                'Code': 0
             }
         )
         self.dir = get_storage_directory()
 
-        if (self.dir is not None and isinstance(self.dir, list)):
+        if self.dir is not None and isinstance(self.dir, list):
             self.dir = ""
 
     @staticmethod
@@ -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': 0,
+                'Error': 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))
@@ -494,10 +506,27 @@ class Filemanager(object):
                 err_msg = "Error: {0}".format(e)
             files = {
                 'Code': 0,
-                'err_msg': err_msg
+                'Error': err_msg
             }
         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': 0,
+                '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,
+            'Code': 1,
+            'Info': '',
             'Properties': {
                 'Date Created': '',
                 'Date Modified': '',
@@ -533,13 +585,16 @@ 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'
         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))
@@ -566,10 +621,21 @@ class Filemanager(object):
         if not self.validate_request('rename'):
             return {
                 'Error': gettext('Not allowed'),
-                'Code': 1
+                'Code': 0
             }
 
         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': 0
+            }
+            return res
+
         # check if it's dir
         if old[-1] == '/':
             old = old[:-1]
@@ -594,8 +660,8 @@ class Filemanager(object):
         code = 1
         try:
             os.rename(oldpath_sys, newpath_sys)
-            code = 0
         except Exception as e:
+            code = 0
             error_msg = "{0} {1}".format(
                 gettext('There was an error renaming the file:'),
                 str(e))
@@ -618,10 +684,20 @@ class Filemanager(object):
         if not self.validate_request('delete'):
             return {
                 'Error': gettext('Not allowed'),
-                'Code': 1
+                'Code': 0
             }
 
         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': 0
+            }
+            return res
+
         orig_path = "{0}{1}".format(dir, path)
 
         err_msg = ''
@@ -629,11 +705,10 @@ class Filemanager(object):
         try:
             if os.path.isdir(orig_path):
                 os.rmdir(orig_path)
-                code = 0
             else:
                 os.remove(orig_path)
-                code = 0
         except Exception as e:
+            code = 0
             err_msg = "Error: {0}".format(e.strerror)
 
         result = {
@@ -651,7 +726,7 @@ class Filemanager(object):
         if not self.validate_request('upload'):
             return {
                 'Error': gettext('Not allowed'),
-                'Code': 1
+                'Code': 0
             }
 
         dir = self.dir if self.dir is not None else ''
@@ -665,10 +740,19 @@ class Filemanager(object):
 
             with open(newName, 'wb') as f:
                 f.write(thefile.read())
-            code = 0
         except Exception as e:
+            code = 0
             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': 0
+            }
+            return res
+
         result = {
             'Path': path,
             'Name': newName,
@@ -687,13 +771,17 @@ 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):
+            if not os.path.exists(newName):
                 code = 0
-            else:
-                code = 1
         except Exception as e:
-            err_msg = "Error: {0}".format(e.strerror)
+            code = 0
+            if hasattr(e, 'strerror'):
+                err_msg = "Error: {0}".format(e.strerror)
+            else:
+                err_msg = "Error: {0}".format(str(e))
 
         result = {
             'Path': path,
@@ -730,11 +818,22 @@ class Filemanager(object):
         if not self.validate_request('create'):
             return {
                 'Error': gettext('Not allowed'),
-                'Code': 1
+                'Code': 0
             }
 
         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': 0
+            }
+            return res
+
         if dir != "":
             newPath = dir + '/' + path + newName + '/'
         else:
@@ -745,15 +844,15 @@ class Filemanager(object):
         if not path_exists(newPath):
             try:
                 os.mkdir(newPath)
-                code = 0
             except Exception as e:
+                code = 0
                 err_msg = "Error: {0}".format(e.strerror)
         else:
             newPath, newName = self.getNewName(dir, path, newName)
             try:
                 os.mkdir(newPath)
-                code = 0
             except Exception as e:
+                code = 0
                 err_msg = "Error: {0}".format(e.strerror)
 
         result = {
@@ -772,10 +871,19 @@ class Filemanager(object):
         if not self.validate_request('download'):
             return {
                 'Error': gettext('Not allowed'),
-                'Code': 1
+                'Code': 0
             }
 
         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..0410337 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'
               };
@@ -514,7 +526,7 @@ define([
                 async: false,
                 success: function(resp) {
                   data = resp.data.result;
-                  if(data['Code'] === 0) {
+                  if(data['Code'] === 1) {
                     is_exist = true;
                   } else {
                     is_exist = false;
@@ -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..b0aadc2 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() {
@@ -320,7 +325,7 @@ var setUploader = function(path) {
         var d = new Date(); // to prevent IE cache issues
         $.getJSON(fileConnector + '?mode=addfolder&path=' + $('.currentpath').val() + '&name=' + foldername, function(resp) {
           var result = resp.data.result;
-          if (result.Code === 0) {
+          if (result.Code === 1) {
             alertify.success(lg.successful_added_folder);
             getFolderInfo(result.Parent);
           } else {
@@ -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();
 };
 
@@ -468,7 +471,7 @@ var renameItem = function(data) {
         async: false,
         success: function(resp) {
           var result = resp.data.result;
-          if (result.Code === 0) {
+          if (result.Code === 1) {
             var newPath = result['New Path'],
                 newName = result['New Name'],
                 title = $("#preview h1").attr("title");
@@ -532,7 +535,7 @@ var deleteItem = function(data) {
       async: false,
       success: function(resp) {
         var result = resp.data.result;
-        if (result.Code === 0) {
+        if (result.Code === 1) {
           isDeleted = true;
           if (isDeleted) {
             alertify.success(lg.successful_delete);
@@ -580,11 +583,11 @@ 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);
+  setUploader(file, '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 +602,8 @@ var getFileInfo = function(file) {
     async: false,
     success: function(resp) {
       var data = resp.data.result;
-
-      if (data.Code === 0) {
+      if (data.Code === 1) {
+        $('.file_manager_ok').removeClass('disabled');
         var properties = '';
         if (
           data.Properties.Size || parseInt(data.Properties.Size)==0
@@ -611,11 +614,24 @@ var getFileInfo = function(file) {
         }
         data.Capabilities = capabilities;
         bindToolbar(data);
+        if (data.FileType == 'Directory') {
+          // Enable/Disable level up button
+          enab_dis_level_up();
+          $('.file_manager_ok').addClass('disabled');
+
+          $('.file_manager button.delete, .file_manager button.rename').attr('disabled', 'disabled');
+          $('.file_manager button.download').attr('disabled', 'disabled');
+          getFolderInfo(file);
+        } else {
+          is_file_valid = true;
+        }
       } else {
+        $('.file_manager_ok').addClass('disabled');
         alertify.error(data.Error);
       }
     }
   });
+  return is_file_valid;
 };
 
 /*
@@ -623,11 +639,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,16 +689,16 @@ 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;
 
       // hide activity indicator
       $('.fileinfo').find('span.activity').hide();
       if (data.Code === 0) {
-        alertify.error(data.err_msg);
+        alertify.error(data.Error);
         return;
       }
-
       // generate HTML for files/folder and render into container
       if (!_.isEmpty(data)) {
         if ($('.fileinfo').data('view') == 'grid') {
@@ -1038,15 +1055,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 +1089,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 +1110,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 +1133,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,27 +1143,19 @@ 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);
           }
         });
 
         $('.fileinfo table#contents tbody tr').on('dblclick', function(e) {
           e.stopPropagation();
-
           // Enable/Disable level up button
           enab_dis_level_up();
 
@@ -1174,13 +1172,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 +1237,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 +1295,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 +1392,101 @@ $('.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 {
+              if(check) {
+                // Enable/Disable level up button
+                enab_dis_level_up();
+                $('.file_manager_ok').addClass('disabled');
+
+                $('.file_manager button.delete, .file_manager button.rename').attr('disabled', 'disabled');
+                $('.file_manager button.download').attr('disabled', 'disabled');
+                getFolderInfo(path);
+              }
+            }
+          } 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();
+        var path = $(this).val();
+        if(config.options.platform_type != "win32" && path.startsWith('/') == false) {
+            path  = '/' + path;
+            $(this).val(path);
+        }
+        setTimeout(function() {
+          check_obj(path, 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;
@@ -1495,7 +1568,7 @@ if (has_capability(data, 'upload')) {
         var data = response.data.result,
             $this = $(file.previewTemplate);
 
-        if (data.Code == 0) {
+        if (data.Code == 1) {
           setTimeout(function() {
             $this.find(".dz-upload").addClass("success");
           }, 1000);
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