diff --git a/hmml_to_html/hmml_to_html.c b/hmml_to_html/hmml_to_html.c index ccf9aa9..c07f841 100644 --- a/hmml_to_html/hmml_to_html.c +++ b/hmml_to_html/hmml_to_html.c @@ -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, "
\n" -" %s\n" -" ⚠ Click here to regain focus ⚠\n", HMML.metadata.project, HMML.metadata.title); +" ", HMML.metadata.project); + CopyStringToBufferHTMLSafe(&Title, HMML.metadata.title); + CopyStringToBuffer(&Title, "\n" +" ⚠ Click here to regain focus ⚠\n"); CopyStringToBuffer(&Player, "
\n" @@ -1408,7 +1477,51 @@ AppendedIdentifier: if(*InPtr) { - *Text.Ptr++ = *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, "“%s”", QuoteInfo.Text); + CopyStringToBuffer(&Text, "“"); + CopyStringToBufferHTMLSafe(&Text, QuoteInfo.Text); + CopyStringToBuffer(&Text, "”"); } CopyStringToBuffer(&Text, "&#%d;", QuoteIdentifier); ++QuoteIdentifier; @@ -1583,16 +1698,19 @@ ReferencesArray[i].URL); if(*ReferencesArray[i].Source) { CopyStringToBuffer(&ReferenceMenu, -"
%s
\n" -"
%s
\n", -ReferencesArray[i].Source, -ReferencesArray[i].RefTitle); +"
"); + CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].Source); + CopyStringToBuffer(&ReferenceMenu, "
\n" +"
"); + CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].RefTitle); + CopyStringToBuffer(&ReferenceMenu, "
\n"); } else { CopyStringToBuffer(&ReferenceMenu, -"
%s
\n", -ReferencesArray[i].RefTitle); +"
"); + CopyStringToBufferHTMLSafe(&ReferenceMenu, ReferencesArray[i].RefTitle); + CopyStringToBuffer(&ReferenceMenu, "
\n"); } CopyStringToBuffer(&ReferenceMenu, " \n"); @@ -1964,7 +2082,9 @@ CategoryMedium[j][2] "\n" " \n" " \n" -" %s\n" // TODO(matt): Add the full name of the project, parsed from a config +" "); + CopyStringToBufferHTMLSafe(&Master, HMML.metadata.title); + CopyStringToBuffer(&Master, "\n" // TODO(matt): Add the full name of the project, parsed from a config "\n" " \n" " \n" @@ -1973,7 +2093,6 @@ CategoryMedium[j][2] " \n" " \n" " \n", -HMML.metadata.title, HMML.metadata.project); CopyStringToBuffer(&Script,