Skip to content

Commit

Permalink
Merge pull request #4 from shugaoye/master
Browse files Browse the repository at this point in the history
Release 1.1.4
  • Loading branch information
passxyz authored Apr 10, 2021
2 parents bbfd50b + 5691e30 commit 79c8d20
Show file tree
Hide file tree
Showing 12 changed files with 232 additions and 91 deletions.
22 changes: 22 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,26 @@ A Dockr image -
`docker-mono <https://github.com/shugaoye/docker-mono>`__ can be used on
Linux or Windows 10 (WSL).

Issues
------
On Windows platform, you may get the below error message:
::

Unhandled exception in event loop:
File "c:\users\kpclibpy\appdata\local\programs\python\python38-32\lib\asyncio\proactor_events.py", line 768, in _loop_self_reading
f.result() # may raise
File "c:\users\kpclibpy\appdata\local\programs\python\python38-32\lib\asyncio\windows_events.py", line 808, in _poll
value = callback(transferred, key, ov)
File "c:\users\kpclibpy\appdata\local\programs\python\python38-32\lib\asyncio\windows_events.py", line 457, in finish_recv
raise ConnectionResetError(*exc.args)

Exception [WinError 995] The I/O operation has been aborted because of either a thread exit or an application request
Press ENTER to continue...

This is an issue of prompt-toolkit. You can change prompt-toolkit to version 2.x.

