From 1b2bf2287fe4e856e4dbe7a9d197a7239ac7777b Mon Sep 17 00:00:00 2001 From: joncruz Date: Sun, 13 May 2007 07:04:40 +0000 Subject: [PATCH] Correcting extraction of "url(...)" for paint --- src/extract-uri-test.h | 55 ++++++++++++++++++++++++++++++++------ src/extract-uri.cpp | 60 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/extract-uri-test.h b/src/extract-uri-test.h index d50628621..aa96fa249 100644 --- a/src/extract-uri-test.h +++ b/src/extract-uri-test.h @@ -9,27 +9,66 @@ class ExtractURITest : public CxxTest::TestSuite { public: + void checkOne( char const* str, char const* expected ) + { + gchar* result = extract_uri( str ); + TS_ASSERT_EQUALS( ( result == NULL ), ( expected == NULL ) ); + if ( result && expected ) { + TS_ASSERT_EQUALS( std::string(result), std::string(expected) ); + } else if ( result ) { + TS_FAIL( std::string("Expected null, found (") + result + ")" ); + } else if ( expected ) { + TS_FAIL( std::string("Expected (") + expected + "), found null" ); + } + g_free( result ); + } + void testBase() { char const* cases[][2] = { { "url(#foo)", "#foo" }, - { "url foo ", "foo" }, + { "url foo ", NULL }, { "url", NULL }, { "url ", NULL }, { "url()", NULL }, { "url ( ) ", NULL }, - { "url foo bar ", "foo bar" } + { "url foo bar ", NULL }, }; for ( size_t i = 0; i < G_N_ELEMENTS(cases); i++ ) { - char const* result = extract_uri( cases[i][0] ); + checkOne( cases[i][0], cases[i][1] ); + } + } - TS_ASSERT_EQUALS( ( result == NULL ), ( cases[i][1] == NULL ) ); - if ( result ) - { - TS_ASSERT_EQUALS( std::string(result), std::string(cases[i][1]) ); - } + void testWithTrailing() + { + char const* cases[][2] = { + { "url(#foo) bar", "#foo" }, + { "url() bar", NULL }, + { "url ( ) bar ", NULL } + }; + + for ( size_t i = 0; i < G_N_ELEMENTS(cases); i++ ) + { + checkOne( cases[i][0], cases[i][1] ); + } + } + + void testQuoted() + { + char const* cases[][2] = { + { "url('#foo')", "#foo" }, + { "url(\"#foo\")", "#foo" }, + { "url('#f o o')", "#f o o" }, + { "url(\"#f o o\")", "#f o o" }, + { "url('#fo\"o')", "#fo\"o" }, + { "url(\"#fo'o\")", "#fo'o" }, + }; + + for ( size_t i = 0; i < G_N_ELEMENTS(cases); i++ ) + { + checkOne( cases[i][0], cases[i][1] ); } } diff --git a/src/extract-uri.cpp b/src/extract-uri.cpp index dd6549c8f..0461f1101 100644 --- a/src/extract-uri.cpp +++ b/src/extract-uri.cpp @@ -2,30 +2,68 @@ #include // FIXME: kill this ugliness when we have a proper CSS parser + +// Functions as per 4.3.4 of CSS 2.1 +// http://www.w3.org/TR/CSS21/syndata.html#uri gchar *extract_uri(gchar const *s) { + gchar* result = 0; gchar const *sb = s; g_assert( strncmp(sb, "url", 3) == 0 ); sb += 3; + // This first whitespace technically is not allowed. + // Just left in for now for legacy behavior. while ( ( *sb == ' ' ) || - ( *sb == '(' ) ) + ( *sb == '\t' ) ) { sb++; } - gchar const *se = sb + strlen(sb); - while ( ( se[-1] == ' ' ) || - ( se[-1] == ')' ) ) - { - se--; - } + if ( *sb == '(' ) { + sb++; + while ( ( *sb == ' ' ) || + ( *sb == '\t' ) ) + { + sb++; + } + + gchar delim = ')'; + if ( (*sb == '\'' || *sb == '"') ) { + delim = *sb; + sb++; + } + gchar const* se = sb + 1; + while ( *se && (*se != delim) ) { + se++; + } - if ( sb < se ) { - return g_strndup(sb, se - sb); - } else { - return NULL; + // we found the delimiter + if ( *se ) { + if ( delim == ')' ) { + // back up for any trailing whitespace + se--; + while ( ( se[-1] == ' ' ) || + ( se[-1] == '\t' ) ) + { + se--; + } + result = g_strndup(sb, se - sb + 1); + } else { + gchar const* tail = se + 1; + while ( ( *tail == ' ' ) || + ( *tail == '\t' ) ) + { + tail++; + } + if ( *tail == ')' ) { + result = g_strndup(sb, se - sb); + } + } + } } + + return result; } /* -- 2.30.2