Skip to content

Commit 68f35ad

Browse files
committed
Fix 33 - migrate to setuptools
1 parent 2a64b2a commit 68f35ad

File tree

8 files changed

+130
-75
lines changed

8 files changed

+130
-75
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ application/MANIFEST
22
application/dist/*
33
application/build/*
44
extension.zip
5+
chrome_pass.egg-info

README.md

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ There are two folders in this repository that contain:
1212
and password store.
1313

1414
To use the extension you need to install the extension in your chrome or
15-
chromium browser and the python native application (nativePass).
15+
chromium browser and the python native application (chrome_pass).
1616

1717
## Requirements
1818

@@ -32,8 +32,8 @@ These instructions have been tested in Ubuntu 22.04 and later:
3232
### Python native pass application install
3333

3434
sudo apt-get install pass python3 python3-pip
35-
pip3 install --user chrome-pass==0.4.0
36-
nativePass install
35+
pip install --user chrome-pass==0.5.0
36+
chrome_pass install
3737

3838
### Chrome extension install
3939

@@ -129,12 +129,14 @@ then load the path to the *extension* folder using the *Load unpacked extension*
129129
button. After the extension is loaded into Chrome take note of the *extension
130130
ID*.
131131

132-
Next we need to install the *nativePass* wrapper script and install the Native
132+
Next we need to install the *chrome_pass* wrapper script and install the Native
133133
Host Application manifest:
134134

135135
cd application
136-
python3 setup.py install
137-
nativePass install [extension ID]
136+
pip install --upgrade setuptools build --user
137+
python -m build
138+
pip install . --user
139+
chrome_pass install [extension ID]
138140

139141
## Usage
140142

@@ -144,6 +146,26 @@ Host Application manifest:
144146
- You may type a search term in the search box to filter the list of usernames.
145147
- The form should be automatically filled with the username and corresponding password.
146148

149+
## Version 0.5.0 Notes
150+
151+
The `nativePass` script has been renamed to `chrome_pass`.
152+
153+
Version 0.5.0 of chrome-pass uses setuptools instead of distutils to package and
154+
install the native application. When installing you may get errors such as:
155+
156+
```
157+
ERROR: Cannot uninstall 'chrome-pass'. It is a distutils installed project and
158+
thus we cannot accurately determine which files belong to it which would lead
159+
to only a partial uninstall.
160+
```
161+
162+
In this situation is necessary to manually uninstall older versions of the package:
163+
164+
1. Remove `nativePass` script. Find it using `which nativePass`.
165+
2. Find where site-packages are installed (e.g.
166+
/var/lib/python3.10/site-packages) and remove all `chrome_pass-0.X.0...`
167+
files and directories.
168+
147169
## Troubleshooting
148170

149171
If for some reason the extension is unable to get the list of usernames from
@@ -157,21 +179,21 @@ your password store the most probable reasons are:
157179
passwords and username list. This file is usually located at
158180
~/.config/google-chrome/NativeMessagingHosts folder and MUST be named
159181
*com.piaotech.chrome.extension.pass.json*.
160-
- The nativePass script has a helper method to generate the native host
161-
manifest *nativePass install [extension id]* so use it to generate the
182+
- The chrome_pass script has a helper method to generate the native host
183+
manifest *chrome_pass install [extension id]* so use it to generate the
162184
manifest. If you do not give it am [extension id] it will generate the
163185
manifest with the id of the extension from the chrome web store.
164186
- Another possible issue is that the manifest contents does not match your
165187
system:
166188
- Ensure the *path* contains the absolute path to the location of the
167-
nativePass wrapper script.
189+
chrome_pass wrapper script.
168190
- Ensure the *allowed_origins* contains the URI with the exact extension ID
169191
installed in Chrome. To get the extension ID simply browse chrome:
170192
//extensions and look for the ID of the chrome-pass extension installed.
171193

172194
## Note about python-gnupg
173195

174-
It has been found that the nativePass application is unable to decrypt the gpg
196+
It has been found that the chrome_pass application is unable to decrypt the gpg
175197
passwords with some newer versions of python-gnupg. I can verify that the plugin
176198
works without issues when using gnupg module version 0.3.9 found by default in
177199
Ubuntu 16.04LTS.
Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
#!/usr/bin/env python3
1+
"""
2+
chrome_pass native application module
3+
"""
24

3-
# Requires python-gpg library
45
import os
56
import re
67
import sys
@@ -9,18 +10,20 @@
910
import shutil
1011
import difflib
1112
import pathlib
13+
import posixpath
1214
from urllib.parse import parse_qs
1315
from urllib.parse import urlparse
1416
from collections import OrderedDict
17+
from importlib.metadata import entry_points
1518
import pyotp
1619
import gnupg
1720

1821
if sys.platform == "win32":
1922
# Interacts with windows registry to register this app
20-
import winreg
23+
import winreg # pylint: disable=import-error
2124
# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY
2225
# to avoid unwanted modifications of the input/output streams.
23-
import msvcrt
26+
import msvcrt # pylint: disable=import-error
2427
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
2528
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
2629

@@ -97,13 +100,16 @@ def read_data(path):
97100
raise RuntimeError(f'Failed to decrypt {txt}')
98101

99102

100-
# Returns a dictionary with id and value pairs read from pass files that match
101-
# pattern:
102-
#
103-
# key=value
104-
#
105-
# key only matches alphanumeric characters and cannot have spaces.
106103
def get_creds(path):
104+
"""
105+
Returns a dictionary with id and value pairs read from pass files
106+
that match pattern:
107+
108+
key=value
109+
110+
key only matches alphanumeric characters and cannot have spaces.
111+
"""
112+
107113
# Read decripted pass file data.
108114
data = read_data(path).decode('utf-8').split("\n")
109115

@@ -131,17 +137,22 @@ def get_creds(path):
131137
return creds
132138

133139

134-
# Sends the response message with the format that chrome HostNativeApplications
135-
# expect.
136140
def send_message(message):
141+
"""
142+
Sends response messages in format compatible with chrome
143+
HostNativeApplications.
144+
"""
137145
response = json.dumps(message).encode('utf-8')
138146
sys.stdout.buffer.write(struct.pack('I', len(response)))
139147
sys.stdout.buffer.write(response)
140148
sys.stdout.buffer.flush()
141149

142150

143-
# Method that implements Chrome Native App protocol for messaging.
144151
def process_native():
152+
"""
153+
Method that implements Chrome Native App protocol to enable
154+
communication between chrome-pass chrome extension and pass.
155+
"""
145156
size = sys.stdin.buffer.read(4)
146157

147158
if not size:
@@ -173,21 +184,28 @@ def process_native():
173184
send_message({"action": "error", "msg": sys.exc_info()[0]})
174185

175186

176-
# Method prints to stdout the list of passwords ordered by a similarty pattern
177187
def print_list(pattern):
188+
"""
189+
Method prints to stdout the list of passwords ordered by a similarty
190+
pattern
191+
"""
178192
for credential in get_list(pattern)[:20]:
179193
print(credential)
180194

181195

182-
# Method prints to stdout the first match creds data.
183196
def print_creds(pattern):
197+
"""
198+
Method prints to stdout the first match creds data.
199+
"""
184200
for credential in get_list(pattern)[:20]:
185201
account = credential[0] + "/" + credential[2]
186202
print(f'{get_creds(account)}')
187203

188204

189-
# Determines the path were the native app manifest should be installed.
190205
def native_path_chrome():
206+
"""
207+
Determines the path were the native app manifest should be installed.
208+
"""
191209
if sys.platform == "darwin":
192210
return os.path.expanduser(
193211
'~'
@@ -228,8 +246,23 @@ def native_path_brave():
228246
sys.exit(1)
229247

230248

231-
# Installs the Native Host Application manifest for this script into Chrome.
249+
def find_chrome_pass_path():
250+
"""
251+
Convoluted function to figure out the absolute path of the chrome_pass
252+
console script.
253+
"""
254+
entry_point = entry_points().select(
255+
name='chrome_pass', group='console_scripts')[0]
256+
package_path = list(filter(
257+
lambda file: file.name == "chrome_pass",
258+
entry_point.dist.files))[0]
259+
return posixpath.abspath(package_path.locate())
260+
261+
232262
def install(native_path, extension_id):
263+
"""
264+
Installs the Native Host Application manifest for this script into Chrome.
265+
"""
233266
if sys.platform == "win32":
234267
# Appends APPDATA to native_path and set this path as a registry value
235268
reg_key = os.path.join("Software", native_path)
@@ -242,14 +275,14 @@ def install(native_path, extension_id):
242275
os.makedirs(native_path)
243276

244277
if sys.platform == "win32":
245-
batch = "python \"{}\" %*".format(os.path.realpath(__file__))
278+
batch = f"python \"{os.path.realpath(__file__)}\" %*"
246279
native_app = EXTENSION_NAME + '.bat'
247280
outfile = os.path.join(native_path, native_app)
248281
with open(outfile, 'w', encoding="utf-8") as file:
249282
file.write("@echo off\n\n")
250283
file.write(batch)
251284
else:
252-
native_app = os.path.realpath(__file__)
285+
native_app = find_chrome_pass_path()
253286

254287
manifest = OrderedDict()
255288
manifest['name'] = EXTENSION_NAME
@@ -264,22 +297,23 @@ def install(native_path, extension_id):
264297
json.dump(manifest, file, indent='\t')
265298

266299

267-
if len(sys.argv) > 1:
268-
if sys.argv[1].startswith('chrome-extension://'):
269-
process_native()
270-
elif sys.argv[1] == "install":
271-
if len(sys.argv) > 2:
272-
install(native_path_chrome(), sys.argv[2])
273-
install(native_path_chromium(), sys.argv[2])
274-
install(native_path_brave(), sys.argv[2])
300+
def run():
301+
if len(sys.argv) > 1:
302+
if sys.argv[1].startswith('chrome-extension://'):
303+
process_native()
304+
elif sys.argv[1] == "install":
305+
if len(sys.argv) > 2:
306+
install(native_path_chrome(), sys.argv[2])
307+
install(native_path_chromium(), sys.argv[2])
308+
install(native_path_brave(), sys.argv[2])
309+
else:
310+
install(native_path_chrome(), EXTENSION_ID)
311+
install(native_path_chromium(), EXTENSION_ID)
312+
install(native_path_brave(), EXTENSION_ID)
313+
elif sys.argv[1] == "pass":
314+
if len(sys.argv) > 2:
315+
print_creds(sys.argv[2])
316+
elif sys.argv[1] == "gpgbin":
317+
print(f"GPG Binary path: {get_gpg_bin()}")
275318
else:
276-
install(native_path_chrome(), EXTENSION_ID)
277-
install(native_path_chromium(), EXTENSION_ID)
278-
install(native_path_brave(), EXTENSION_ID)
279-
elif sys.argv[1] == "pass":
280-
if len(sys.argv) > 2:
281-
print_creds(sys.argv[2])
282-
elif sys.argv[1] == "gpgbin":
283-
print(f"GPG Binary path: {get_gpg_bin()}")
284-
else:
285-
print_list(sys.argv[1])
319+
print_list(sys.argv[1])
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""
2+
Console script main
3+
"""
4+
from . import run
5+
6+
if __name__ == '__main__':
7+
run()
7.93 KB
Binary file not shown.
272 Bytes
Binary file not shown.

application/pyproject.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[build-system]
2+
requires = ["setuptools"]
3+
build-backend = "setuptools.build_meta"
4+
[project]
5+
name = "chrome_pass"
6+
version = "0.5.0"
7+
authors = [
8+
{name = "Horacio Sanson", email = "hsanson@gmail.com"},
9+
]
10+
description = "Native application for chrome-pass extension"
11+
requires-python = ">=3.8"
12+
keywords = ["pass", "chrome"]
13+
license = {text = "MIT"}
14+
dependencies = [
15+
"python-gnupg",
16+
"pyotp"
17+
]
18+
[project.scripts]
19+
chrome_pass = "chrome_pass:run"

application/setup.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)