pwsafe/transport — Plugin Identity & Scheme Dispatch

See parent: transport

Filename Convention (primary lookup)

Plugin files are named pwsafe-<scheme>.so (e.g. pwsafe-webdav.so, pwsafe-file.so, pwsafe-s3.so). When a scheme is needed, the loader constructs the filename directly — no directory scan required.

Search path (in order): 1. Directory containing the application binary (via /proc/self/exe on Linux) 2. Current working directory — #ifdef DEVELOPMENT builds only (security: avoid loading arbitrary plugins from cwd in production)

Embedded Identity String (verification)

Every plugin embeds a static string. After finding the file by name, the loader verifies it before dlopen as a sanity check against renamed files:

static const char pws_transport_info[] =
    "PWS_TRANSPORT_INFO:1:http,https:WebDAV store via libcurl";
//                     ^ ^-scheme(s)-^ ^----description----^
//                     ABI version

Format: PWS_TRANSPORT_INFO:<abi>:<scheme>[,scheme,...]:<description>

Examples: PWS_TRANSPORT_INFO:1:file:Local file transport (testing) PWS_TRANSPORT_INFO:1:http,https:WebDAV transport via libcurl PWS_TRANSPORT_INFO:1:s3:Amazon S3 transport

Verification is a raw-bytes scan (fopen + memmem) — no dlopen needed. If the identity string is absent or the scheme doesn't match the filename, the file is rejected with a clear error. Readable externally with strings pwsafe-webdav.so | grep PWS_TRANSPORT_INFO.

Load Sequence

1. User enters a URL — scheme extracted (e.g. webdav) 2. Construct filename: pwsafe-webdav.so 3. Search for it in path order (app dir, then cwd if DEVELOPMENT) 4. If not found → popup error, offer retry; stop 5. Pre-scan raw bytes: verify PWS_TRANSPORT_INFO: string matches scheme and ABI 6. If mismatch → error ("file may have been renamed"); stop 7. dlopen the file 8. Call pws_plugin_init(register_fn) 9. If init fails → dlclose, error; stop 10. Plugin is live — use it for this database session

Plugin Lifetime

A plugin is loaded when its scheme is first needed and unloaded when the database using it is closed (or when the user switches to a plain file path). Only one plugin is live at a time. If the same scheme is needed again in the same session, it is reloaded.

First match wins: the assumption is at most one pwsafe-<scheme>.so per scheme on the search path. If duplicates exist, the one in the app binary directory takes precedence.

Scheme Dispatch Rules

• No prefix, or plain OS path → no plugin → existing local file code, unchanged • file:///pathpwsafe-file.so (reference/test plugin) • webdav:https://host/pathpwsafe-webdav.so (strips own prefix, passes https://... to libcurl) • s3://bucket/keypwsafe-s3.so

version2
created2026-02-24
updated2026-02-24