Skip to content

Commit 4c47c87

Browse files
committed
anti_password.py 1.2.2: fix linter errors, add typing, reformat script, remove history, add SPDX copyright and license tags
1 parent e5c761e commit 4c47c87

2 files changed

Lines changed: 105 additions & 117 deletions

File tree

REUSE.toml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -673,12 +673,6 @@ SPDX-FileCopyrightText = [
673673
]
674674
SPDX-License-Identifier = "MIT"
675675

676-
[[annotations]]
677-
path = "python/anti_password.py"
678-
precedence = "override"
679-
SPDX-FileCopyrightText = "2021 Sébastien Helleu <flashcode@flashtux.org>"
680-
SPDX-License-Identifier = "GPL-3.0-or-later"
681-
682676
[[annotations]]
683677
path = "python/apply_corrections.py"
684678
precedence = "override"

python/anti_password.py

Lines changed: 105 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#
2-
# Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
2+
# SPDX-FileCopyrightText: 2021-2026 Sébastien Helleu <flashcode@flashtux.org>
3+
#
4+
# SPDX-License-Identifier: GPL-3.0-or-later
35
#
46
# This program is free software; you can redistribute it and/or modify
57
# it under the terms of the GNU General Public License as published by
@@ -18,214 +20,206 @@
1820
# Prevent a password from being accidentally sent to a buffer
1921
# (requires WeeChat ≥ 0.4.0 and WeeChat ≥ 3.1 to check secured data).
2022
#
21-
# History:
22-
#
23-
# 2021-03-13, Sébastien Helleu <flashcode@flashtux.org>:
24-
# version 1.2.1: simplify regex condition
25-
# 2021-03-12, Sébastien Helleu <flashcode@flashtux.org>:
26-
# version 1.2.0: add option "allowed_regex"
27-
# 2021-02-26, Sébastien Helleu <flashcode@flashtux.org>:
28-
# version 1.1.0: add options "check_secured_data" and "max_rejects"
29-
# 2021-02-24, Sébastien Helleu <flashcode@flashtux.org>:
30-
# version 1.0: first official version
3123

3224
"""Anti password script."""
3325

3426
import re
3527

28+
IMPORT_OK = True
29+
3630
try:
37-
import weechat
38-
IMPORT_OK = True
31+
import weechat # type: ignore[import]
3932
except ImportError:
40-
print('This script must be run under WeeChat.')
41-
print('Get WeeChat now at: https://weechat.org/')
33+
print("This script must be run under WeeChat.")
34+
print("Get WeeChat now at: https://weechat.org/")
4235
IMPORT_OK = False
4336

44-
SCRIPT_NAME = 'anti_password'
45-
SCRIPT_AUTHOR = 'Sébastien Helleu <flashcode@flashtux.org>'
46-
SCRIPT_VERSION = '1.2.1'
47-
SCRIPT_LICENSE = 'GPL3'
48-
SCRIPT_DESC = 'Prevent a password from being accidentally sent to a buffer'
37+
SCRIPT_NAME = "anti_password"
38+
SCRIPT_AUTHOR = "Sébastien Helleu <flashcode@flashtux.org>"
39+
SCRIPT_VERSION = "1.2.2"
40+
SCRIPT_LICENSE = "GPL3"
41+
SCRIPT_DESC = "Prevent a password from being accidentally sent to a buffer"
4942

