From ee8d3aa3f337cef3faae8d45c6e23ab05f380db8 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sun, 3 Aug 2008 23:29:01 +0200 Subject: Always generate valid XHTML entities No need to double-escape entities in source XML files, just use single & etc. --- gallery-utils.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 128 insertions(+), 21 deletions(-) (limited to 'gallery-utils.c') diff --git a/gallery-utils.c b/gallery-utils.c index 6de0224..ce80a4f 100644 --- a/gallery-utils.c +++ b/gallery-utils.c @@ -23,39 +23,83 @@ #include "gallery-utils.h" + +static char * +strstr_exclude (const char *haystack, const char *needle, const char *exclude_when) +{ + const char *src; + char *found; + + src = haystack; + + while (src && strstr (src, needle)) { + found = strstr (src, needle); + + /* skip if found 'exclude_when' at the same place as 'search' */ + if (exclude_when && (found == strstr (haystack, exclude_when))) { + src += strlen (exclude_when); + continue; + } + else + return found; + } + + return NULL; +} + /* * str_replace: replace substring 'search' with a 'replace' string - * - only one occurence of the string is replaced - * - reallocates the original string + * - multiple occurences of the string are replaced + * - specify 'exclude_when' if you want to skip replace when a string found at the place of 'search' + * - reallocates the original string */ void -str_replace (char **dst, const char *search, const char *replace) +str_replace (char **dst, const char *search, const char *replace, const char *exclude_when) { - char *res; - char *tms; - int new_str_len; + #define REPLACE_MAX_LENGTH 32768 + static char d[REPLACE_MAX_LENGTH]; + char *src; + char *found; + int i; - /* is 'search' present in 'dst'? */ - res = strstr (*dst, search); - if (res == NULL) - return; + /* TODO: add range checking */ - new_str_len = strlen (*dst) - strlen (search) + strlen (replace) + 1; + if (strstr (*dst, search) == NULL || strlen (*dst) == 0 || + strlen (search) == 0 || strlen (replace) == 0) + return; - tms = malloc (new_str_len); - memset (tms, 0, new_str_len); + i = 0; + src = *dst; + while (strstr_exclude (src, search, exclude_when)) { + found = strstr_exclude (src, search, exclude_when); + + /* copy the data between search string */ + if (found > src) { + memcpy (&d[i], src, found - src); + i += found - src; + } + + /* copy replace string instead */ + memcpy (&d[i], replace, strlen (replace)); + i += strlen (replace); + src = found + strlen (search); + } - memcpy (tms, *dst, res - *dst); - memcpy ((void*) ((long int) tms + (long int) res - (long int) *dst), - replace, - strlen (replace)); - memcpy ((void*) ((long int) tms + (long int) res - (long int) *dst + strlen (replace)), - (void*) ((long int) res + strlen (search)), - strlen (res) - strlen (search)); + /* copy the rest */ + if (src) { + memcpy (&d[i], src, strlen (src)); + i += strlen (src); + } + d[i] = 0x0; + +#ifdef __DEBUG_ALL__ + printf ("str_replace('%s', '%s') = '%s' --> '%s'\n", search, replace, *dst, &d[0]); +#endif + /* return fixed string */ free (*dst); - *dst = tms; + *dst = g_strdup (&d[0]); } @@ -120,3 +164,66 @@ make_string (const char* substr, const int count) } +/* + * fix_entities: replace all invalid & entities with & + * - returns newly allocated string + */ +void +fix_entities (char **str) +{ + static char d[REPLACE_MAX_LENGTH]; + char *src; + char *found; + char *scan; + int i; + + /* TODO: add range checking */ + + if (! *str || strstr (*str, "&") == NULL) + return; + + i = 0; + src = *str; + while (strstr (src, "&")) { + found = strstr (src, "&"); + + /* copy the data between search string */ + memcpy (&d[i], src, found - src + 1); + i += found - src + 1; + + /* scroll to next whitespace */ + scan = found + 1; + while (scan && ( + (*scan >= 0x41 && *scan <= 0x5a) || (*scan >= 0x61 && *scan <= 0x7a) || /* A-Z, a-z */ + (*scan >= 0x30 && *scan <= 0x39) || (*scan == 0x23) /* 0-9, # */ + )) + scan++; + + if (scan && (*scan == 0x3b)) { + /* this is semi-colon, correctly closed entity */ + /* -- ignore */ + } + else { + /* replace with & */ + memcpy (&d[i], "amp;", 4); + i += 4; + } + src = found + 1; + } + + /* copy the rest */ + if (src) { + memcpy (&d[i], src, strlen (src)); + i += strlen (src); + } + d[i] = 0x0; + + +#ifdef __DEBUG_ALL__ + printf ("fix_entities: '%s' --> '%s'\n", *str, &d[0]); +#endif + + /* return fixed string */ + free (*str); + *str = g_strdup (&d[0]); +} -- cgit v1.2.3