.. code:: bash
pip install -U prompt-toolkit~=2.0
.. |image01| image:: https://github.com/passxyz/passxyz.github.io/raw/master/images/kpclib/kpclibpy.gif
172 changes: 108 additions & 64 deletions keepass.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8,82 +8,120 @@
"This is a Python Library that can be used to access KeePass database using KPCLib and Python.NET"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Configuration file support"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"from pathlib import *\n",
"from os import listdir, path\n",
"from os.path import isfile, join\n",
"\n",
"import configparser\n",
"\n",
"def get_homepath():\n",
" config_file = str(Path.home())+'/.kpclibdb/kpclibpy.ini'\n",
"\n",
" if path.exists(config_file):\n",
" config = configparser.ConfigParser()\n",
" config.read(config_file)\n",
" return config['DEFAULT']['homepath']\n",
" else:\n",
" return str(Path.home())+'/.kpclibdb'\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"from passxyz.commands.keepass import KeePass, IStatusLogger"
"home_path = get_homepath()\n",
"onlyfiles = [f for f in listdir(home_path) if isfile(join(home_path, f))]\n",
"if re.match(r'[0-9]+.*\\.jpg', f)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"import fnmatch\n",
"files = fnmatch.filter(listdir(home_path), \"*.kdbx\") + fnmatch.filter(listdir(home_path), \"*.xyz\")"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['ContinueWork',\n",
" 'EndLogging',\n",
" 'SetProgress',\n",
" 'SetText',\n",
" 'StartLogging',\n",
" '__class__',\n",
" '__delattr__',\n",
" '__dir__',\n",
" '__doc__',\n",
" '__eq__',\n",
" '__format__',\n",
" '__ge__',\n",
" '__getattribute__',\n",
" '__gt__',\n",
" '__hash__',\n",
" '__init__',\n",
" '__init_subclass__',\n",
" '__iter__',\n",
" '__le__',\n",
" '__lt__',\n",
" '__module__',\n",
" '__ne__',\n",
" '__new__',\n",
" '__reduce__',\n",
" '__reduce_ex__',\n",
" '__repr__',\n",
" '__setattr__',\n",
" '__sizeof__',\n",
" '__str__',\n",
" '__subclasshook__']"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
"name": "stdout",
"output_type": "stream",
"text": [
"['utdb.kdbx', 'pass_d_E8f4pEk.xyz']\n"
]
}
],
"source": [
"dir(IStatusLogger)"
"print(files)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
"'/home/roger_ye/.venvs/kpclib'"
]
},
"execution_count": 12,
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"o1.is_open()"
"config['DEFAULT']['homepath']"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import kpclibpy.kpclib\n",
"from KeePassLib import PwDatabase, PwGroup\n",
"from PassXYZLib import PxDefs, ItemType, ItemSubType"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n"
]
}
],
"source": [
"print(ItemType.PwGroup)"
]
},
{
Expand Down Expand Up @@ -138,12 +176,13 @@
"outputs": [],
"source": [
"import os\n",
"import passxyz.kpclibpy\n",
"import kpclibpy.kpclib\n",
"\n",
"from KeePassLib import PwDatabase, PwGroup \n",
"from KeePassLib.Serialization import IOConnectionInfo\n",
"from KeePassLib.Keys import CompositeKey, KcpPassword\n",
"from KeePassLib.Interfaces import IStatusLogger\n",
"from PassXYZLib import PxDefs, ItemType, ItemSubType\n",
"\n",
"class ShowWarningsLogger(IStatusLogger):\n",
" __namespace__ = \"KPCLibPyTest1\"\n",
Expand All @@ -160,15 +199,15 @@
" def SetText(self, strNewText, lsType):\n",
" print('SetText {} {}'.format(strNewText, lsType))\n",
" return True\n",
" def ContinueWork():\n",
" def ContinueWork(self):\n",
" return True\n",
"\n",
"class KeePass:\n",
"class KeePassTest:\n",
" _keepass = None\n",
" _db = None\n",
" def __new__(cls, *args, **kwargs):\n",
" if not cls._keepass:\n",
" cls._keepass = super(KeePass, cls\n",
" cls._keepass = super(KeePassTest, cls\n",
" ).__new__(cls, *args, **kwargs)\n",
" return cls._keepass\n",
" \n",
Expand Down Expand Up @@ -202,9 +241,9 @@
}
],
"source": [
"test_db_path = 'test/utdb.kdbx'\n",
"test_db_path = 'test/pass_d_E8f4pEk.xyz'\n",
"TEST_DB_KEY = \"12345\"\n",
"kp = KeePass()\n",
"kp = KeePassTest()\n",
"kp.open(test_db_path, TEST_DB_KEY)"
]
},
Expand Down Expand Up @@ -237,38 +276,43 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<-- Item 0 -->\n",
"Notes=Notes\n",
"Password=Password\n",
"Title=Sample Entry\n",
"URL=https://keepass.info/\n",
"UserName=User Name\n",
"How to use PassXYZ ? is a Notes? True\n",
"<-- Item 1 -->\n",
"Password=12345\n",
"Title=Sample Entry #2\n",
"URL=https://keepass.info/help/kb/testform.html\n",
"UserName=Michael321\n"
"KeePass Entry is a Notes? False\n",
"<-- Item 2 -->\n",
"WebDAV is a Notes? False\n",
"UserName=\n",
"Password=\n",
"Email=\n",
"WebDAV URL=\n",
"es=\n",
"le=WebDAV\n"
]
}
],
"source": [
"from PassXYZLib import PxDefs\n",
"def printEntry(kp):\n",
" for kp in entry.Strings:\n",
" print('{}={}'.format(kp.Key, kp.Value.ReadString()))\n",
" print('{}={}'.format(PxDefs.DecodeKey(kp.Key), kp.Value.ReadString()))\n",
"\n",
"pg = kp._db.RootGroup\n",
"i = 0\n",
"for entry in pg.Entries:\n",
" print('<-- Item {} -->'.format(i))\n",
" printEntry(entry)\n",
" i = i + 1"
" #printEntry(entry)\n",
" print(entry.get_Name(), \"is a Notes? \", PxDefs.IsNotes(entry))\n",
" i = i + 1\n",
" if PxDefs.IsPxEntry(entry):\n",
" printEntry(entry)"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion kpclibpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@
__email__ = metadata["author-email"]
__license__ = metadata["license"]
except ModuleNotFoundError:
__version__ = "1.1.3.dev2"
__version__ = "1.1.5.dev0"
print("Debug build ", __version__)
6 changes: 6 additions & 0 deletions kpclibpy/commands/database_cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,17 @@ def show(items):
db_table.add_row([colored("HistoryMaxSize", "magenta"), db.HistoryMaxSize])
db_table.add_row([colored("Description", "magenta"), db.Description])
db_table.add_row([colored("MaintenanceHistoryDays", "magenta"), db.MaintenanceHistoryDays])
db_table.add_row([colored("Filename", "magenta"), ctx.keepass.file_name])
if ctx.keepass.db_type == "PassXYZ":
db_table.add_row([colored("Decoded Filename", "magenta"), ctx.keepass.user_name])
cprint("Database configureation", "yellow")
print(db_table)
else:
cprint("Database is closed", "red")
elif items == "version":
version()
elif items == "databases":
print("The current path: ", get_homepath())
db_table = PrettyTable(["No.", "Name"])
db_table.align = "l"
num = 1
Expand Down Expand Up @@ -256,6 +260,8 @@ def open(dbfile: str, password = ""):
logger = KPCLibPyLogger()
db_path = get_homepath() + '/' + dbfile
ctx.keepass.open(db_path, password, logger)

ctx.keepass.file_name = dbfile


@command
Expand Down
23 changes: 17 additions & 6 deletions kpclibpy/commands/entry/entry_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#

import typing
import click
#from pathlib import *
from termcolor import cprint
from nubia import command, argument, context
Expand All @@ -31,13 +32,18 @@ def cat(path: str):
@argument("path", description="entry path", positional=True)
@argument("key", description="source entry/group")
@argument("value", description="destination entry/group")
def edit(path, key, value):
@argument("protected", description="print detail information or not")
def edit(path, key="Notes", value="", protected=False):
"Edit an entry. Need to provide a key and a value to edit a field."
ctx = context.get_context()
if ctx.keepass.is_open():
entry = ctx.keepass.find_entry_by_path(path)
if entry:
ctx.keepass.update_entry(entry, key, value)
if value:
ctx.keepass.update_entry(entry, key, value, protected)
else:
value = click.edit(entry.Strings.ReadSafe(key))
ctx.keepass.update_entry(entry, key, value, protected)
else:
print("cannot access {}: No such file or directory".format(path))

Expand All @@ -57,15 +63,20 @@ def new(title="New entry", username="", password="", url="", notes=""):

@command
@argument("entry_name", description="enter a entry name", positional=True)
def rm(entry_name: str):
"Remove an entry"
@argument("key", description="source entry/group")
def rm(entry_name: str, key=""):
"Remove an entry or a field"
ctx = context.get_context()
if ctx.keepass.is_open():
try:
entry = ctx.keepass.entries[entry_name]
if entry:
ctx.keepass.db.DeleteEntry(entry)
cprint("Removed {}.".format(entry_name))
if key:
ctx.keepass.update_entry(entry, key, "")
cprint("Removed field {}.".format(key))
else:
ctx.keepass.db.DeleteEntry(entry)
cprint("Removed entry {}.".format(entry_name))
else:
cprint("rm: cannot remove {}: No such entry".format(entry_name), "red")
except KeyError:
Expand Down
Loading

0 comments on commit 79c8d20

Please sign in to comment.