diff options
author | Jorge Arellano Cid <jcid@dillo.org> | 2009-02-03 09:18:49 -0300 |
---|---|---|
committer | Jorge Arellano Cid <jcid@dillo.org> | 2009-02-03 09:18:49 -0300 |
commit | ba53afebc95493fcf3a7105989e2cabb015b4b1b (patch) | |
tree | ba2d4120e27956da3c5dc2e276731d5c50db5b75 /src | |
parent | 69bcd6963fabfd547495c186e3ea570d2f33cbed (diff) |
Fix a race condition with charset, and the case of charset after CSS in HEAD
Race condition example: www.blisty.cz
charset after CSS ex. : http://www.daemonnews.org
Diffstat (limited to 'src')
-rw-r--r-- | src/cache.c | 5 | ||||
-rw-r--r-- | src/html.cc | 55 | ||||
-rw-r--r-- | src/html_common.hh | 6 |
3 files changed, 44 insertions, 22 deletions
diff --git a/src/cache.c b/src/cache.c index 8d01c40e..8ab9e1a4 100644 --- a/src/cache.c +++ b/src/cache.c @@ -424,7 +424,8 @@ static void Cache_ref_data(CacheEntry_t *entry) if (entry) { entry->DataRefcount++; _MSG("DataRefcount++: %d\n", entry->DataRefcount); - if (entry->CharsetDecoder && entry->DataRefcount == 1) { + if (entry->CharsetDecoder && + (!entry->UTF8Data || entry->DataRefcount == 1)) { dStr_free(entry->UTF8Data, 1); entry->UTF8Data = a_Decode_process(entry->CharsetDecoder, entry->Data->str, @@ -518,7 +519,7 @@ const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype, entry->CharsetDecoder = a_Decode_charset_init(charset); dFree(charset); curr = Cache_current_content_type(entry); - + /* Invalidate UTF8Data */ dStr_free(entry->UTF8Data, 1); entry->UTF8Data = NULL; diff --git a/src/html.cc b/src/html.cc index 5571b8bb..93cb769b 100644 --- a/src/html.cc +++ b/src/html.cc @@ -110,6 +110,7 @@ static void Html_load_image(BrowserWindow *bw, DilloUrl *url, DilloImage *image); static void Html_callback(int Op, CacheClient_t *Client); static void Html_tag_cleanup_at_close(DilloHtml *html, int TagIdx); +static void Html_load_stylesheet(DilloHtml *html, DilloUrl *url); /*----------------------------------------------------------------------------- * Local Data @@ -416,7 +417,6 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url, a_Misc_parse_content_type(content_type, NULL, NULL, &charset); stop_parser = false; - repush_after_head = false; CurrTagOfs = 0; OldTagOfs = 0; @@ -425,6 +425,8 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url, DocType = DT_NONE; /* assume Tag Soup 0.0! :-) */ DocTypeVersion = 0.0f; + cssUrls = new misc::SimpleVector <DilloUrl*> (1); + stack = new misc::SimpleVector <DilloHtmlState> (16); stack->increase(); stack->getRef(0)->table_cell_props = NULL; @@ -509,6 +511,11 @@ DilloHtml::~DilloHtml() a_Url_free(page_url); a_Url_free(base_url); + for (int i = 0; i < cssUrls->size(); i++) + if (cssUrls->get(i)) + a_Url_free(cssUrls->get(i)); + delete (cssUrls); + for (int i = 0; i < forms->size(); i++) a_Html_form_delete (forms->get(i)); delete(forms); @@ -613,6 +620,8 @@ void DilloHtml::finishParsing(int ClientKey) { int si; + dReturn_if (stop_parser == true); + /* force the close of elements left open (TODO: not for XHTML) */ while ((si = stack->size() - 1)) { if (stack->getRef(si)->tag_idx != -1) { @@ -672,6 +681,16 @@ void DilloHtml::loadImages (const DilloUrl *pattern) } } +/* + * Save URL in a vector (may be loaded later). + */ +void DilloHtml::addCssUrl(const DilloUrl *url) +{ + int nu = cssUrls->size(); + cssUrls->increase(); + cssUrls->set(nu, a_Url_dup(url)); +} + bool DilloHtml::HtmlLinkReceiver::enter (Widget *widget, int link, int img, int x, int y) { @@ -1552,8 +1571,7 @@ static void Html_tag_open_head(DilloHtml *html, const char *tag, int tagsize) * Handle close HEAD element * Note: as a side effect of Html_test_section() this function is called * twice when the head element is closed implicitly. - * Note2: HEAD is parsed once completely got. This asserts that a - * linked stylesheet will always arrive after HEAD contents. + * Note2: HEAD is parsed once completely got. */ static void Html_tag_close_head(DilloHtml *html, int TagIdx) { @@ -1564,10 +1582,9 @@ static void Html_tag_close_head(DilloHtml *html, int TagIdx) html->InFlags &= ~IN_HEAD; - if (html->repush_after_head) { - html->stop_parser = true; - MSG(" [html->stop_parser = true]\n"); - a_UIcmd_repush(html->bw); + /* charset is already set, load remote stylesheets now */ + for (int i = 0; i < html->cssUrls->size(); i++) { + Html_load_stylesheet(html, html->cssUrls->get(i)); } } } @@ -2768,8 +2785,8 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize) */ new_content = a_Capi_set_content_type(html->page_url,content,"meta"); if (a_Misc_content_type_cmp(html->content_type, new_content)) { - html->stop_parser = true; /* Avoid a race condition */ - html->repush_after_head = true; + html->stop_parser = true; /* The cache buffer is no longer valid */ + a_UIcmd_repush(html->bw); } } } @@ -2780,7 +2797,7 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize) */ static void Html_css_load_callback(int Op, CacheClient_t *Client) { - _MSG("Css_callback: Op=%d\n", Op); + _MSG("Html_css_load_callback: Op=%d\n", Op); if (Op) { /* EOF */ BrowserWindow *bw = ((DilloWeb *)Client->Web)->bw; /* Repush when we've got them all */ @@ -2796,25 +2813,28 @@ static void Html_load_stylesheet(DilloHtml *html, DilloUrl *url) { char *data; int len; + + dReturn_if (url == NULL); + + _MSG("Html_load_stylesheet: "); if (a_Capi_get_buf(url, &data, &len)) { - /* Haven't looked into what origin_count is */ + _MSG("cached URL=%s len=%d", URL_STR(url), len); if (a_Capi_get_flags(url) & CAPI_Completed) html->styleEngine->parse(data, len, 0, CSS_ORIGIN_AUTHOR); a_Capi_unref_buf(url); - } else if (!html->repush_after_head) { + } else { /* Fill a Web structure for the cache query */ int ClientKey; DilloWeb *Web = a_Web_new(url); Web->bw = html->bw; - //Web->flags |= WEB_Stylesheet; if ((ClientKey = a_Capi_open_url(Web, Html_css_load_callback, NULL))) { ++html->bw->NumPendingStyleSheets; a_Bw_add_client(html->bw, ClientKey, 0); a_Bw_add_url(html->bw, url); - MSG("Html_load_stylesheet: NumPendingStyleSheets=%d\n", - html->bw->NumPendingStyleSheets); + MSG("NumPendingStyleSheets=%d", html->bw->NumPendingStyleSheets); } } + MSG("\n"); } /* @@ -2861,10 +2881,9 @@ static void Html_tag_open_link(DilloHtml *html, const char *tag, int tagsize) !(url = a_Html_url_new(html, attrbuf, NULL, 0))) return; - MSG(" Html_tag_open_link(): URL=%s\n", URL_STR(url)); - _MSG(" repush after HEAD=%d\n", html->repush_after_head); + MSG(" Html_tag_open_link(): addCssUrl %s\n", URL_STR(url)); - Html_load_stylesheet(html, url); + html->addCssUrl(url); a_Url_free(url); } diff --git a/src/html_common.hh b/src/html_common.hh index de87ec80..7983ea5a 100644 --- a/src/html_common.hh +++ b/src/html_common.hh @@ -172,14 +172,15 @@ public: //BUG: for now everything is public char *content_type, *charset; bool stop_parser; - bool repush_after_head; - size_t CurrTagOfs; size_t OldTagOfs, OldTagLine; DilloHtmlDocumentType DocType; /* as given by DOCTYPE tag */ float DocTypeVersion; /* HTML or XHTML version number */ + /* vector of remote CSS resources, as given by the LINK element */ + lout::misc::SimpleVector<DilloUrl*> *cssUrls; + lout::misc::SimpleVector<DilloHtmlState> *stack; StyleEngine *styleEngine; @@ -233,6 +234,7 @@ public: DilloHtmlForm *getCurrentForm (); bool_t unloadedImages(); void loadImages (const DilloUrl *pattern); + void addCssUrl(const DilloUrl *url); }; /* |