我正在编写一个简单的插件,它:
.crypt
的文件,提示输入密码在下面的代码中,加密方法很简单:password
是整数,并且加密移位+password
的每个字符;解密会移动-password
的每个字符(即,将password
减去每个字符的值)。这不是真正的加密也不是安全的方法;当然,以后我将用AES加密或类似的方法代替它,但是在此示例中,这足以说明我在此问题中遇到的问题。
import sublime_plugin, sublime
password = None
class PromptCryptCommand(sublime_plugin.WindowCommand):
def run(self):
panel = self.window.show_input_panel("Enter password", "2", self.on_done, None, None)
def on_done(self, pwd):
global password
password = int(pwd)
self.window.run_command(action)
class EncryptCommand(sublime_plugin.TextCommand):
def run(self, edit):
region = sublime.Region(0, self.view.size())
plaintext = self.view.substr(region)
ciphertext = ''.join([chr(ord(c)+password) for c in plaintext])
self.view.replace(edit, region, ciphertext)
class DecryptCommand(sublime_plugin.TextCommand):
def run(self, edit):
region = sublime.Region(0, self.view.size())
ciphertext = self.view.substr(region)
plaintext = ''.join([chr(ord(c)-password) for c in ciphertext])
self.view.replace(edit, region, plaintext)
class LoadSaveListener(sublime_plugin.EventListener):
def on_load(self, view):
global action
if view.file_name().endswith(".crypt"):
action = 'decrypt'
view.window().run_command('prompt_crypt')
def on_pre_save(self, view):
global action
if view.file_name().endswith(".crypt"):
if password == None: # password not entered yet, let's prompt for it
action = 'encrypt'
view.window().run_command('prompt_crypt')
else: # password already asked when file was loaded,
view.window().run_command('encrypt')
我遇到了这些我不知道如何解决的问题:
我用CTRL + S重新保存了多次,文件被重新保存,即被重新加密。例如:
plaintext = 'abc'
password = 2
after one CTRL+S, content = 'cde'
after one more CTRS+S, content = 'efg'
after one more CTRS+S, content = 'ghi' etc.
我尝试用def on_post_save(view):
和restore解决未保存的纯文本,然后进行保存操作。确实可以,但是即使保存了文件且未进行任何更改,Sublime 认为文件已修改也可以! (因为未加密的纯文本已替换文件的已保存加密版本)。
当加载.crypt
文件时,密文显示在编辑器窗口中,如何隐藏该密文,直到在提示中输入密码?
view
与磁盘上的文件关联,并且应直接跟踪任何修改。因此,尝试使用未出现在文件中的内容来表示与该文件关联的view
的内容是有问题的。尽管不是那么无缝,但是像命令一样,它会在后台自己加密保存(这将保留两个文件)并捕获视图的内容,然后关闭视图并从中重新创建原始文件以及Sublime期望事情如何运作。
我尝试使用def on_post_save(view):
解决此问题,并在保存操作后恢复未加密的纯文本。这样做是可行的,但是,即使保存了文件且未进行任何更改,Sublime仍认为文件已修改! (因为未加密的纯文本已替换文件的已保存加密版本)。
对缓冲区进行任何形式的修改都将其标记为dirty
,这就是这种情况的原因。只有两件事可以从文件中删除此状态。
其中最明显的是save
命令;一旦Sublime将数据持久保存到磁盘,它就会从文件中删除dirty
标志,
另一种方法是使用view
将view.set_scratch(True)
标记为草稿视图;临时视图根本不显示任何修改状态,因此您可以使用它暂时关闭表示文件已修改的标记。
与此相关的问题是,一旦文件被标记为scratch
,无论您进行了多少更改,它都将永远不会显示为已修改。另外,这只会阻止Sublime将状态渲染为脏状态;一旦删除暂存状态,脏状态将返回(即使视图处于暂存模式时view.is_dirty()
将返回False
。)>
您可以通过以下方法在某种程度上解决此问题:将视图设置为scratch
,然后对其应用视图设置,并使on_modified
事件侦听器仅在启用该视图设置时触发,并删除scratch
状态(和设置),以便在您进行修改之前,缓冲区看起来没有被修改。
这并非没有问题;例如,您可以通过用纯文本替换文件的加密版本的操作来撤消操作,这可能是不希望的。
这里的另一种选择是通过手动将文件写入磁盘而不是让Sublime替您完成文件加密来节省文件的加密;在这种情况下,您完全可以控制,不需要更改缓冲区的内容,因此只有在本应为脏的情况下它才会脏。不利的一面是,它将留下未加密版本的文件(尽管您可以根据需要将其删除on_close
)。
当加载.crypt文件时,密文会显示在编辑器窗口中,如何隐藏该密文,直到在提示中输入密码?执行此操作的一种方法是,准备一种具有相同前景和背景字符的配色方案,并覆盖
color_scheme
中的view
设置,直到输入密码后,您才能将其删除。这将隐藏数据。
一种替代方法是从文件中捕获数据,然后使用view.close()
关闭选项卡(例如,您可能还需要捕获其他信息,例如文件名)。然后,您将能够创建一个新的空视图,并使用解密的数据填充它(尽管您仍然需要执行与上述相同的技巧,以使其看起来不会变脏。