[Tex/LaTex] Using \newcommand to display user input that may contain special characters that need to be escaped

charactersinputinput-encodingsmacros

I don't know much about LaTeX right now, but I need to be able to use it to generate dynamic PDF documents using C#.

For the most part, everything is cool and works the way I want it to work.

Someone gives me a static LaTeX document to use as a base template, and I use C# to write in all the dynamic data that comes from the web server and database.

For example, this is what I would get from a LaTeX dev:

\documentclass[letter,landscape]{report}

\newcommand{\ReportTitle} {Summary Report }
\newcommand{\ReportAuthor}{Mister San }

\pdfinfo{
    /Title   (\ReportTitle)
    /Author  (\ReportAuthor)
    /Subject (Generated by \ReportAuthor on \today)
}

\begin{document}
    \ReportTitle \\
    By: \ReportAuthor \\
\end{document}

I will then take that LaTeX code (markup?) and make it dynamic using C# / ASP.NET MVC (the technology I use there doesn't matter much for this question). It'll end up looking like this once I'm done with it:

\documentclass[letter,landscape]{report}

\newcommand{\ReportTitle} {@Model.ReportTitle }
\newcommand{\ReportAuthor}{@Model.ReportAuthor }

\pdfinfo{
    /Title   (\ReportTitle)
    /Author  (\ReportAuthor)
    /Subject (Generated by \ReportAuthor on \today)
}

\begin{document}
    \ReportTitle \\
    By: \ReportAuthor \\
\end{document}

Now, \ReportTitle and \ReportAuthor are dynamic and based on whatever's in the database. This normally works as-is, but there's a specific issue I've been encountering that I don't know what to do to fix it.

The text that goes into the fields \ReportTitle and \ReportAuthor comes from what users input, and they can use any characters they want. If a user inputted a \ReportTitle like "~My_$uper_Report~" – the LaTeX markup will become invalid since reserved characters were chosen.

I know you can escape reserved characters so a \ReportTitle of "Standard_Report" will become:

\newcommand{\ReportTitle} {Standard\_Report }

I wrote a method in C# that replaces all the special LaTeX characters with their escaped counterparts.

This works sometimes (which is odd, usually things work or they don't).

It seems like if I have too many escaped characters like this:

\newcommand{\ReportTitle} {\# \$ \% \& \~ \_ \^ \{ \} \backslash}

I get an out of memory error.

I have no idea why I am unable to basically store a space-separated list of escaped special characters in a \newcommand.

Does anyone know why I can't make that previous example work? Is there a better way to go about doing this?

Is there an existing tool that encodes user input so you don't have to escape everything yourself and check for LaTeX injection attacks?

By the way, this is the error I get:

./main.tex:7: TeX capacity exceeded, sorry [input stack size=5000].
\@inmathwarn ...latex@warning {Command \protect #1
invalid in math mode}\fi l.7        /Title   (\ReportTitle)

****Edit:****
A user posted a comment (but then deleted it) suggesting to use something like this:

\detokenize\expandafter{\ReportTitle}

Which actually allowed the Report to compile and display the reserved characters, but unfortunately it also added double quote characters around each escaped character, which isn't acceptable. Thanks though. I'm sure I'll eventually figure it out, or another user on here will know what to do.

Best Answer

\# \$ \% \& \~ \_ \^ \{ \} 

are very different types of commands, \% makes a percent but \^ does not make ^ it is a command that takes an argument \^{a} constructing accented letters.

You can use

\detokenize{@Model.ReportTitle}

then you basically only need to quote \( \} and \% to ensure that the construct has balanced braces. and add

\usepackage[T1]{fontenc}

so that you get a slightly more normal font encoding in which the ascii characters print as themselves.

If you are never going to insert comments in to the document you can make % a normal character globally so you don't need \% just add

 \catcode`\%=12

to the preamble (after any packages are loaded or comments in the package will break)