5043
# script options
51-
ap_settings_default = {
52-
'allowed_regex': {
53-
'default': '^(http|https|ftp|file|irc)://',
54-
'help': (
55-
'allowed regular expression (case is ignored); this is checked '
56-
'first: if the input matched this regular expression, it is '
57-
'considered safe and sent immediately to the buffer; '
58-
'if empty, nothing specific is allowed'
44+
AP_SETTINGS_DEFAULT = {
45+
"allowed_regex": {
46+
"default": "^(http|https|ftp|file|irc)://",
47+
"help": (
48+
"allowed regular expression (case is ignored); this is checked "
49+
"first: if the input matched this regular expression, it is "
50+
"considered safe and sent immediately to the buffer; "
51+
"if empty, nothing specific is allowed"
5952
),
6053
},
61-
'password_condition': {
62-
'default': (
63-
'${words} == 1 && ${lower} >= 1 && ${upper} >= 1 '
64-
'&& ${digits} >= 1 && ${special} >= 1'
54+
"password_condition": {
55+
"default": (
56+
"${words} == 1 && ${lower} >= 1 && ${upper} >= 1 "
57+
"&& ${digits} >= 1 && ${special} >= 1"
6558
),
66-
'help': (
67-
'condition evaluated to check if the input string is a password; '
68-
'allowed variables: '
69-
'${words} = number of words, '
70-
'${lower} = number of lower case letters, '
71-
'${upper} = number of upper case letters, '
72-
'${digits} = number of digits, '
73-
'${special} = number of other chars (not letter/digits/spaces), '
59+
"help": (
60+
"condition evaluated to check if the input string is a password; "
61+
"allowed variables: "
62+
"${words} = number of words, "
63+
"${lower} = number of lower case letters, "
64+
"${upper} = number of upper case letters, "
65+
"${digits} = number of digits, "
66+
"${special} = number of other chars (not letter/digits/spaces), "
7467
),
7568
},
76-
'check_secured_data': {
77-
'default': 'equal',
78-
'help': (
79-
'consider that all secured data values are passwords and can not '
80-
'be sent to buffers, possible values: '
81-
'off = do not check secured data at all, '
82-
'equal = reject input if stripped input is equal to a secured '
83-
'data value, '
84-
'include = reject input if a secured data value is part of input'
69+
"check_secured_data": {
70+
"default": "equal",
71+
"help": (
72+
"consider that all secured data values are passwords and can not "
73+
"be sent to buffers, possible values: "
74+
"off = do not check secured data at all, "
75+
"equal = reject input if stripped input is equal to a secured "
76+
"data value, "
77+
"include = reject input if a secured data value is part of input"
8578
),
8679
},
87-
'max_rejects': {
88-
'default': '3',
89-
'help': (
90-
'max number of rejects for a given input text; if you press Enter '
91-
'more than N times with exactly the same input, the text is '
92-
'finally sent to the buffer; '
93-
'if set to 0, the input is never sent to the buffer when it is '
94-
'considered harmful (be careful, according to the other settings, '
95-
'this can completely block the input)'
80+
"max_rejects": {
81+
"default": "3",
82+
"help": (
83+
"max number of rejects for a given input text; if you press Enter "
84+
"more than N times with exactly the same input, the text is "
85+
"finally sent to the buffer; "
86+
"if set to 0, the input is never sent to the buffer when it is "
87+
"considered harmful (be careful, according to the other settings, "
88+
"this can completely block the input)"
9689
),
9790
},
9891
}
9992
ap_settings = {}
10093
ap_reject = {
101-
'input': '',
102-
'count': 0,
94+
"input": "",
95+
"count": 0,
10396
}
10497

10598

106-
def ap_config_cb(data, option, value):
99+
def ap_config_cb(_data: str, option: str, value: str) -> int:
107100
"""Called when a script option is changed."""
108-
pos = option.rfind('.')
101+
pos = option.rfind(".")
109102
if pos > 0:
110-
name = option[pos+1:]
103+
name = option[pos + 1 :]
111104
if name in ap_settings:
112105
ap_settings[name] = value
113106
return weechat.WEECHAT_RC_OK
114107

115108

116-
def ap_input_is_secured_data(input_text):
109+
def ap_input_is_secured_data(input_text: str) -> bool:
117110
"""Check if input_text is any value of a secured data."""
118-
check = ap_settings['check_secured_data']
119-
if check == 'off':
111+
check = ap_settings["check_secured_data"]
112+
if check == "off":
120113
return False
121-
sec_data = weechat.info_get_hashtable('secured_data', {}) or {}
122-
if check == 'include':
114+
sec_data = weechat.info_get_hashtable("secured_data", {}) or {}
115+
if check == "include":
123116
for value in sec_data.values():
124117
if value and value in input_text:
125118
return True
126-
if check == 'equal':
119+
if check == "equal":
127120
return input_text.strip() in sec_data.values()
128121
return False
129122

130123

131-
def ap_input_matches_condition(input_text):
124+
def ap_input_matches_condition(input_text: str) -> bool:
132125
"""Check if input_text matches the password condition."""
133126
# count chars in the input text
134-
words = len(list(filter(None, re.split(r'\s+', input_text))))
127+
words = len(list(filter(None, re.split(r"\s+", input_text))))
135128
lower = sum(1 for c in input_text if c.islower())
136129
upper = sum(1 for c in input_text if c.isupper())
137130
digits = sum(1 for c in input_text if c.isdigit())
138131
special = sum(1 for c in input_text if not (c.isalnum() or c.isspace()))
139132

140133
# evaluate password condition
141134
extra_vars = {
142-
'words': str(words),
143-
'lower': str(lower),
144-
'upper': str(upper),
145-
'digits': str(digits),
146-
'special': str(special),
135+
"words": str(words),
136+
"lower": str(lower),
137+
"upper": str(upper),
138+
"digits": str(digits),
139+
"special": str(special),
147140
}
148141
ret = weechat.string_eval_expression(
149-
ap_settings['password_condition'],
142+
ap_settings["password_condition"],
150143
{},
151144
extra_vars,
152-
{'type': 'condition'},
145+
{"type": "condition"},
153146
)
154-
return ret == '1'
147+
return ret == "1"
155148

156149

157-
def ap_input_is_password(input_text):
150+
def ap_input_is_password(input_text: str) -> bool:
158151
"""Check if input_text looks like a password."""
159-
return (ap_input_is_secured_data(input_text)
160-
or ap_input_matches_condition(input_text))
152+
return ap_input_is_secured_data(input_text) or ap_input_matches_condition(
153+
input_text
154+
)
161155

162156

163-
def ap_input_return_cb(data, buf, command):
157+
def ap_input_return_cb(_data: str, buf: str, _command: str) -> int:
164158
"""Callback called when Return key is pressed in a buffer."""
165159
try:
166-
max_rejects = int(ap_settings['max_rejects'])
160+
max_rejects = int(ap_settings["max_rejects"])
167161
except ValueError:
168162
max_rejects = 3
169163

170-
input_text = weechat.buffer_get_string(buf, 'input')
164+
input_text = weechat.buffer_get_string(buf, "input")
171165

172166
# check if input is a command
173167
if not weechat.string_input_for_buffer(input_text):
174168
# commands are ignored
175-
ap_reject['input'] = ''
176-
ap_reject['count'] = 0
169+
ap_reject["input"] = ""
170+
ap_reject["count"] = 0
177171
return weechat.WEECHAT_RC_OK
178172

179173
# check if input matches the allowed regex
180-
regex = ap_settings['allowed_regex']
174+
regex = ap_settings["allowed_regex"]
181175
if regex and re.search(regex, input_text, re.IGNORECASE):
182176
# allowed regex
183-
ap_reject['input'] = ''
184-
ap_reject['count'] = 0
177+
ap_reject["input"] = ""
178+
ap_reject["count"] = 0
185179
return weechat.WEECHAT_RC_OK
186180

187181
if ap_input_is_password(input_text):
188-
if ap_reject['input'] == input_text:
189-
if ap_reject['count'] >= max_rejects > 0:
182+
if ap_reject["input"] == input_text:
183+
if ap_reject["count"] >= max_rejects > 0:
190184
# it looks like a password but send anyway after N rejects
191-
ap_reject['input'] = ''
192-
ap_reject['count'] = 0
185+
ap_reject["input"] = ""
186+
ap_reject["count"] = 0
193187
return weechat.WEECHAT_RC_OK
194-
ap_reject['count'] += 1
188+
ap_reject["count"] += 1
195189
else:
196-
ap_reject['input'] = input_text
197-
ap_reject['count'] = 1
190+
ap_reject["input"] = input_text
191+
ap_reject["count"] = 1
198192
# password detected, do NOT send it to the buffer!
199193
return weechat.WEECHAT_RC_OK_EAT
200194

201195
# not a password
202-
ap_reject['input'] = ''
203-
ap_reject['count'] = 0
196+
ap_reject["input"] = ""
197+
ap_reject["count"] = 0
204198
return weechat.WEECHAT_RC_OK
205199

206200

207-
def main():
201+
def main() -> None:
208202
"""Main function."""
209-
if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION,
210-
SCRIPT_LICENSE, SCRIPT_DESC, '', ''):
203+
if weechat.register(
204+
SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""
205+
):
211206
# set default settings
212-
for name, option in ap_settings_default.items():
207+
for name, option in AP_SETTINGS_DEFAULT.items():
213208
if weechat.config_is_set_plugin(name):
214209
ap_settings[name] = weechat.config_get_plugin(name)
215210
else:
216-
weechat.config_set_plugin(name, option['default'])
217-
ap_settings[name] = option['default']
211+
weechat.config_set_plugin(name, option["default"])
212+
ap_settings[name] = option["default"]
218213
weechat.config_set_desc_plugin(
219-
name,
220-
'%s (default: "%s")' % (option['help'], option['default']))
214+
name, f'{option["help"]} (default: "{option["default"]}")'
215+
)
221216

222217
# detect config changes
223-
weechat.hook_config('plugins.var.python.%s.*' % SCRIPT_NAME,
224-
'ap_config_cb', '')
218+
weechat.hook_config(f"plugins.var.python.{SCRIPT_NAME}.*", "ap_config_cb", "")
225219

226220
# hook Return key
227-
weechat.hook_command_run('/input return', 'ap_input_return_cb', '')
221+
weechat.hook_command_run("/input return", "ap_input_return_cb", "")
228222

229223

230-
if __name__ == '__main__' and IMPORT_OK:
224+
if __name__ == "__main__" and IMPORT_OK:
231225
main()

0 commit comments

Comments
 (0)