Replace srand()/rand() with random_int() for cryptographically secure,
unbiased key generation. The previous implementation seeded rand() from
microtime(), making TOTP secrets predictable if the generation time
could be approximated. Also removes modulo bias and dead while(1)
wrapper.
Output format is unchanged: 32 chars from the base32 alphabet (A-Z,
2-7), so existing TOTP enrollments are unaffected.
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.