%% dnsrecord.sty
%% Copyright 2026 Vahid Shaik
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3c
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%   https://www.latex-project.org/lppl.txt
%% and version 1.3c or later is part of all distributions of LaTeX
%% version 2008 or later.
%%
%% This work has the LPPL maintenance status `maintained'.
%% The Current Maintainer of this work is Vahid Shaik.
%%
%% Homepage: https://dnsrobot.net
%% Repository: https://github.com/dnsrobot/latex-dnsrecord
%%
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\ProvidesPackage{dnsrecord}[2026/03/09 v1.0.0 Typeset DNS records in LaTeX documents]

% Required packages
\RequirePackage{booktabs}
\RequirePackage{xcolor}
\RequirePackage{xparse}
\RequirePackage{etoolbox}
\RequirePackage{amsmath}

% ============================================================
% Color definitions for DNS record types
% ============================================================
\definecolor{dns@a}{HTML}{2563EB}
\definecolor{dns@aaaa}{HTML}{7C3AED}
\definecolor{dns@cname}{HTML}{059669}
\definecolor{dns@mx}{HTML}{DC2626}
\definecolor{dns@ns}{HTML}{D97706}
\definecolor{dns@txt}{HTML}{4B5563}
\definecolor{dns@soa}{HTML}{BE185D}
\definecolor{dns@ptr}{HTML}{0891B2}
\definecolor{dns@srv}{HTML}{4338CA}
\definecolor{dns@caa}{HTML}{B45309}
\definecolor{dns@dnskey}{HTML}{1D4ED8}
\definecolor{dns@ds}{HTML}{6D28D9}
\definecolor{dns@rrsig}{HTML}{9333EA}
\definecolor{dns@nsec}{HTML}{065F46}
\definecolor{dns@nsec3}{HTML}{047857}
\definecolor{dns@tlsa}{HTML}{7E22CE}
\definecolor{dns@spf}{HTML}{B91C1C}
\definecolor{dns@dkim}{HTML}{92400E}
\definecolor{dns@dmarc}{HTML}{9F1239}
\definecolor{dns@https}{HTML}{0E7490}
\definecolor{dns@svcb}{HTML}{155E75}
\definecolor{dns@default}{HTML}{374151}

% Propagation status colors
\definecolor{dns@propagated}{HTML}{059669}
\definecolor{dns@pending}{HTML}{D97706}
\definecolor{dns@failed}{HTML}{DC2626}
\definecolor{dns@timeout}{HTML}{6B7280}

% Health check colors
\definecolor{dns@healthy}{HTML}{059669}
\definecolor{dns@warning}{HTML}{D97706}
\definecolor{dns@critical}{HTML}{DC2626}
\definecolor{dns@info}{HTML}{2563EB}

% Background colors for boxed records
\definecolor{dns@boxbg}{HTML}{F9FAFB}
\definecolor{dns@boxborder}{HTML}{E5E7EB}

% ============================================================
% Options
% ============================================================
\newif\ifdns@usecolor  \dns@usecolortrue
\newif\ifdns@mono      \dns@monotrue
\newif\ifdns@showttl   \dns@showttltrue
\newif\ifdns@showclass \dns@showclassfalse
\newif\ifdns@compact   \dns@compactfalse
\newif\ifdns@boxed     \dns@boxedfalse

\DeclareOption{color}{\dns@usecolortrue}
\DeclareOption{nocolor}{\dns@usecolorfalse}
\DeclareOption{monospace}{\dns@monotrue}
\DeclareOption{nomonospace}{\dns@monofalse}
\DeclareOption{ttl}{\dns@showttltrue}
\DeclareOption{nottl}{\dns@showttlfalse}
\DeclareOption{class}{\dns@showclasstrue}
\DeclareOption{noclass}{\dns@showclassfalse}
\DeclareOption{compact}{\dns@compacttrue}
\DeclareOption{boxed}{\dns@boxedtrue}
\ProcessOptions\relax

% ============================================================
% Internal helpers
% ============================================================
\newcommand{\dns@getcolor}[1]{%
  \ifdns@usecolor
    \@ifundefined{color@dns@\MakeLowercase{#1}}%
      {\color{dns@default}}%
      {\color{dns@\MakeLowercase{#1}}}%
  \fi
}

\newcommand{\dns@fmt}[1]{%
  \ifdns@mono\texttt{#1}\else#1\fi
}

\newcommand{\dns@badge}[1]{%
  {\dns@getcolor{#1}\textbf{\dns@fmt{\MakeUppercase{#1}}}}%
}

% Colored box around text
\newcommand{\dns@colorbox}[2]{%
  \ifdns@usecolor
    \fcolorbox{dns@boxborder}{dns@boxbg}{{\dns@getcolor{#1}\textbf{\dns@fmt{\MakeUppercase{#1}}}}\ #2}%
  \else
    \fbox{\textbf{\dns@fmt{\MakeUppercase{#1}}}\ #2}%
  \fi
}

% ============================================================
% Section 1: Inline DNS record commands
% ============================================================

% \dnsrecord{type}{name}{value}[ttl]
\NewDocumentCommand{\dnsrecord}{m m m O{}}{%
  \ifdns@boxed
    \dns@colorbox{#1}{\dns@fmt{#2} \textrightarrow\ \dns@fmt{#3}%
      \ifblank{#4}{}{\ifdns@showttl\ {\footnotesize TTL\,\dns@fmt{#4}}\fi}}%
  \else
    \dns@badge{#1}%
    \enspace\dns@fmt{#2}%
    \enspace\textrightarrow\enspace\dns@fmt{#3}%
    \ifdns@showclass\enspace{\footnotesize IN}\fi%
    \ifblank{#4}{}{\ifdns@showttl\enspace{\footnotesize TTL\,\dns@fmt{#4}}\fi}%
  \fi
}

% Standard record type shorthands
\NewDocumentCommand{\dnsA}{m m O{}}{\dnsrecord{A}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsAAAA}{m m O{}}{\dnsrecord{AAAA}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsCNAME}{m m O{}}{\dnsrecord{CNAME}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsMX}{m m m O{}}{\dnsrecord{MX}{#1}{#3 (pri #2)}[#4]}
\NewDocumentCommand{\dnsNS}{m m O{}}{\dnsrecord{NS}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsTXT}{m m O{}}{\dnsrecord{TXT}{#1}{"#2"}[#3]}
\NewDocumentCommand{\dnsSOA}{m m m O{}}{\dnsrecord{SOA}{#1}{#2 (#3)}[#4]}
\NewDocumentCommand{\dnsPTR}{m m O{}}{\dnsrecord{PTR}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsSRV}{m m m m O{}}{\dnsrecord{SRV}{#1}{#3:#4 (pri #2)}[#5]}
\NewDocumentCommand{\dnsCAA}{m m m O{}}{\dnsrecord{CAA}{#1}{#2 #3}[#4]}

% DNSSEC record type shorthands
\NewDocumentCommand{\dnsDNSKEY}{m m O{}}{\dnsrecord{DNSKEY}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsDS}{m m O{}}{\dnsrecord{DS}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsRRSIG}{m m O{}}{\dnsrecord{RRSIG}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsNSEC}{m m O{}}{\dnsrecord{NSEC}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsNSEC3}{m m O{}}{\dnsrecord{NSEC3}{#1}{#2}[#3]}

% Modern record type shorthands
\NewDocumentCommand{\dnsTLSA}{m m O{}}{\dnsrecord{TLSA}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsHTTPS}{m m O{}}{\dnsrecord{HTTPS}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsSVCB}{m m O{}}{\dnsrecord{SVCB}{#1}{#2}[#3]}

% Email authentication shorthands
\NewDocumentCommand{\dnsSPF}{m m O{}}{\dnsrecord{SPF}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsDKIM}{m m O{}}{\dnsrecord{DKIM}{#1}{#2}[#3]}
\NewDocumentCommand{\dnsDMARC}{m m O{}}{\dnsrecord{DMARC}{#1}{#2}[#3]}

% ============================================================
% Section 2: DNS zone table environment
% ============================================================

\newcounter{dns@entrycount}

\NewDocumentEnvironment{dnszone}{m}{%
  \setcounter{dns@entrycount}{0}%
  \def\dns@zonedomain{#1}%
  \ifdns@showclass
    \begin{tabular}{@{} l l l l l @{}}
  \else
    \begin{tabular}{@{} l l l l @{}}
  \fi
  \toprule
  \textbf{Type} & \textbf{Name} & \textbf{Value}
  \ifdns@showclass & \textbf{Class}\fi
  \ifdns@showttl & \textbf{TTL}\fi \\
  \midrule
}{%
  \bottomrule
  \ifdns@showclass
    \end{tabular}
  \else
    \end{tabular}
  \fi
  \par\smallskip
  {\footnotesize\textit{DNS zone: \dns@fmt{\dns@zonedomain}
  --- \arabic{dns@entrycount} records}}%
}

\NewDocumentCommand{\dnsentry}{m m m O{}}{%
  \stepcounter{dns@entrycount}%
  \dns@badge{#1} & \dns@fmt{#2} & \dns@fmt{#3}
  \ifdns@showclass & IN\fi
  \ifdns@showttl & \ifblank{#4}{---}{\dns@fmt{#4}}\fi \\
}

% ============================================================
% Section 3: DNS propagation table environment
% ============================================================

\NewDocumentEnvironment{dnspropagation}{m m}{%
  \def\dns@propdomain{#1}%
  \def\dns@proptype{#2}%
  \begin{tabular}{@{} l l l l l @{}}
  \toprule
  \textbf{Server} & \textbf{IP} & \textbf{Result} & \textbf{RTT} & \textbf{Status} \\
  \midrule
}{%
  \bottomrule
  \end{tabular}
  \par\smallskip
  {\footnotesize\textit{Propagation check:
  \dns@badge{\dns@proptype} record for \dns@fmt{\dns@propdomain}}}%
}

\NewDocumentCommand{\dnsstatus}{m}{%
  \ifstrequal{#1}{propagated}{{\color{dns@propagated}\textbullet\ Propagated}}{}%
  \ifstrequal{#1}{pending}{{\color{dns@pending}\textbullet\ Pending}}{}%
  \ifstrequal{#1}{failed}{{\color{dns@failed}\textbullet\ Failed}}{}%
  \ifstrequal{#1}{timeout}{{\color{dns@timeout}\textbullet\ Timeout}}{}%
}

\NewDocumentCommand{\dnsserver}{m m m m m}{%
  \dns@fmt{#1} & \dns@fmt{#2} & \dns@fmt{#3} & \dns@fmt{#4} & \dnsstatus{#5} \\
}

% ============================================================
% Section 4: DNSSEC validation display
% ============================================================

\NewDocumentCommand{\dnssec}{m}{%
  \ifstrequal{#1}{valid}{{\color{dns@propagated}\textbf{DNSSEC:} Validated}}{}%
  \ifstrequal{#1}{invalid}{{\color{dns@failed}\textbf{DNSSEC:} Validation Failed}}{}%
  \ifstrequal{#1}{unsigned}{{\color{dns@pending}\textbf{DNSSEC:} Not Signed}}{}%
  \ifstrequal{#1}{insecure}{{\color{dns@timeout}\textbf{DNSSEC:} Insecure Delegation}}{}%
}

% DNSSEC chain of trust table
\NewDocumentEnvironment{dnssecchain}{m}{%
  \def\dns@secdomain{#1}%
  \begin{tabular}{@{} l l l l @{}}
  \toprule
  \textbf{Zone} & \textbf{Record} & \textbf{Key Tag} & \textbf{Algorithm} \\
  \midrule
}{%
  \bottomrule
  \end{tabular}
  \par\smallskip
  {\footnotesize\textit{DNSSEC chain of trust for \dns@fmt{\dns@secdomain}}}%
}

\NewDocumentCommand{\dnssecentry}{m m m m}{%
  \dns@fmt{#1} & \dns@badge{#2} & \dns@fmt{#3} & \dns@fmt{#4} \\
}

% ============================================================
% Section 5: DNS health check environment
% ============================================================

\NewDocumentCommand{\dnshealth}{m m}{%
  \ifstrequal{#1}{healthy}{{\color{dns@healthy}\textbullet\ \textbf{PASS:}} #2}{}%
  \ifstrequal{#1}{warning}{{\color{dns@warning}\textbullet\ \textbf{WARN:}} #2}{}%
  \ifstrequal{#1}{critical}{{\color{dns@critical}\textbullet\ \textbf{FAIL:}} #2}{}%
  \ifstrequal{#1}{info}{{\color{dns@info}\textbullet\ \textbf{INFO:}} #2}{}%
}

\NewDocumentEnvironment{dnshealthcheck}{m}{%
  \def\dns@healthdomain{#1}%
  \par\medskip
  {\large\textbf{DNS Health Check:} \dns@fmt{#1}}\par\smallskip
  \begin{list}{}{\setlength{\leftmargin}{1em}\setlength{\itemsep}{2pt}}%
}{%
  \end{list}%
  \par
}

\NewDocumentCommand{\dnshealthitem}{m m}{%
  \item \dnshealth{#1}{#2}%
}

% ============================================================
% Section 6: Email authentication summary
% ============================================================

\NewDocumentEnvironment{dnsemailauth}{m}{%
  \def\dns@emaildomain{#1}%
  \begin{tabular}{@{} l l l l @{}}
  \toprule
  \textbf{Protocol} & \textbf{Record} & \textbf{Policy} & \textbf{Status} \\
  \midrule
}{%
  \bottomrule
  \end{tabular}
  \par\smallskip
  {\footnotesize\textit{Email authentication for \dns@fmt{\dns@emaildomain}}}%
}

\NewDocumentCommand{\dnsemailentry}{m m m m}{%
  \dns@badge{#1} & \dns@fmt{#2} & \dns@fmt{#3} & \dnsstatus{#4} \\
}

% ============================================================
% Section 7: DNS response time comparison
% ============================================================

\NewDocumentEnvironment{dnslatency}{m}{%
  \def\dns@latencydomain{#1}%
  \begin{tabular}{@{} l l r r r @{}}
  \toprule
  \textbf{Resolver} & \textbf{IP} & \textbf{Min (ms)} & \textbf{Avg (ms)} & \textbf{Max (ms)} \\
  \midrule
}{%
  \bottomrule
  \end{tabular}
  \par\smallskip
  {\footnotesize\textit{DNS latency for \dns@fmt{\dns@latencydomain}}}%
}

\NewDocumentCommand{\dnslatencyentry}{m m m m m}{%
  \dns@fmt{#1} & \dns@fmt{#2} & #3 & #4 & #5 \\
}

% ============================================================
% Section 8: TTL timeline visualization (text-based)
% ============================================================

\newcommand{\dnsttlbar}[3]{%
  % #1 = label, #2 = TTL value, #3 = max TTL for scale
  \dns@fmt{#1}\enspace%
  {\color{dns@a}\rule{\dimexpr#2pt*200/#3\relax}{8pt}}%
  \enspace{\footnotesize\dns@fmt{#2}s}%
}

% ============================================================
% Section 9: Comparison table for DNS providers
% ============================================================

\NewDocumentEnvironment{dnsproviders}{}{%
  \begin{tabular}{@{} l l l l l @{}}
  \toprule
  \textbf{Provider} & \textbf{Primary} & \textbf{Secondary} & \textbf{DNSSEC} & \textbf{DoH/DoT} \\
  \midrule
}{%
  \bottomrule
  \end{tabular}
}

\NewDocumentCommand{\dnsprovider}{m m m m m}{%
  \textbf{#1} & \dns@fmt{#2} & \dns@fmt{#3} & #4 & #5 \\
}

% ============================================================
% Section 10: Utility commands
% ============================================================

% Domain name formatting
\NewDocumentCommand{\dnsdomain}{m}{\dns@fmt{#1}}

% IP address formatting
\NewDocumentCommand{\dnsip}{m}{\dns@fmt{#1}}

% TTL value with human-readable conversion
\NewDocumentCommand{\dnsttl}{m}{%
  \dns@fmt{#1}%
  \ifnum#1>86399\enspace(\the\numexpr#1/86400\relax d)\fi
  \ifnum#1<86400\ifnum#1>3599\enspace(\the\numexpr#1/3600\relax h)\fi\fi
  \ifnum#1<3600\ifnum#1>59\enspace(\the\numexpr#1/60\relax m)\fi\fi
  \ifnum#1<60\enspace(#1s)\fi
}

% Record class
\NewDocumentCommand{\dnsclass}{m}{\dns@fmt{\MakeUppercase{#1}}}

% RCODE formatting
\NewDocumentCommand{\dnsrcode}{m}{%
  \ifstrequal{#1}{NOERROR}{{\color{dns@propagated}\dns@fmt{NOERROR}}}{}%
  \ifstrequal{#1}{NXDOMAIN}{{\color{dns@failed}\dns@fmt{NXDOMAIN}}}{}%
  \ifstrequal{#1}{SERVFAIL}{{\color{dns@failed}\dns@fmt{SERVFAIL}}}{}%
  \ifstrequal{#1}{REFUSED}{{\color{dns@warning}\dns@fmt{REFUSED}}}{}%
  \ifstrequal{#1}{FORMERR}{{\color{dns@warning}\dns@fmt{FORMERR}}}{}%
}

% DNS flag formatting
\NewDocumentCommand{\dnsflag}{ m }{%
  \fbox{\footnotesize\dns@fmt{\MakeUppercase{#1}}}%
}

% Query/Response header
\NewDocumentCommand{\dnsheader}{m m m m}{%
  % #1=id, #2=opcode, #3=rcode, #4=flags
  \par\smallskip
  \dns@fmt{;; HEADER: id=#1, opcode=#2, rcode=}\dnsrcode{#3}\dns@fmt{, flags=#4}%
  \par\smallskip
}

\endinput
