#ifndef ____imapaccounts_h__ # define ____imapaccounts_h__ # include "Tag.h" # include "ZString.h" # include "MString.h" # include # include # include namespace jet { /// /// /// /// Pure list-transform tag (no session-variable access of its own, /// no IMAP connection) that manages the multi-account list webmail /// keeps in the single session variable "_imap_accounts" - the .jet /// route wraps each call in itself and /// s it back, the same separation-of-concerns every other /// session variable in this codebase already uses (this tag never /// touches Global's session-variable map directly). /// /// The list's own on-the-wire encoding (semicolon-separated /// "base64(host):base64(user):base64(password)" entries) is private /// to this tag - callers only ever pass the whole `list` value back /// in verbatim and use the returned value the same way, so the /// choice of delimiter can't collide with any real username or /// password character. Each account can live on its own IMAP server /// (see the //etc. tags' own optional host/port /// keywords), not just the one fixed host in email.cfg. /// /// action="add": upserts host/user/password (removing any existing /// entry for the same user first, so reconnecting with a changed /// password or server updates it) - returns the updated encoded list. /// action="remove": drops the entry for user, if present - returns /// the updated encoded list. /// action="getpassword": returns the stored password for user, or /// an empty string if not present. /// action="gethost": returns the stored host for user, or an empty /// string if not present. /// action="firstuser": returns the first entry's username, or an /// empty string if the list is empty. /// action="list": returns JSON ({"accounts":[...],"active":"..."}) /// - the one client-facing action; "active" echoes the `active` /// keyword (typically $[@_imap_user]) back verbatim so the sidebar /// can highlight the current one, and never includes any password or /// host (unchanged shape from before per-account hosts existed - /// nothing client-side needs the host to switch between already- /// connected accounts). /// class __imapaccounts : public Tag { struct Account { std::string host, user, password; }; public: __imapaccounts(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local); private: static std::vector decodeList(const std::string &encoded); static std::string encodeList(const std::vector &entries); static std::string jsonEscape(const std::string &s); }; } #endif