PyNUTClient: decode NUT values and escape authentication arguments - #3629
PyNUTClient: decode NUT values and escape authentication arguments#3629user01010111 wants to merge 4 commits into
Conversation
Parse the quoted LIST UPS description without treating escaped quotes as field delimiters. Decode NUT escapes once while keeping dictionary keys and values as bytes and preserving GetUPSNames() conversion of names. Add deterministic regression coverage to make check, including escaped byte combinations, fragmented reads, consumers and existing errors. Reject malformed quoted descriptions with ValueError rather than silently truncating a description whose closing quote is missing. Closes: networkupstools#3620 AI assistance: OpenAI Codex with gpt-6-astra (x-high reasoning). The human contributor remains responsible for reviewing and submitting the change. Signed-off-by: user01010111 <12504630+user01010111@users.noreply.github.com>
|
A ZIP file with standard source tarball and another tarball with pre-built docs for commit af77624 is temporarily available: NUT-tarballs-PR-3629.zip. |
|
Thanks! I think this parser code makes sense as a separate helper method, which should be applied to all strings returned by |
Thanks, Jim. Happy to extract a shared helper and reuse it across the relevant Python readers. Before expanding this PR, could you clarify a few scope points?
To clarify, I’d preserve the existing return types and keep the changes focused on NUT’s escaping semantics. |
|
Fixes for Python (and C if there is indeed some inconsistency) may well be in this PR. Regarding C, I think there was a bug logged about I think PERL binding may suffer similarly, but can be addressed separately based on lessons learned here. |
|
Thanks, Jim. I traced the related paths and checked them with deterministic parser probes, NDE self-test mode, and a localhost
I propose keeping the shared Python parsing helper and affected readers, configuration/include parsing, necessary outbound encoding, the Python 3 command-name correction, and the two C response-encoding fixes in this PR, with the relevant tests and documentation updates. Existing Python return types would be preserved. Perl and NDE would follow separately. Does that scope split work for you? Two compatibility points before implementing:
No physical UPS hardware was available for testing. These checks covered software behavior and simulated/local integration; physical UPS models, firmware versions, and hardware combinations were not tested. |
|
✅ Build nut 2.8.5.5253-master completed (commit 70271d4362 by @user01010111)
|
|
Yes, splitting the PRs makes sense. The C parser breaking for a hash inside quotes (the
|
Decode LIST CMD identifiers as ASCII for GET CMDDESC requests and response offsets, preserving the public bytes dictionary and description fallback. Add request-sensitive regression coverage to make check and note the fix in NEWS.adoc. Validated with Python 2.6, 2.7 and 3.4 through 3.14, localhost upsd with dummy-ups, generated/installed/packaged modules, make check, spellcheck and distcheck-light. AI assistance: OpenAI Codex with gpt-6-astra (x-high reasoning). The human contributor remains responsible for reviewing and submitting the change. Closes: networkupstools#3621 Signed-off-by: user01010111 <12504630+user01010111@users.noreply.github.com>
Share NUT token decoding across Python response and configuration readers, including INCLUDE paths, and encode literal authentication arguments. Escape server DESC and CMDDESC responses with pconf_encode. Preserve return types and existing response limits; document configuration compatibility. Add deterministic and localhost integration coverage to existing tests. Validated across Python 2.6, 2.7 and 3.4-3.14, package/install paths, real localhost upsd/dummy-ups, documentation checks and distcheck-light. Closes: networkupstools#3620 AI assistance: OpenAI Codex with gpt-6-astra (x-high and high reasoning) and gpt-daybreak-blue-latest (high reasoning). The human contributor remains responsible for reviewing and submitting the change. Signed-off-by: user01010111 <12504630+user01010111@users.noreply.github.com>
|
❌ Build nut 2.8.5.5258-master failed (commit f7612c782d by @user01010111) |
Use portable real filenames and escape complete paths in INCLUDE fixtures. Check quote, hash and backslash decoding separately through the AuthConf reader without creating a Windows-invalid filename. Preserve production behavior and existing escape coverage. Validated with all 36 tests across the documented macOS/Linux Python matrix and Windows CPython 3.13.7 under Wine, including a separate shared-test run with spaces and a hash in the temporary parent path. Build, make check, spelling/style and distcheck-light pass. Wine does not establish exact AppVeyor-image or Windows-kernel acceptance. Related: networkupstools#3629 AI assistance: OpenAI Codex with gpt-6-astra. The human contributor remains responsible for reviewing and submitting the change. Signed-off-by: user01010111 <12504630+user01010111@users.noreply.github.com>
|
❌ Build nut 2.8.5.5262-master failed (commit 5d14f3687d by @user01010111) |
|
In Appveyor build, this still complains: |
Descriptions containing escaped quotes can make
GetUPSList()fail, whileother Python readers truncate quoted values or retain wire escapes. Decode
NUT tokens once in a shared private parser, preserving existing byte/string
return types and the command-description error fallback. Use the same
grammar for
nutauth.confvalues and INCLUDE filenames, and escape literalusernames and passwords before sending them. Double quotes group tokens;
single quotes remain literal characters.
Encode
upsdvariable and command descriptions with the existingpconf_encode()helper before returning DESC and CMDDESC. Keep the existingresponse-size limit. Add deterministic tests and a localhost integration
case to the existing test infrastructure. Update NEWS in its client-library
and data-server sections, UPGRADING, the authentication manual and Python
README; add the documented API names to the spelling dictionary.
Closes: #3620
This implements the agreed Python/server scope from the discussion in this
PR. The C quoted-hash correction (#3633), Perl parsing (#3634)
and NDE configuration fixes (#3635) are separate contributions. Command-name formatting reuses the existing
#3628 change; its ownership remains with that PR.
Validation:
one error on the pre-feedback module. Existing ordinary controls pass.
The patched module passes all 35 tests: 16 UPS-list tests, 13 shared
protocol/configuration tests and six existing command tests.
3.8.20, 3.9.25, 3.10.21, 3.11.16, 3.12.14, 3.13.15 and 3.14.7 pass.
Native macOS ARM64 tests pass on Python 3.9.6 and 3.14.7.
352 valid ASCII cases, including 3,304 split-boundary checks and text
input checks. Python deliberately preserves bytes where C configuration
parsing filters high bytes; no new Unicode conversion policy is added.
Linux and macOS: eight passed, zero failed or skipped on each. Existing
TLS checks and the new plaintext punctuation fixture cover decoded
values/descriptions, INCLUDE credentials, ordinary controls, successful
secondary LOGIN and incorrect-password rejection. No power commands are
issued by the new fixture.
35 tests on Linux Python 3.11.15; installed module bytes match the
configured source. The direct CI packaging recipe also builds successfully.
tests, documentation, stylecheck, spellcheck and distcheck-light pass.
The final distribution check uses real manual pages and exercises the
archive's build/test/install/uninstall/cleanup lifecycle. Changed source
files are verified against that archive.
No physical UPS hardware was available for testing. Validation covered
deterministic protocol/configuration tests, corrected-C parser comparisons,
package/install tests and localhost upsd with simulated dummy-ups, including
the existing TLS integration checks.
Physical UPS models, firmware versions, and hardware combinations were
not tested.
Windows and other operating systems were not executed. Python 2.6 uses
the plain socket path. Simulated tests do not establish physical-device
compatibility. The existing server response-size ceiling and configuration
include lookup/precedence remain unchanged. Users should remove manual
unescaping workarounds and replace single quotes previously used to group
configuration values with double quotes, as described in UPGRADING.
Relevant checklist:
AI assistance: OpenAI Codex with gpt-6-astra (x-high and high reasoning)
and gpt-daybreak-blue-latest (high reasoning).
The human contributor remains responsible for reviewing and submitting
the change.