Skip to content

Commit

Permalink
Add support to set or get AutoType/Association/Window (#367)
Browse files Browse the repository at this point in the history
Co-authored-by: Bernd Gempel <[email protected]>
  • Loading branch information
iBernd81 and Bernd Gempel authored Nov 27, 2023
1 parent 1085c59 commit 0a9e071
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ dist/
*.egg-info/
build/
*.xml
Pipfile
Pipfile.lock
*.kdbx
*.kdbx.out
.idea
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Finding Entries

**find_entries** (title=None, username=None, password=None, url=None, notes=None, otp=None, path=None, uuid=None, tags=None, string=None, group=None, recursive=True, regex=False, flags=None, history=False, first=False)

Returns entries which match all provided parameters, where ``title``, ``username``, ``password``, ``url``, ``notes``, ``otp``, and ``autotype_sequence`` are strings, ``path`` is a list, ``string`` is a dict, ``autotype_enabled`` is a boolean, ``uuid`` is a ``uuid.UUID`` and ``tags`` is a list of strings. This function has optional ``regex`` boolean and ``flags`` string arguments, which means to interpret search strings as `XSLT style`_ regular expressions with `flags`_.
Returns entries which match all provided parameters, where ``title``, ``username``, ``password``, ``url``, ``notes``, ``otp``, ``autotype_window`` and ``autotype_sequence`` are strings, ``path`` is a list, ``string`` is a dict, ``autotype_enabled`` is a boolean, ``uuid`` is a ``uuid.UUID`` and ``tags`` is a list of strings. This function has optional ``regex`` boolean and ``flags`` string arguments, which means to interpret search strings as `XSLT style`_ regular expressions with `flags`_.

.. _XSLT style: https://www.xml.com/pub/a/2003/06/04/tr.html
.. _flags: https://www.w3.org/TR/xpath-functions/#flags
Expand Down
20 changes: 18 additions & 2 deletions pykeepass/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Entry(BaseElement):

def __init__(self, title=None, username=None, password=None, url=None,
notes=None, otp=None, tags=None, expires=False, expiry_time=None,
icon=None, autotype_sequence=None, autotype_enabled=True,
icon=None, autotype_sequence=None, autotype_enabled=True, autotype_window=None,
element=None, kp=None):

self._kp = kp
Expand Down Expand Up @@ -60,7 +60,11 @@ def __init__(self, title=None, username=None, password=None, url=None,
E.AutoType(
E.Enabled(str(autotype_enabled)),
E.DataTransferObfuscation('0'),
E.DefaultSequence(str(autotype_sequence) if autotype_sequence else '')
E.DefaultSequence(str(autotype_sequence) if autotype_sequence else ''),
E.Association(
E.Window(str(autotype_window) if autotype_window else ''),
E.KeystrokeSequence('')
)
)
)
# FIXME: include custom_properties in constructor
Expand Down Expand Up @@ -268,6 +272,18 @@ def autotype_sequence(self):
def autotype_sequence(self, value):
self._element.find('AutoType/DefaultSequence').text = value

@property
def autotype_window(self):
"""str: get or set [autotype target window filter](https://keepass.info/help/base/autotype.html#autowindows)"""
sequence = self._element.find('AutoType/Association/Window')
if sequence is None or sequence.text == '':
return None
return sequence.text

@autotype_window.setter
def autotype_window(self, value):
self._element.find('AutoType/Association/Window').text = value

@property
def is_a_history_entry(self):
"""bool: check if entry is History entry"""
Expand Down
2 changes: 2 additions & 0 deletions pykeepass/xpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
'tags': '/Tags[text()="{}"]/..',
'string': '/String/Key[text()="{}"]/../Value[text()="{}"]/../..',
'autotype_sequence': '/AutoType/DefaultSequence[text()="{}"]/../..',
'autotype_window': '/AutoType/Association/Window[text()="{}"]/../../..',
'autotype_enabled': '/AutoType/Enabled[text()="{}"]/../..',
'otp': '/String/Key[text()="otp"]/../Value[text()="{}"]/../..',
},
Expand All @@ -44,6 +45,7 @@
'tags': '/Tags[re:test(text(), "{}", "{flags}")]/..',
'string': '/String/Key[text()="{}"]/../Value[re:test(text(), "{}", "{flags}")]/../..',
'autotype_sequence': '/AutoType/DefaultSequence[re:test(text(), "{}", "{flags}")]/../..',
'autotype_window': '/AutoType/Association/Window[re:test(text(), "{}", "{flags}")]/../../..',
'autotype_enabled': '/AutoType/Enabled[re:test(text(), "{}", "{flags}")]/../..',
'otp': '/String/Key[text()="otp"]/../Value[re:test(text(), "{}", "{flags}")]/../..',
}
Expand Down
Binary file modified tests/test3.kdbx
Binary file not shown.
7 changes: 5 additions & 2 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@
from datetime import datetime, timedelta

from dateutil import tz
from lxml.etree import Element
from pathlib import Path

from io import BytesIO

from pykeepass import PyKeePass, icons
from pykeepass.entry import Entry
from pykeepass.group import Group
from pykeepass.kdbx_parsing import KDBX
from pykeepass.exceptions import BinaryError, CredentialsError, HeaderChecksumError

"""
Expand Down Expand Up @@ -144,6 +142,11 @@ def test_find_entries_by_autotype_sequence(self):
self.assertEqual(len(results), 1)
self.assertEqual(results[0].autotype_sequence, '{USERNAME}{TAB}{PASSWORD}{ENTER}')

def test_find_entries_by_autotype_window(self):
results = self.kp.find_entries(autotype_window='test', regex=True, flags="i")
self.assertEqual(len(results), 1)
self.assertEqual(results[0].autotype_window, 'TEST')

def test_find_entries_by_autotype_enabled(self):
results = self.kp.find_entries(autotype_enabled=True)
self.assertEqual(len(results), len(self.kp.entries) - 1)
Expand Down

0 comments on commit 0a9e071

Please sign in to comment.