From 1cb2a62fa8cc130fcc6a64b5aa4f16e85cb397b6 Mon Sep 17 00:00:00 2001 From: Murtuza Zabuawala Date: Mon, 15 May 2017 13:01:12 +0100 Subject: [PATCH] Ensure object names are properly escaped for external process management. Fixes #2405 --- .../misc/bgprocess/static/js/bgprocess.js | 2 +- web/pgadmin/tools/backup/__init__.py | 48 ++++++++++++++----- web/pgadmin/tools/import_export/__init__.py | 23 +++++---- web/pgadmin/utils/html.py | 14 +++++- 4 files changed, 64 insertions(+), 23 deletions(-) diff --git a/web/pgadmin/misc/bgprocess/static/js/bgprocess.js b/web/pgadmin/misc/bgprocess/static/js/bgprocess.js index cccd6a2f0..f88aa2926 100644 --- a/web/pgadmin/misc/bgprocess/static/js/bgprocess.js +++ b/web/pgadmin/misc/bgprocess/static/js/bgprocess.js @@ -310,7 +310,7 @@ define([ panel = this.panel = pgBrowser.BackgroundProcessObsorver.create_panel(); - panel.title('Process Watcher - ' + self.desc); + panel.title('Process Watcher - ' + _.escape(self.desc)); panel.focus(); } diff --git a/web/pgadmin/tools/backup/__init__.py b/web/pgadmin/tools/backup/__init__.py index 7afacfdbb..9c0537a4f 100644 --- a/web/pgadmin/tools/backup/__init__.py +++ b/web/pgadmin/tools/backup/__init__.py @@ -95,7 +95,7 @@ class BackupMessage(IProcessDesc): x = x.replace('"', '\\"') x = x.replace('""', '\\"') - return ' "' + x + '"' + return ' "' + x + '"' return '' for arg in _args: @@ -113,18 +113,26 @@ class BackupMessage(IProcessDesc): if self.backup_type == BACKUP.OBJECT: return _( - "Backing up an object on the server '{0}' from database '{1}'..." + "Backing up an object on the server '{0}' " + "from database '{1}'..." ).format( - "{0} ({1}:{2})".format(s.name, s.host, s.port), + "{0} ({1}:{2})".format( + s.name, s.host, s.port + ), self.database ) if self.backup_type == BACKUP.GLOBALS: - return _("Backing up the global objects on the server '{0}'...").format( - "{0} ({1}:{2})".format(s.name, s.host, s.port) + return _("Backing up the global objects on " + "the server '{0}'...").format( + "{0} ({1}:{2})".format( + s.name, s.host, s.port + ) ) elif self.backup_type == BACKUP.SERVER: return _("Backing up the server '{0}'...").format( - "{0} ({1}:{2})".format(s.name, s.host, s.port) + "{0} ({1}:{2})".format( + s.name, s.host, s.port + ) ) else: # It should never reach here. @@ -140,18 +148,32 @@ class BackupMessage(IProcessDesc): if self.backup_type == BACKUP.OBJECT: res += _( - "Backing up an object on the server '{0}' from database '{1}'..." + "Backing up an object on the server '{0}' " + "from database '{1}'..." ).format( - "{0} ({1}:{2})".format(s.name, s.host, s.port), - self.database + "{0} ({1}:{2})".format( + html.safe_str(s.name), + html.safe_str(s.host), + html.safe_str(s.port), + ), + html.safe_str(self.database) ) elif self.backup_type == BACKUP.GLOBALS: - res += _("Backing up the global objects on the server '{0}'...").format( - "{0} ({1}:{2})".format(s.name, s.host, s.port) + res += _("Backing up the global objects on " + "the server '{0}'...").format( + "{0} ({1}:{2})".format( + html.safe_str(s.name), + html.safe_str(s.host), + html.safe_str(s.port) + ) ) elif self.backup_type == BACKUP.SERVER: res += _("Backing up the server '{0}'...").format( - "{0} ({1}:{2})".format(s.name, s.host, s.port) + "{0} ({1}:{2})".format( + html.safe_str(s.name), + html.safe_str(s.host), + html.safe_str(s.port) + ) ) else: # It should never reach here. @@ -160,7 +182,7 @@ class BackupMessage(IProcessDesc): res += '
' res += _("Running command:") res += '
' - res += self.cmd + res += html.safe_str(self.cmd) res += '
' return res diff --git a/web/pgadmin/tools/import_export/__init__.py b/web/pgadmin/tools/import_export/__init__.py index dae1793e8..4c1ac043d 100644 --- a/web/pgadmin/tools/import_export/__init__.py +++ b/web/pgadmin/tools/import_export/__init__.py @@ -94,10 +94,9 @@ class IEMessage(IProcessDesc): arg = cmdArg(arg) if _storage is not None: arg = arg.replace(_storage, '') - self._cmd += ' "' + arg + '"' + self._cmd += ' "' + arg + '"' else: - self._cmd+= cmdArg(arg) - + self._cmd += cmdArg(arg) @property def message(self): @@ -107,7 +106,8 @@ class IEMessage(IProcessDesc): ).first() return _( - "Copying table data '{0}.{1}' on database '{2}' and server ({3}:{4})..." + "Copying table data '{0}.{1}' on database '{2}' " + "and server ({3}:{4})..." ).format( self.schema, self.table, self.database, s.host, s.port ) @@ -120,16 +120,23 @@ class IEMessage(IProcessDesc): res = '
' res += _( - "Copying table data '{0}.{1}' on database '{2}' for the server '{3}'..." + "Copying table data '{0}.{1}' on database '{2}' " + "for the server '{3}'..." ).format( - self.schema, self.table, self.database, - "{0} ({1}:{2})".format(s.name, s.host, s.port) + html.safe_str(self.schema), + html.safe_str(self.table), + html.safe_str(self.database), + "{0} ({1}:{2})".format( + html.safe_str(s.name), + html.safe_str(s.host), + html.safe_str(s.port) + ) ) res += '
' res += _("Running command:") res += '
' - res += self._cmd + res += html.safe_str(self._cmd) res += '
' return res diff --git a/web/pgadmin/utils/html.py b/web/pgadmin/utils/html.py index 66a888b01..4f23d0dc7 100644 --- a/web/pgadmin/utils/html.py +++ b/web/pgadmin/utils/html.py @@ -15,7 +15,19 @@ from pgadmin.utils import IS_PY2 def safe_str(x): try: - x = x.encode('ascii', 'xmlcharrefreplace') if hasattr(x, 'encode') else x + # For Python2, it can be int, long, float + if IS_PY2: + if isinstance(x, (int, long, float)): + x = str(x) + else: + # For Python3, it can be int, float + if isinstance(x, (int, float)): + x = str(x) + + x = x.encode( + 'ascii', 'xmlcharrefreplace' + ) if hasattr(x, 'encode') else x + if not IS_PY2: x = x.decode('utf-8') except: