Patchwork lib: fwts_log_html: convert misc ASCII chars to HTML mnemonics

login
register
mail settings
Submitter Colin King
Date June 11, 2012, 10:01 a.m.
Message ID <1339408910-31944-1-git-send-email-colin.king@canonical.com>
Download mbox | patch
Permalink /patch/164115/
State Accepted
Headers show

Comments

Colin King - June 11, 2012, 10:01 a.m.
From: Colin Ian King <colin.king@canonical.com>

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 src/lib/src/fwts_log_html.c |  207 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 198 insertions(+), 9 deletions(-)
Chris Van Hoof - June 11, 2012, 3:57 p.m.
On 06/11/2012 06:01 AM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
> 
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>  src/lib/src/fwts_log_html.c |  207 +++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 198 insertions(+), 9 deletions(-)
> 
> diff --git a/src/lib/src/fwts_log_html.c b/src/lib/src/fwts_log_html.c
> index 1ca79b8..a040b43 100644
> --- a/src/lib/src/fwts_log_html.c
> +++ b/src/lib/src/fwts_log_html.c
> @@ -34,6 +34,133 @@ typedef struct {
>  	const char *name;
>  } fwts_log_html_stack_t;
>  
> +typedef struct {
> +	unsigned char	ch;	/* ASCII */
> +	char *		html;	/* HTML equivalent */
> +} fwts_log_html_ascii_t;
> +
> +/*
> + * ASCII to HTML conversion table:
> + * ISO 10646, ISO 8879, ISO 8859-1 Latin alphabet No. 1
> + * Browser support: All browsers
> + */
> +static fwts_log_html_ascii_t fwts_log_html_ascii_table[] = {
> +	{ '"',	"&quot;" },
> +	{ '&', 	"&amp;" },
> +	{ '<', 	"&lt;" },
> +	{ '>',	"&gt;" },
> +	{ '{',	"&#123;" },
> +	{ '|',	"&#124;" },
> +	{ '}',	"&#125;" },
> +	{ '~',	"&#126;" },
> +
> +	{ 160,	"&nbsp;" },
> +	{ 161,	"&iexl;" },
> +	{ 162,	"&cent;" },
> +	{ 163,	"&pound;" },
> +	{ 164,	"&curren;" },
> +	{ 165,	"&yen;" },
> +	{ 166,	"&brvbar;" },
> +	{ 167,	"&sect;" },
> +	{ 168,	"&uml;" },
> +	{ 169,	"&copy;" },
> +	{ 170,	"&ordf;" },
> +	{ 171,	"&laquo;" },
> +	{ 172,	"&not;" },
> +	{ 173,	"&shy;" },
> +	{ 174,	"&reg;" },
> +	{ 175,	"&macr;" },
> +
> +	{ 176,	"&deg;" },
> +	{ 177,	"&plusmn;" },
> +	{ 178,	"&sup2;" },
> +	{ 179,	"&sup3;" },
> +	{ 180,	"&acute;" },
> +	{ 181,	"&micro;" },
> +	{ 182,	"&para;" },
> +	{ 183,	"&middot;" },
> +	{ 184,	"&cedil;" },
> +	{ 185,	"&sup1;" },
> +	{ 186,	"&ordm;" },
> +	{ 187,	"&raquo;" },
> +	{ 187,	"&frac14;" },
> +	{ 189,	"&frac12;" },
> +	{ 190,	"&frac34;" },
> +	{ 191,	"&iquest;" },
> +
> +	/* Probably never used, but here in case */
> +
> +	{ 192,	"&Agrave;" },
> +	{ 193,	"&Aacute;" },
> +	{ 194,	"&Acirc;" },
> +	{ 195,	"&Atilde;" },
> +	{ 196,	"&Auml;" },
> +	{ 197,	"&Aring;" },
> +	{ 198,	"&AElig;" },
> +	{ 199,	"&Ccedil;" },
> +	{ 200,	"&Egrave;" },
> +	{ 201,	"&Eacute;" },
> +	{ 202,	"&Ecirc;" },
> +	{ 203,	"&Euml;" },
> +	{ 204,	"&lgrave;" },
> +	{ 205,	"&lacute;" },
> +	{ 206,	"&lcirc;" },
> +	{ 207,	"&luml;" },
> +
> +	{ 208,	"&ETH;" },
> +	{ 209,	"&Ntilde;" },
> +	{ 210,	"&Ograve;" },
> +	{ 211,	"&Oacute;" },
> +	{ 212,	"&Ocirc;" },
> +	{ 213,	"&Otilde;" },
> +	{ 214,	"&Ouml;" },
> +	{ 215,	"&times;" },
> +	{ 216,	"&Oslash;" },
> +	{ 217,	"&Ugrave;" },
> +	{ 218,	"&Uacute;" },
> +	{ 219,	"&Ucirc;" },
> +	{ 220,	"&Uuml;" },
> +	{ 221,	"&Yacute;" },
> +	{ 222,	"&THORN;" },
> +	{ 223,	"&szlig;" },
> +
> +	{ 224,	"&agrave;" },
> +	{ 225,	"&aacute;" },
> +	{ 226,	"&acirc;" },
> +	{ 227,	"&atilde;" },
> +	{ 228,	"&auml;" },
> +	{ 229,	"&aring;" },
> +	{ 230,	"&aelig;" },
> +	{ 231,	"&ccedil;" },
> +	{ 232,	"&egrave;" },
> +	{ 233,	"&eacute;" },
> +	{ 234,	"&ecirc;" },
> +	{ 235,	"&emuml;" },
> +	{ 236,	"&igrave;" },
> +	{ 237,	"&iacute;" },
> +	{ 238,	"&icirc;" },
> +	{ 239,	"&iuml;" },
> +
> +	{ 240,	"&eth;" },
> +	{ 241,	"&ntilde;" },
> +	{ 242,	"&ograve;" },
> +	{ 243,	"&oacute;" },
> +	{ 244,	"&ocirc;" },
> +	{ 245,	"&otilde;" },
> +	{ 246,	"&ouml;" },
> +	{ 247,	"&divide;" },
> +	{ 248,	"&oslash;" },
> +	{ 249,	"&ugrave;" },
> +	{ 250,	"&uacute;" },
> +	{ 251,	"&ucirc;" },
> +	{ 252,	"&uuml;" },
> +	{ 253,	"&yacute;" },
> +	{ 254,	"&thorn;" },
> +	{ 255,	"&yuml;" },
> +
> +	{ 0, 	NULL },
> +};
> +
>  static fwts_log_html_stack_t html_stack[MAX_HTML_STACK];
>  static int html_stack_index = 0;
>  
> @@ -49,6 +176,58 @@ static void fwts_log_html(fwts_log_file *log_file, const char *fmt, ...)
>  	va_end(args);
>  }
>  
> +/*
> + *  fwts_log_html_convert_ascii()
> + *	return a static string containing any convertion from ASCII to a
> + *	HTML representation of char ch.  If no conversion needed, just
> + *	return a string containing the ch.
> + */
> +static char *fwts_log_html_convert_ascii(const char ch)
> +{
> +	int i;
> +	static char buf[2];
> +
> +	for (i = 0; fwts_log_html_ascii_table[i].html != NULL; i++) {
> +		if (fwts_log_html_ascii_table[i].ch == ch)
> +			return fwts_log_html_ascii_table[i].html;
> +	}
> +
> +	/* No mapping, just return string containing ch */
> +	buf[0] = ch;
> +	buf[1] = '\0';
> +
> +	return buf;
> +}
> +
> +/*
> + *  fwts_log_html_convert_ascii_str()
> + *	convert an ASCII string into a HTML encoded string. The returned
> + *	string needs free'ing once finished with.
> + */
> +static char *fwts_log_html_convert_ascii_str(const char *buffer)
> +{
> +	const char *str1;
> +	char *converted;
> +	size_t len = 0;
> +
> +	/* Step 1, figure out how much space we need */
> +	for (str1 = buffer; *str1; str1++) {
> +		char *str = fwts_log_html_convert_ascii(*str1);
> +		len += strlen(str);
> +	}
> +
> +	if ((converted = calloc(len + 1, 1)) == NULL)
> +		return NULL;
> +
> +	/* Step 2, convert */
> +	for (str1 = buffer; *str1; str1++) {
> +		char *str = fwts_log_html_convert_ascii(*str1);
> +		strcat(converted, str);
> +	}
> +
> +	return converted;
> +}
> +
>  
>  /*
>   *  fwts_log_print_html()
> @@ -67,6 +246,7 @@ static int fwts_log_print_html(
>  	char *style;
>  	char *code_start;
>  	char *code_end;
> +	char *html_converted;
>  
>  	if (!((field & LOG_FIELD_MASK) & fwts_log_filter))
>  		return 0;
> @@ -74,6 +254,12 @@ static int fwts_log_print_html(
>  	if (field & (LOG_NEWLINE | LOG_SEPARATOR | LOG_DEBUG))
>  		return 0;
>  
> +	if ((html_converted = fwts_log_html_convert_ascii_str(buffer)) == NULL) {
> +		/* We can't report an error via the logging mechanism in case we loop */
> +		fprintf(stderr, "Out of memory converting html.\n");
> +		exit(EXIT_FAILURE);
> +	}
> +
>  	fwts_log_html(log_file, "<TR>\n");
>  
>  	if (field & LOG_VERBATUM) {
> @@ -87,23 +273,24 @@ static int fwts_log_print_html(
>  	switch (field & LOG_FIELD_MASK) {
>  	case LOG_ERROR:
>  		fwts_log_html(log_file, "  <TD class=style_error>Error</TD>"
> -			"<TD COLSPAN=2>%s</TD>\n", buffer);
> +			"<TD COLSPAN=2>%s</TD>\n", html_converted);
>  		break;
>  	case LOG_WARNING:
>  		fwts_log_html(log_file, "  <TD class=style_error>Warning</TD>"
>  			"<TD COLSPAN=2 class=style_advice_info>%s%s%s</TD>\n",
> -			code_start, buffer, code_end);
> +			code_start, html_converted, code_end);
>  		break;
>  	case LOG_HEADING:
>  		fwts_log_html(log_file, "<TD COLSPAN=2 class=style_heading>%s%s%s</TD>\n",
> -			code_start, buffer, code_end);
> +			code_start, html_converted, code_end);
>  		break;
>  	case LOG_INFO:
>  		fwts_log_html(log_file, "  <TD></TD><TD COLSPAN=2 class=style_infos>%s%s%s</TD>\n",
> -			code_start, buffer, code_end);
> +			code_start, html_converted, code_end);
>  		break;
>  	case LOG_PASSED:
> -		fwts_log_html(log_file, "<TD class=style_passed>PASSED</TD><TD>%s</TD>\n", buffer);
> +		fwts_log_html(log_file, "<TD class=style_passed>PASSED</TD><TD>%s</TD>\n",
> +			html_converted);
>  		break;
>  	case LOG_FAILED:
>  		switch (level) {
> @@ -128,30 +315,32 @@ static int fwts_log_print_html(
>  		str = fwts_log_level_to_str(level);
>  
>  		fwts_log_html(log_file, "  <TD%s>%s [%s]</TD>\n", style, *status ? status : "", str);
> -		fwts_log_html(log_file, "  <TD>%s</TD>\n", buffer);
> +		fwts_log_html(log_file, "  <TD>%s</TD>\n", html_converted);
>  		break;
>  
>  	case LOG_SKIPPED:
>  		fwts_log_html(log_file, "<TD class=style_skipped>Skipped</TD>"
> -			"<TD>%s%s%s</TD>\n", code_start, buffer, code_end);
> +			"<TD>%s%s%s</TD>\n", code_start, html_converted, code_end);
>  		break;
>  
>  	case LOG_SUMMARY:
>  		fwts_log_html(log_file, "  <TD></TD>"
>  			"<TD COLSPAN=2 class=style_summary>%s%s%s</TD>\n",
> -			code_start, buffer, code_end);
> +			code_start, html_converted, code_end);
>  		break;
>  
>  	case LOG_ADVICE:
>  		fwts_log_html(log_file, "  <TD class=style_advice>Advice</TD>"
>  			"<TD COLSPAN=2 class=style_advice_info>%s%s%s</TD>\n",
> -			code_start, buffer, code_end);
> +			code_start, html_converted, code_end);
>  		break;
>  
>  	default:
>  		break;
>  	}
>  
> +	free(html_converted);
> +
>  	fwts_log_html(log_file, "</TR>\n");
>  	fflush(log_file->fp);

Looks good to me, and renders with no issues or warnings while generating:

http://ouwish.com/~vanhoof/pickup/cking/fwts_2012-06-11/results.html

Tested-by: Chris Van Hoof <vanhoof@canonical.com>
Keng-Yu Lin - June 13, 2012, 9:52 a.m.
On Mon, Jun 11, 2012 at 6:01 PM, Colin King <colin.king@canonical.com> wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>  src/lib/src/fwts_log_html.c |  207 +++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 198 insertions(+), 9 deletions(-)
>
> diff --git a/src/lib/src/fwts_log_html.c b/src/lib/src/fwts_log_html.c
> index 1ca79b8..a040b43 100644
> --- a/src/lib/src/fwts_log_html.c
> +++ b/src/lib/src/fwts_log_html.c
> @@ -34,6 +34,133 @@ typedef struct {
>        const char *name;
>  } fwts_log_html_stack_t;
>
> +typedef struct {
> +       unsigned char   ch;     /* ASCII */
> +       char *          html;   /* HTML equivalent */
> +} fwts_log_html_ascii_t;
> +
> +/*
> + * ASCII to HTML conversion table:
> + * ISO 10646, ISO 8879, ISO 8859-1 Latin alphabet No. 1
> + * Browser support: All browsers
> + */
> +static fwts_log_html_ascii_t fwts_log_html_ascii_table[] = {
> +       { '"',  "&quot;" },
> +       { '&',  "&amp;" },
> +       { '<',  "&lt;" },
> +       { '>',  "&gt;" },
> +       { '{',  "&#123;" },
> +       { '|',  "&#124;" },
> +       { '}',  "&#125;" },
> +       { '~',  "&#126;" },
> +
> +       { 160,  "&nbsp;" },
> +       { 161,  "&iexl;" },
> +       { 162,  "&cent;" },
> +       { 163,  "&pound;" },
> +       { 164,  "&curren;" },
> +       { 165,  "&yen;" },
> +       { 166,  "&brvbar;" },
> +       { 167,  "&sect;" },
> +       { 168,  "&uml;" },
> +       { 169,  "&copy;" },
> +       { 170,  "&ordf;" },
> +       { 171,  "&laquo;" },
> +       { 172,  "&not;" },
> +       { 173,  "&shy;" },
> +       { 174,  "&reg;" },
> +       { 175,  "&macr;" },
> +
> +       { 176,  "&deg;" },
> +       { 177,  "&plusmn;" },
> +       { 178,  "&sup2;" },
> +       { 179,  "&sup3;" },
> +       { 180,  "&acute;" },
> +       { 181,  "&micro;" },
> +       { 182,  "&para;" },
> +       { 183,  "&middot;" },
> +       { 184,  "&cedil;" },
> +       { 185,  "&sup1;" },
> +       { 186,  "&ordm;" },
> +       { 187,  "&raquo;" },
> +       { 187,  "&frac14;" },
> +       { 189,  "&frac12;" },
> +       { 190,  "&frac34;" },
> +       { 191,  "&iquest;" },
> +
> +       /* Probably never used, but here in case */
> +
> +       { 192,  "&Agrave;" },
> +       { 193,  "&Aacute;" },
> +       { 194,  "&Acirc;" },
> +       { 195,  "&Atilde;" },
> +       { 196,  "&Auml;" },
> +       { 197,  "&Aring;" },
> +       { 198,  "&AElig;" },
> +       { 199,  "&Ccedil;" },
> +       { 200,  "&Egrave;" },
> +       { 201,  "&Eacute;" },
> +       { 202,  "&Ecirc;" },
> +       { 203,  "&Euml;" },
> +       { 204,  "&lgrave;" },
> +       { 205,  "&lacute;" },
> +       { 206,  "&lcirc;" },
> +       { 207,  "&luml;" },
> +
> +       { 208,  "&ETH;" },
> +       { 209,  "&Ntilde;" },
> +       { 210,  "&Ograve;" },
> +       { 211,  "&Oacute;" },
> +       { 212,  "&Ocirc;" },
> +       { 213,  "&Otilde;" },
> +       { 214,  "&Ouml;" },
> +       { 215,  "&times;" },
> +       { 216,  "&Oslash;" },
> +       { 217,  "&Ugrave;" },
> +       { 218,  "&Uacute;" },
> +       { 219,  "&Ucirc;" },
> +       { 220,  "&Uuml;" },
> +       { 221,  "&Yacute;" },
> +       { 222,  "&THORN;" },
> +       { 223,  "&szlig;" },
> +
> +       { 224,  "&agrave;" },
> +       { 225,  "&aacute;" },
> +       { 226,  "&acirc;" },
> +       { 227,  "&atilde;" },
> +       { 228,  "&auml;" },
> +       { 229,  "&aring;" },
> +       { 230,  "&aelig;" },
> +       { 231,  "&ccedil;" },
> +       { 232,  "&egrave;" },
> +       { 233,  "&eacute;" },
> +       { 234,  "&ecirc;" },
> +       { 235,  "&emuml;" },
> +       { 236,  "&igrave;" },
> +       { 237,  "&iacute;" },
> +       { 238,  "&icirc;" },
> +       { 239,  "&iuml;" },
> +
> +       { 240,  "&eth;" },
> +       { 241,  "&ntilde;" },
> +       { 242,  "&ograve;" },
> +       { 243,  "&oacute;" },
> +       { 244,  "&ocirc;" },
> +       { 245,  "&otilde;" },
> +       { 246,  "&ouml;" },
> +       { 247,  "&divide;" },
> +       { 248,  "&oslash;" },
> +       { 249,  "&ugrave;" },
> +       { 250,  "&uacute;" },
> +       { 251,  "&ucirc;" },
> +       { 252,  "&uuml;" },
> +       { 253,  "&yacute;" },
> +       { 254,  "&thorn;" },
> +       { 255,  "&yuml;" },
> +
> +       { 0,    NULL },
> +};
> +
>  static fwts_log_html_stack_t html_stack[MAX_HTML_STACK];
>  static int html_stack_index = 0;
>
> @@ -49,6 +176,58 @@ static void fwts_log_html(fwts_log_file *log_file, const char *fmt, ...)
>        va_end(args);
>  }
>
> +/*
> + *  fwts_log_html_convert_ascii()
> + *     return a static string containing any convertion from ASCII to a
> + *     HTML representation of char ch.  If no conversion needed, just
> + *     return a string containing the ch.
> + */
> +static char *fwts_log_html_convert_ascii(const char ch)
> +{
> +       int i;
> +       static char buf[2];
> +
> +       for (i = 0; fwts_log_html_ascii_table[i].html != NULL; i++) {
> +               if (fwts_log_html_ascii_table[i].ch == ch)
> +                       return fwts_log_html_ascii_table[i].html;
> +       }
> +
> +       /* No mapping, just return string containing ch */
> +       buf[0] = ch;
> +       buf[1] = '\0';
> +
> +       return buf;
> +}
> +
> +/*
> + *  fwts_log_html_convert_ascii_str()
> + *     convert an ASCII string into a HTML encoded string. The returned
> + *     string needs free'ing once finished with.
> + */
> +static char *fwts_log_html_convert_ascii_str(const char *buffer)
> +{
> +       const char *str1;
> +       char *converted;
> +       size_t len = 0;
> +
> +       /* Step 1, figure out how much space we need */
> +       for (str1 = buffer; *str1; str1++) {
> +               char *str = fwts_log_html_convert_ascii(*str1);
> +               len += strlen(str);
> +       }
> +
> +       if ((converted = calloc(len + 1, 1)) == NULL)
> +               return NULL;
> +
> +       /* Step 2, convert */
> +       for (str1 = buffer; *str1; str1++) {
> +               char *str = fwts_log_html_convert_ascii(*str1);
> +               strcat(converted, str);
> +       }
> +
> +       return converted;
> +}
> +
>
>  /*
>  *  fwts_log_print_html()
> @@ -67,6 +246,7 @@ static int fwts_log_print_html(
>        char *style;
>        char *code_start;
>        char *code_end;
> +       char *html_converted;
>
>        if (!((field & LOG_FIELD_MASK) & fwts_log_filter))
>                return 0;
> @@ -74,6 +254,12 @@ static int fwts_log_print_html(
>        if (field & (LOG_NEWLINE | LOG_SEPARATOR | LOG_DEBUG))
>                return 0;
>
> +       if ((html_converted = fwts_log_html_convert_ascii_str(buffer)) == NULL) {
> +               /* We can't report an error via the logging mechanism in case we loop */
> +               fprintf(stderr, "Out of memory converting html.\n");
> +               exit(EXIT_FAILURE);
> +       }
> +
>        fwts_log_html(log_file, "<TR>\n");
>
>        if (field & LOG_VERBATUM) {
> @@ -87,23 +273,24 @@ static int fwts_log_print_html(
>        switch (field & LOG_FIELD_MASK) {
>        case LOG_ERROR:
>                fwts_log_html(log_file, "  <TD class=style_error>Error</TD>"
> -                       "<TD COLSPAN=2>%s</TD>\n", buffer);
> +                       "<TD COLSPAN=2>%s</TD>\n", html_converted);
>                break;
>        case LOG_WARNING:
>                fwts_log_html(log_file, "  <TD class=style_error>Warning</TD>"
>                        "<TD COLSPAN=2 class=style_advice_info>%s%s%s</TD>\n",
> -                       code_start, buffer, code_end);
> +                       code_start, html_converted, code_end);
>                break;
>        case LOG_HEADING:
>                fwts_log_html(log_file, "<TD COLSPAN=2 class=style_heading>%s%s%s</TD>\n",
> -                       code_start, buffer, code_end);
> +                       code_start, html_converted, code_end);
>                break;
>        case LOG_INFO:
>                fwts_log_html(log_file, "  <TD></TD><TD COLSPAN=2 class=style_infos>%s%s%s</TD>\n",
> -                       code_start, buffer, code_end);
> +                       code_start, html_converted, code_end);
>                break;
>        case LOG_PASSED:
> -               fwts_log_html(log_file, "<TD class=style_passed>PASSED</TD><TD>%s</TD>\n", buffer);
> +               fwts_log_html(log_file, "<TD class=style_passed>PASSED</TD><TD>%s</TD>\n",
> +                       html_converted);
>                break;
>        case LOG_FAILED:
>                switch (level) {
> @@ -128,30 +315,32 @@ static int fwts_log_print_html(
>                str = fwts_log_level_to_str(level);
>
>                fwts_log_html(log_file, "  <TD%s>%s [%s]</TD>\n", style, *status ? status : "", str);
> -               fwts_log_html(log_file, "  <TD>%s</TD>\n", buffer);
> +               fwts_log_html(log_file, "  <TD>%s</TD>\n", html_converted);
>                break;
>
>        case LOG_SKIPPED:
>                fwts_log_html(log_file, "<TD class=style_skipped>Skipped</TD>"
> -                       "<TD>%s%s%s</TD>\n", code_start, buffer, code_end);
> +                       "<TD>%s%s%s</TD>\n", code_start, html_converted, code_end);
>                break;
>
>        case LOG_SUMMARY:
>                fwts_log_html(log_file, "  <TD></TD>"
>                        "<TD COLSPAN=2 class=style_summary>%s%s%s</TD>\n",
> -                       code_start, buffer, code_end);
> +                       code_start, html_converted, code_end);
>                break;
>
>        case LOG_ADVICE:
>                fwts_log_html(log_file, "  <TD class=style_advice>Advice</TD>"
>                        "<TD COLSPAN=2 class=style_advice_info>%s%s%s</TD>\n",
> -                       code_start, buffer, code_end);
> +                       code_start, html_converted, code_end);
>                break;
>
>        default:
>                break;
>        }
>
> +       free(html_converted);
> +
>        fwts_log_html(log_file, "</TR>\n");
>        fflush(log_file->fp);
>
> --
> 1.7.10.4
>
Acked-by: Keng-Yu Lin <kengyu@canonical.com>
Alex Hung - June 18, 2012, 2:56 a.m.
On 06/11/2012 06:01 PM, Colin King wrote:
> From: Colin Ian King<colin.king@canonical.com>
>
> Signed-off-by: Colin Ian King<colin.king@canonical.com>
> ---
>   src/lib/src/fwts_log_html.c |  207 +++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 198 insertions(+), 9 deletions(-)
>
> diff --git a/src/lib/src/fwts_log_html.c b/src/lib/src/fwts_log_html.c
> index 1ca79b8..a040b43 100644
> --- a/src/lib/src/fwts_log_html.c
> +++ b/src/lib/src/fwts_log_html.c

Acked-by: Alex Hung <alex.hung@canonical.com>

Patch

diff --git a/src/lib/src/fwts_log_html.c b/src/lib/src/fwts_log_html.c
index 1ca79b8..a040b43 100644
--- a/src/lib/src/fwts_log_html.c
+++ b/src/lib/src/fwts_log_html.c
@@ -34,6 +34,133 @@  typedef struct {
 	const char *name;
 } fwts_log_html_stack_t;
 
+typedef struct {
+	unsigned char	ch;	/* ASCII */
+	char *		html;	/* HTML equivalent */
+} fwts_log_html_ascii_t;
+
+/*
+ * ASCII to HTML conversion table:
+ * ISO 10646, ISO 8879, ISO 8859-1 Latin alphabet No. 1
+ * Browser support: All browsers
+ */
+static fwts_log_html_ascii_t fwts_log_html_ascii_table[] = {
+	{ '"',	"&quot;" },
+	{ '&', 	"&amp;" },
+	{ '<', 	"&lt;" },
+	{ '>',	"&gt;" },
+	{ '{',	"&#123;" },
+	{ '|',	"&#124;" },
+	{ '}',	"&#125;" },
+	{ '~',	"&#126;" },
+
+	{ 160,	"&nbsp;" },
+	{ 161,	"&iexl;" },
+	{ 162,	"&cent;" },
+	{ 163,	"&pound;" },
+	{ 164,	"&curren;" },
+	{ 165,	"&yen;" },
+	{ 166,	"&brvbar;" },
+	{ 167,	"&sect;" },
+	{ 168,	"&uml;" },
+	{ 169,	"&copy;" },
+	{ 170,	"&ordf;" },
+	{ 171,	"&laquo;" },
+	{ 172,	"&not;" },
+	{ 173,	"&shy;" },
+	{ 174,	"&reg;" },
+	{ 175,	"&macr;" },
+
+	{ 176,	"&deg;" },
+	{ 177,	"&plusmn;" },
+	{ 178,	"&sup2;" },
+	{ 179,	"&sup3;" },
+	{ 180,	"&acute;" },
+	{ 181,	"&micro;" },
+	{ 182,	"&para;" },
+	{ 183,	"&middot;" },
+	{ 184,	"&cedil;" },
+	{ 185,	"&sup1;" },
+	{ 186,	"&ordm;" },
+	{ 187,	"&raquo;" },
+	{ 187,	"&frac14;" },
+	{ 189,	"&frac12;" },
+	{ 190,	"&frac34;" },
+	{ 191,	"&iquest;" },
+
+	/* Probably never used, but here in case */
+
+	{ 192,	"&Agrave;" },
+	{ 193,	"&Aacute;" },
+	{ 194,	"&Acirc;" },
+	{ 195,	"&Atilde;" },
+	{ 196,	"&Auml;" },
+	{ 197,	"&Aring;" },
+	{ 198,	"&AElig;" },
+	{ 199,	"&Ccedil;" },
+	{ 200,	"&Egrave;" },
+	{ 201,	"&Eacute;" },
+	{ 202,	"&Ecirc;" },
+	{ 203,	"&Euml;" },
+	{ 204,	"&lgrave;" },
+	{ 205,	"&lacute;" },
+	{ 206,	"&lcirc;" },
+	{ 207,	"&luml;" },
+
+	{ 208,	"&ETH;" },
+	{ 209,	"&Ntilde;" },
+	{ 210,	"&Ograve;" },
+	{ 211,	"&Oacute;" },
+	{ 212,	"&Ocirc;" },
+	{ 213,	"&Otilde;" },
+	{ 214,	"&Ouml;" },
+	{ 215,	"&times;" },
+	{ 216,	"&Oslash;" },
+	{ 217,	"&Ugrave;" },
+	{ 218,	"&Uacute;" },
+	{ 219,	"&Ucirc;" },
+	{ 220,	"&Uuml;" },
+	{ 221,	"&Yacute;" },
+	{ 222,	"&THORN;" },
+	{ 223,	"&szlig;" },
+
+	{ 224,	"&agrave;" },
+	{ 225,	"&aacute;" },
+	{ 226,	"&acirc;" },
+	{ 227,	"&atilde;" },
+	{ 228,	"&auml;" },
+	{ 229,	"&aring;" },
+	{ 230,	"&aelig;" },
+	{ 231,	"&ccedil;" },
+	{ 232,	"&egrave;" },
+	{ 233,	"&eacute;" },
+	{ 234,	"&ecirc;" },
+	{ 235,	"&emuml;" },
+	{ 236,	"&igrave;" },
+	{ 237,	"&iacute;" },
+	{ 238,	"&icirc;" },
+	{ 239,	"&iuml;" },
+
+	{ 240,	"&eth;" },
+	{ 241,	"&ntilde;" },
+	{ 242,	"&ograve;" },
+	{ 243,	"&oacute;" },
+	{ 244,	"&ocirc;" },
+	{ 245,	"&otilde;" },
+	{ 246,	"&ouml;" },
+	{ 247,	"&divide;" },
+	{ 248,	"&oslash;" },
+	{ 249,	"&ugrave;" },
+	{ 250,	"&uacute;" },
+	{ 251,	"&ucirc;" },
+	{ 252,	"&uuml;" },
+	{ 253,	"&yacute;" },
+	{ 254,	"&thorn;" },
+	{ 255,	"&yuml;" },
+
+	{ 0, 	NULL },
+};
+
 static fwts_log_html_stack_t html_stack[MAX_HTML_STACK];
 static int html_stack_index = 0;
 
@@ -49,6 +176,58 @@  static void fwts_log_html(fwts_log_file *log_file, const char *fmt, ...)
 	va_end(args);
 }
 
+/*
+ *  fwts_log_html_convert_ascii()
+ *	return a static string containing any convertion from ASCII to a
+ *	HTML representation of char ch.  If no conversion needed, just
+ *	return a string containing the ch.
+ */
+static char *fwts_log_html_convert_ascii(const char ch)
+{
+	int i;
+	static char buf[2];
+
+	for (i = 0; fwts_log_html_ascii_table[i].html != NULL; i++) {
+		if (fwts_log_html_ascii_table[i].ch == ch)
+			return fwts_log_html_ascii_table[i].html;
+	}
+
+	/* No mapping, just return string containing ch */
+	buf[0] = ch;
+	buf[1] = '\0';
+
+	return buf;
+}
+
+/*
+ *  fwts_log_html_convert_ascii_str()
+ *	convert an ASCII string into a HTML encoded string. The returned
+ *	string needs free'ing once finished with.
+ */
+static char *fwts_log_html_convert_ascii_str(const char *buffer)
+{
+	const char *str1;
+	char *converted;
+	size_t len = 0;
+
+	/* Step 1, figure out how much space we need */
+	for (str1 = buffer; *str1; str1++) {
+		char *str = fwts_log_html_convert_ascii(*str1);
+		len += strlen(str);
+	}
+
+	if ((converted = calloc(len + 1, 1)) == NULL)
+		return NULL;
+
+	/* Step 2, convert */
+	for (str1 = buffer; *str1; str1++) {
+		char *str = fwts_log_html_convert_ascii(*str1);
+		strcat(converted, str);
+	}
+
+	return converted;
+}
+
 
 /*
  *  fwts_log_print_html()
@@ -67,6 +246,7 @@  static int fwts_log_print_html(
 	char *style;
 	char *code_start;
 	char *code_end;
+	char *html_converted;
 
 	if (!((field & LOG_FIELD_MASK) & fwts_log_filter))
 		return 0;
@@ -74,6 +254,12 @@  static int fwts_log_print_html(
 	if (field & (LOG_NEWLINE | LOG_SEPARATOR | LOG_DEBUG))
 		return 0;
 
+	if ((html_converted = fwts_log_html_convert_ascii_str(buffer)) == NULL) {
+		/* We can't report an error via the logging mechanism in case we loop */
+		fprintf(stderr, "Out of memory converting html.\n");
+		exit(EXIT_FAILURE);
+	}
+
 	fwts_log_html(log_file, "<TR>\n");
 
 	if (field & LOG_VERBATUM) {
@@ -87,23 +273,24 @@  static int fwts_log_print_html(
 	switch (field & LOG_FIELD_MASK) {
 	case LOG_ERROR:
 		fwts_log_html(log_file, "  <TD class=style_error>Error</TD>"
-			"<TD COLSPAN=2>%s</TD>\n", buffer);
+			"<TD COLSPAN=2>%s</TD>\n", html_converted);
 		break;
 	case LOG_WARNING:
 		fwts_log_html(log_file, "  <TD class=style_error>Warning</TD>"
 			"<TD COLSPAN=2 class=style_advice_info>%s%s%s</TD>\n",
-			code_start, buffer, code_end);
+			code_start, html_converted, code_end);
 		break;
 	case LOG_HEADING:
 		fwts_log_html(log_file, "<TD COLSPAN=2 class=style_heading>%s%s%s</TD>\n",
-			code_start, buffer, code_end);
+			code_start, html_converted, code_end);
 		break;
 	case LOG_INFO:
 		fwts_log_html(log_file, "  <TD></TD><TD COLSPAN=2 class=style_infos>%s%s%s</TD>\n",
-			code_start, buffer, code_end);
+			code_start, html_converted, code_end);
 		break;
 	case LOG_PASSED:
-		fwts_log_html(log_file, "<TD class=style_passed>PASSED</TD><TD>%s</TD>\n", buffer);
+		fwts_log_html(log_file, "<TD class=style_passed>PASSED</TD><TD>%s</TD>\n",
+			html_converted);
 		break;
 	case LOG_FAILED:
 		switch (level) {
@@ -128,30 +315,32 @@  static int fwts_log_print_html(
 		str = fwts_log_level_to_str(level);
 
 		fwts_log_html(log_file, "  <TD%s>%s [%s]</TD>\n", style, *status ? status : "", str);
-		fwts_log_html(log_file, "  <TD>%s</TD>\n", buffer);
+		fwts_log_html(log_file, "  <TD>%s</TD>\n", html_converted);
 		break;
 
 	case LOG_SKIPPED:
 		fwts_log_html(log_file, "<TD class=style_skipped>Skipped</TD>"
-			"<TD>%s%s%s</TD>\n", code_start, buffer, code_end);
+			"<TD>%s%s%s</TD>\n", code_start, html_converted, code_end);
 		break;
 
 	case LOG_SUMMARY:
 		fwts_log_html(log_file, "  <TD></TD>"
 			"<TD COLSPAN=2 class=style_summary>%s%s%s</TD>\n",
-			code_start, buffer, code_end);
+			code_start, html_converted, code_end);
 		break;
 
 	case LOG_ADVICE:
 		fwts_log_html(log_file, "  <TD class=style_advice>Advice</TD>"
 			"<TD COLSPAN=2 class=style_advice_info>%s%s%s</TD>\n",
-			code_start, buffer, code_end);
+			code_start, html_converted, code_end);
 		break;
 
 	default:
 		break;
 	}
 
+	free(html_converted);
+
 	fwts_log_html(log_file, "</TR>\n");
 	fflush(log_file->fp);