hmml_to_html.c: Make strings HTML safe

Basically just rewriting < and > and others as &lt; and &gt; etc.
This commit is contained in:
Matt Mascarenhas 2017-06-08 00:47:47 +01:00
parent 97332baf52
commit 1389b4f414
1 changed files with 169 additions and 50 deletions

View File

@ -161,6 +161,26 @@ CopyString(char Dest[], char *Format, ...)
va_end(Args);
}
void
CopyStringNoFormat(char *Dest, char *String)
{
while(*String)
{
*Dest++ = *String++;
}
}
int
StringLength(char *String)
{
int i = 0;
while(String[i])
{
++i;
}
return i;
}
__attribute__ ((format (printf, 2, 3)))
void
CopyStringToBuffer(buffer *Dest, char *Format, ...)
@ -180,6 +200,64 @@ CopyStringToBuffer(buffer *Dest, char *Format, ...)
Dest->Ptr += Length;
}
void
CopyStringToBufferHTMLSafe(buffer *Dest, char *String)
{
while(*String)
{
if(Dest->Ptr - Dest->Location >= Dest->Size)
{
fprintf(stderr, "CopyStringToBufferHTMLSafe: %s cannot accommodate %d-character string\n", Dest->ID, StringLength(String));
__asm__("int3");
}
switch(*String)
{
case '<':
*Dest->Ptr++ = '&';
*Dest->Ptr++ = 'l';
*Dest->Ptr++ = 't';
*Dest->Ptr++ = ';';
String++;
break;
case '>':
*Dest->Ptr++ = '&';
*Dest->Ptr++ = 'g';
*Dest->Ptr++ = 't';
*Dest->Ptr++ = ';';
String++;
break;
case '&':
*Dest->Ptr++ = '&';
*Dest->Ptr++ = 'a';
*Dest->Ptr++ = 'm';
*Dest->Ptr++ = 'p';
*Dest->Ptr++ = ';';
String++;
break;
case '\"':
*Dest->Ptr++ = '&';
*Dest->Ptr++ = 'q';
*Dest->Ptr++ = 'u';
*Dest->Ptr++ = 'o';
*Dest->Ptr++ = 't';
*Dest->Ptr++ = ';';
String++;
break;
case '\'':
*Dest->Ptr++ = '&';
*Dest->Ptr++ = '#';
*Dest->Ptr++ = '3';
*Dest->Ptr++ = '9';
*Dest->Ptr++ = ';';
String++;
break;
default:
*Dest->Ptr++ = *String++;
break;
}
}
}
int
StringsDiffer(char *A, char *B)
{
@ -263,17 +341,6 @@ StringToColourHash(buffer *Buffer, char *String)
return(Buffer->Location);
}
int
StringLength(char *String)
{
int i = 0;
while(String[i])
{
++i;
}
return i;
}
char *
SanitisePunctuation(char *String)
{
@ -414,63 +481,63 @@ BuildReference(ref_info *ReferencesArray, int RefIdentifier, int UniqueRefs, HMM
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.isbn);
CopyString(ReferencesArray[UniqueRefs].Source, "%s (%s)", Ref.author, Ref.publisher);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else if(Ref.page && Ref.url && Ref.title)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.title);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.page);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].Source, Ref.title);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.page);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else if(Ref.site && Ref.page && Ref.url)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.site);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.page);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].Source, Ref.site);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.page);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else if(Ref.site && Ref.url && Ref.title)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.site);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].Source, Ref.site);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else if(Ref.title && Ref.author && Ref.isbn)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.isbn);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.author);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
//TODO(matt): Look into finding the best ISBN searcher the web has to offer
CopyString(ReferencesArray[UniqueRefs].URL, "http://www.openisbn.com/isbn/%s", Ref.isbn);
}
else if(Ref.url && Ref.article && Ref.author)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.author);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.article);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.article);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else if(Ref.url && Ref.title && Ref.author)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.author);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else if(Ref.url && Ref.title)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else if(Ref.site && Ref.url)
{
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.site);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.site);
CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
}
else
{
@ -1173,8 +1240,10 @@ main(int ArgC, char **Args)
CopyStringToBuffer(&Title,
" <div class=\"title %s\">\n"
" <span class=\"episode_name\">%s</span>\n"
" <span id=\"focus-warn\">⚠ Click here to regain focus ⚠</span>\n", HMML.metadata.project, HMML.metadata.title);
" <span class=\"episode_name\">", HMML.metadata.project);
CopyStringToBufferHTMLSafe(&Title, HMML.metadata.title);
CopyStringToBuffer(&Title, "</span>\n"
" <span id=\"focus-warn\">⚠ Click here to regain focus ⚠</span>\n");
CopyStringToBuffer(&Player,
" <div class=\"player_container\">\n"
@ -1408,7 +1477,51 @@ AppendedIdentifier:
if(*InPtr)
{
switch(*InPtr)
{
case '<':
*Text.Ptr++ = '&';
*Text.Ptr++ = 'l';
*Text.Ptr++ = 't';
*Text.Ptr++ = ';';
InPtr++;
break;
case '>':
*Text.Ptr++ = '&';
*Text.Ptr++ = 'g';
*Text.Ptr++ = 't';
*Text.Ptr++ = ';';
InPtr++;
break;
case '&':
*Text.Ptr++ = '&';
*Text.Ptr++ = 'a';
*Text.Ptr++ = 'm';
*Text.Ptr++ = 'p';
*Text.Ptr++ = ';';
InPtr++;
break;
case '\"':
*Text.Ptr++ = '&';
*Text.Ptr++ = 'q';
*Text.Ptr++ = 'u';
*Text.Ptr++ = 'o';
*Text.Ptr++ = 't';
*Text.Ptr++ = ';';
InPtr++;
break;
case '\'':
*Text.Ptr++ = '&';
*Text.Ptr++ = '#';
*Text.Ptr++ = '3';
*Text.Ptr++ = '9';
*Text.Ptr++ = ';';
InPtr++;
break;
default:
*Text.Ptr++ = *InPtr++;
break;
}
}
}
@ -1470,7 +1583,9 @@ QuoteIdentifier,
Anno->time);
if(!Anno->text[0])
{
CopyStringToBuffer(&Text, "&#8220;%s&#8221;", QuoteInfo.Text);
CopyStringToBuffer(&Text, "&#8220;");
CopyStringToBufferHTMLSafe(&Text, QuoteInfo.Text);
CopyStringToBuffer(&Text, "&#8221;");
}
CopyStringToBuffer(&Text, "<sup>&#%d;</sup>", QuoteIdentifier);
++QuoteIdentifier;
@ -1583,16 +1698,19 @@ ReferencesArray[i].URL);
if(*ReferencesArray[i].Source)
{
CopyStringToBuffer(&ReferenceMenu,
" <div class=\"source\">%s</div>\n"
" <div class=\"ref_title\">%s</div>\n",
ReferencesArray[i].Source,
ReferencesArray[i].RefTitle);
" <div class=\"source\">");
CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].Source);
CopyStringToBuffer(&ReferenceMenu, "</div>\n"
" <div class=\"ref_title\">");
CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].RefTitle);
CopyStringToBuffer(&ReferenceMenu, "</div>\n");
}
else
{
CopyStringToBuffer(&ReferenceMenu,
" <div class=\"ref_title\">%s</div>\n",
ReferencesArray[i].RefTitle);
" <div class=\"ref_title\">");
CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].RefTitle);
CopyStringToBuffer(&ReferenceMenu, "</div>\n");
}
CopyStringToBuffer(&ReferenceMenu,
" </span>\n");
@ -1964,7 +2082,9 @@ CategoryMedium[j][2]
"<html>\n"
" <head>\n"
" <meta charset=\"UTF-8\">\n"
" <title>%s</title>\n" // TODO(matt): Add the full name of the project, parsed from a config
" <title>");
CopyStringToBufferHTMLSafe(&Master, HMML.metadata.title);
CopyStringToBuffer(&Master, "</title>\n" // TODO(matt): Add the full name of the project, parsed from a config
"\n"
" <!-- Load the player -->\n"
" <script type=\"text/javascript\" src=\"player.js\"></script>\n"
@ -1973,7 +2093,6 @@ CategoryMedium[j][2]
" <link rel=\"stylesheet\" type=\"text/css\" href=\"topics.css\">\n"
" </head>\n"
" <body>\n",
HMML.metadata.title,
HMML.metadata.project);
CopyStringToBuffer(&Script,