From a6d1cb14f51989892ad036c9e0220f728000ac06 Mon Sep 17 00:00:00 2001 From: Yonathan Negussie Mengesha Date: Fri, 10 Aug 2018 02:42:52 +0200 Subject: [PATCH 1/4] CHANGED: check if the user is logged in already CHANGED: fix 'status_message' references - it is part of the 'Window' class --- Perforce.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Perforce.py b/Perforce.py index 25b9522..7d3401d 100644 --- a/Perforce.py +++ b/Perforce.py @@ -20,6 +20,7 @@ # global variable used when calling p4 - it stores the path of the file in the current view, used to determine with P4CONFIG to use # whenever a view is selected, the variable gets updated + global_folder = '' class PerforceP4CONFIGHandler(sublime_plugin.EventListener): @@ -331,7 +332,7 @@ def WarnUser(message): perforce_settings = sublime.load_settings('Perforce.sublime-settings') if(perforce_settings.get('perforce_warnings_enabled')): if(perforce_settings.get('perforce_log_warnings_to_status')): - sublime.status_message("Perforce [warning]: {0}".format(message)) + sublime.active_window().status_message("Perforce [warning]: {0}".format(message)) else: print("Perforce [warning]: {0}".format(message)) @@ -666,7 +667,7 @@ def on_done(self, picked): entry = applications.get('applications')[picked] f.close() - sublime.status_message(__name__ + ': Please make sure that {0} is reachable - you might need to restart Sublime Text 2.'.format(entry['exename'])) + self.window.status_message(__name__ + ': Please make sure that {0} is reachable - you might need to restart Sublime Text 2.'.format(entry['exename'])) settings = sublime.load_settings('Perforce.sublime-settings') settings.set('perforce_selectedgraphicaldiffapp', entry['name']) @@ -1076,6 +1077,15 @@ def run(self): class PerforceLoginCommand(sublime_plugin.WindowCommand): def run(self): + # first check if logged in already + user = GetUserFromClientspec() + command = ConstructCommand("p4 login -s {0}".format(user)) + p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) + p.communicate() + if not p.returncode: + self.window.status_message("{0} already logged in.".format(user)) + return + self.window.show_input_panel("Enter Perforce Password", "", self.on_done, None, None) def on_done(self, password): From 605033af0350e5446065a1cef14e4bf3af680604 Mon Sep 17 00:00:00 2001 From: Yonathan Negussie Mengesha Date: Wed, 15 Aug 2018 01:13:57 +0200 Subject: [PATCH 2/4] CHANGED: use ticket-based authentication instead of P4PASSWD for login --- Perforce.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Perforce.py b/Perforce.py index 7d3401d..2bd564a 100644 --- a/Perforce.py +++ b/Perforce.py @@ -1090,13 +1090,11 @@ def run(self): def on_done(self, password): try: - command = ConstructCommand("p4 logout") + command = ConstructCommand("p4 login") p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) - p.communicate() - #unset var - command = ConstructCommand("p4 set P4PASSWD={0}".format(password)) - p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) - p.communicate() + p.communicate(input=password.encode('utf-8')) + if p.returncode: + self.window.status_message("login failed!") except ValueError: pass From c372933278feeffa1f2facf1a47d1d2569dd6f47 Mon Sep 17 00:00:00 2001 From: Yonathan Negussie Mengesha Date: Wed, 15 Aug 2018 01:38:21 +0200 Subject: [PATCH 3/4] CHANGED: use ticket-based authentication instead of P4PASSWD for logout --- Perforce.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Perforce.py b/Perforce.py index 2bd564a..d324bd3 100644 --- a/Perforce.py +++ b/Perforce.py @@ -1069,7 +1069,7 @@ def run(self): class PerforceLogoutCommand(sublime_plugin.WindowCommand): def run(self): try: - command = ConstructCommand("p4 set P4PASSWD=") + command = ConstructCommand("p4 logout") p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) p.communicate() except ValueError: From bbe1a526dc0102f1851dfb98f5747fe47afb6136 Mon Sep 17 00:00:00 2001 From: Yonathan Negussie Mengesha Date: Thu, 16 Aug 2018 04:15:48 +0200 Subject: [PATCH 4/4] CHANGED: unset P4PASSWD as well during logout ADDED: masked password input for login --- Perforce.py | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/Perforce.py b/Perforce.py index d324bd3..d2bc382 100644 --- a/Perforce.py +++ b/Perforce.py @@ -1072,10 +1072,21 @@ def run(self): command = ConstructCommand("p4 logout") p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) p.communicate() + + # if password authenticated + command = ConstructCommand("p4 set P4PASSWD=") + p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) + p.communicate() + except ValueError: pass +maskChar = '*' + class PerforceLoginCommand(sublime_plugin.WindowCommand): + inputPanel = None + clearPassword = [] + def run(self): # first check if logged in already user = GetUserFromClientspec() @@ -1086,18 +1097,47 @@ def run(self): self.window.status_message("{0} already logged in.".format(user)) return - self.window.show_input_panel("Enter Perforce Password", "", self.on_done, None, None) + self.inputPanel = self.window.show_input_panel("Enter Perforce Password", "", self.on_done, self.on_change, None) + + def isMasked(self, text): + return all(ch == maskChar for ch in text) + + def on_change(self, password): + for i, c in enumerate(password): + if c != maskChar: + self.clearPassword.insert(i, c) + + if self.inputPanel: + # check for cases when user only makes deletions from the fully masked input + if self.isMasked(password) and len(password) < len(self.clearPassword): + sel = self.inputPanel.sel() + if sel: + # get current caret position + pos = sel[0].a + self.clearPassword.pop(pos) + + if not self.isMasked(password): + self.inputPanel.run_command("mask_input") def on_done(self, password): try: command = ConstructCommand("p4 login") p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) - p.communicate(input=password.encode('utf-8')) + p.communicate(input="".join(self.clearPassword).encode('utf-8')) if p.returncode: - self.window.status_message("login failed!") + self.window.status_message("login failed.") + else: + self.window.status_message("login successful.") + self.clearPassword.clear() except ValueError: pass +class MaskInputCommand(sublime_plugin.TextCommand): + def run(self, edit): + size = self.view.size() + toBeReplaced = sublime.Region(0, size) + self.view.replace(edit, toBeReplaced, size * maskChar) + class PerforceUnshelveClCommand(sublime_plugin.WindowCommand): def run(self): try: