Remove exec/shell_exec from update checker and domain lookups
Update checker (fetchUpdates) no longer shells out to git:
- Current commit read directly from .git/HEAD, following the branch
ref through loose refs with a packed-refs fallback (survives git gc);
detached HEAD handled
- Latest commit fetched from the GitHub API via curl using the
Accept: application/vnd.github.sha header (returns bare SHA, no
JSON parsing)
- Repo owner/name derived from the origin remote in .git/config so
forks check against their own remote, falling back to
itflow-org/itflow
- Failures now distinguish unreadable .git (permissions) from API
errors (network/rate limit) instead of silently returning empty
Domain lookups no longer shell out to dig and whois:
- DNS records (A/NS/MX/TXT) via dns_get_record()
- Registration data via RDAP (JSON over HTTPS, curl), the ICANN
successor to port-43 whois; RDAP server per TLD resolved from
IANA's bootstrap registry, cached locally for a week, rdap.org as
secondary lookup
- Expiration date from RDAP's structured expiration event, replacing
regex/date-format guessing for RDAP-covered TLDs
- Port-43 whois retained as socket-based fallback (fsockopen) for
ccTLDs without RDAP, with IANA server discovery and one registrar
referral follow
- RDAP responses cached per-run: getDomainRecords() and
getDomainExpirationDate() on the same domain = one HTTP request
Fixes whois rate limiting, removes the exec dependency for hardened
hosts (Snuffleupagus etc.), and eliminates the shell injection
surface - no shell, nothing to escape.
Replace webklex/php-imap with directorytree/imapengine in the ticket
email parser. ImapEngine is pure PHP over sockets.
Parser improvements:
- Wrap per-message processing in try/catch so one malformed email
can't abort the run; failures are flagged and logged with UID
- Query unseen + unflagged so previously-failed (flagged) messages
are no longer re-processed on every cron run
- Skip vacation/auto-responder emails (RFC 3834) to prevent mail
loops with the ticket auto-reply
- Cap messages per run (50) and attachment size (15MB); inline
images over 2MB are stored as attachments instead of base64-embedded
in ticket details
- Atomic lock file creation
- preg_quote() the ticket prefix in subject matching
- Dedupe CC watchers and exclude the sender
- Map webklex 'tls' encryption setting to STARTTLS for compatibility
NDR/DSN parsing now walks MIME parts via the underlying
zbateson parser instead of relying on attachment extraction.