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); 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))) __attribute__ ((format (printf, 2, 3)))
void void
CopyStringToBuffer(buffer *Dest, char *Format, ...) CopyStringToBuffer(buffer *Dest, char *Format, ...)
@ -180,6 +200,64 @@ CopyStringToBuffer(buffer *Dest, char *Format, ...)
Dest->Ptr += Length; 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 int
StringsDiffer(char *A, char *B) StringsDiffer(char *A, char *B)
{ {
@ -263,17 +341,6 @@ StringToColourHash(buffer *Buffer, char *String)
return(Buffer->Location); return(Buffer->Location);
} }
int
StringLength(char *String)
{
int i = 0;
while(String[i])
{
++i;
}
return i;
}
char * char *
SanitisePunctuation(char *String) 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].ID, Ref.isbn);
CopyString(ReferencesArray[UniqueRefs].Source, "%s (%s)", Ref.author, Ref.publisher); CopyString(ReferencesArray[UniqueRefs].Source, "%s (%s)", Ref.author, Ref.publisher);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else if(Ref.page && Ref.url && Ref.title) else if(Ref.page && Ref.url && Ref.title)
{ {
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.title); CopyStringNoFormat(ReferencesArray[UniqueRefs].Source, Ref.title);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.page); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.page);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else if(Ref.site && Ref.page && Ref.url) else if(Ref.site && Ref.page && Ref.url)
{ {
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.site); CopyStringNoFormat(ReferencesArray[UniqueRefs].Source, Ref.site);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.page); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.page);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else if(Ref.site && Ref.url && Ref.title) else if(Ref.site && Ref.url && Ref.title)
{ {
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.site); CopyStringNoFormat(ReferencesArray[UniqueRefs].Source, Ref.site);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else if(Ref.title && Ref.author && Ref.isbn) else if(Ref.title && Ref.author && Ref.isbn)
{ {
CopyString(ReferencesArray[UniqueRefs].ID, Ref.isbn); CopyString(ReferencesArray[UniqueRefs].ID, Ref.isbn);
CopyString(ReferencesArray[UniqueRefs].Source, Ref.author); 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 //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); CopyString(ReferencesArray[UniqueRefs].URL, "http://www.openisbn.com/isbn/%s", Ref.isbn);
} }
else if(Ref.url && Ref.article && Ref.author) 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].Source, Ref.author);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.article); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.article);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else if(Ref.url && Ref.title && Ref.author) 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].Source, Ref.author);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else if(Ref.url && Ref.title) else if(Ref.url && Ref.title)
{ {
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.title); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.title);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else if(Ref.site && Ref.url) else if(Ref.site && Ref.url)
{ {
CopyString(ReferencesArray[UniqueRefs].ID, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].ID, Ref.url);
CopyString(ReferencesArray[UniqueRefs].RefTitle, Ref.site); CopyStringNoFormat(ReferencesArray[UniqueRefs].RefTitle, Ref.site);
CopyString(ReferencesArray[UniqueRefs].URL, Ref.url); CopyStringNoFormat(ReferencesArray[UniqueRefs].URL, Ref.url);
} }
else else
{ {
@ -1173,8 +1240,10 @@ main(int ArgC, char **Args)
CopyStringToBuffer(&Title, CopyStringToBuffer(&Title,
" <div class=\"title %s\">\n" " <div class=\"title %s\">\n"
" <span class=\"episode_name\">%s</span>\n" " <span class=\"episode_name\">", HMML.metadata.project);
" <span id=\"focus-warn\">⚠ Click here to regain focus ⚠</span>\n", HMML.metadata.project, HMML.metadata.title); CopyStringToBufferHTMLSafe(&Title, HMML.metadata.title);
CopyStringToBuffer(&Title, "</span>\n"
" <span id=\"focus-warn\">⚠ Click here to regain focus ⚠</span>\n");
CopyStringToBuffer(&Player, CopyStringToBuffer(&Player,
" <div class=\"player_container\">\n" " <div class=\"player_container\">\n"
@ -1408,7 +1477,51 @@ AppendedIdentifier:
if(*InPtr) 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++; *Text.Ptr++ = *InPtr++;
break;
}
} }
} }
@ -1470,7 +1583,9 @@ QuoteIdentifier,
Anno->time); Anno->time);
if(!Anno->text[0]) 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); CopyStringToBuffer(&Text, "<sup>&#%d;</sup>", QuoteIdentifier);
++QuoteIdentifier; ++QuoteIdentifier;
@ -1583,16 +1698,19 @@ ReferencesArray[i].URL);
if(*ReferencesArray[i].Source) if(*ReferencesArray[i].Source)
{ {
CopyStringToBuffer(&ReferenceMenu, CopyStringToBuffer(&ReferenceMenu,
" <div class=\"source\">%s</div>\n" " <div class=\"source\">");
" <div class=\"ref_title\">%s</div>\n", CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].Source);
ReferencesArray[i].Source, CopyStringToBuffer(&ReferenceMenu, "</div>\n"
ReferencesArray[i].RefTitle); " <div class=\"ref_title\">");
CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].RefTitle);
CopyStringToBuffer(&ReferenceMenu, "</div>\n");
} }
else else
{ {
CopyStringToBuffer(&ReferenceMenu, CopyStringToBuffer(&ReferenceMenu,
" <div class=\"ref_title\">%s</div>\n", " <div class=\"ref_title\">");
ReferencesArray[i].RefTitle); CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].RefTitle);
CopyStringToBuffer(&ReferenceMenu, "</div>\n");
} }
CopyStringToBuffer(&ReferenceMenu, CopyStringToBuffer(&ReferenceMenu,
" </span>\n"); " </span>\n");
@ -1964,7 +2082,9 @@ CategoryMedium[j][2]
"<html>\n" "<html>\n"
" <head>\n" " <head>\n"
" <meta charset=\"UTF-8\">\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" "\n"
" <!-- Load the player -->\n" " <!-- Load the player -->\n"
" <script type=\"text/javascript\" src=\"player.js\"></script>\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" " <link rel=\"stylesheet\" type=\"text/css\" href=\"topics.css\">\n"
" </head>\n" " </head>\n"
" <body>\n", " <body>\n",
HMML.metadata.title,
HMML.metadata.project); HMML.metadata.project);
CopyStringToBuffer(&Script, CopyStringToBuffer(&Script,