changeset 802:d29cdb5b842e

Fixed charset decoding given in HTTP and META. (bugs and race condition)
author Jorge Arellano Cid <jcid@dillo.org>
date Wed, 21 Jan 2009 18:54:29 -0300
parents 555cc7fc8d00
children bb850fc92050
files src/cache.c src/html.cc src/nav.c
diffstat 3 files changed, 39 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/cache.c	Sun Jan 18 17:04:56 2009 +0100
+++ b/src/cache.c	Wed Jan 21 18:54:29 2009 -0300
@@ -497,23 +497,31 @@
 
    curr = Cache_current_content_type(entry);
    if (entry->TypeMeta) {
-      /* Type is already been set. Do nothing.
+      /* Type is already been set. Do nothing. META overrides TypeHdr.
        * Multiple META elements? */
-   } else if (a_Misc_content_type_cmp(curr, ctype)) {
-      /* TypeMeta not set, and META gives one different from default */
-      curr = entry->TypeMeta = dStrdup(ctype);
-      if (entry->CharsetDecoder)
-         a_Decode_free(entry->CharsetDecoder);
-      a_Misc_parse_content_type(ctype, NULL, NULL, &charset);
-      entry->CharsetDecoder = a_Decode_charset_init(charset);
-      dFree(charset);
+   } else {
+      if (!entry->TypeHdr) {
+         /* Content-Type from HTTP header */
+         entry->TypeHdr = dStrdup(ctype);
+      } else {
+         /* Content-Type from META */
+         entry->TypeMeta = dStrdup(ctype);
+      }
+      if (a_Misc_content_type_cmp(curr, ctype)) {
+         /* ctype gives one different from current */
+         if (entry->CharsetDecoder)
+            a_Decode_free(entry->CharsetDecoder);
+         a_Misc_parse_content_type(ctype, NULL, NULL, &charset);
+         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;
 
-      /* Invalidate UTF8Data */
-      dStr_free(entry->UTF8Data, 1);
-      entry->UTF8Data = NULL;
-
+      }
    }
-
    return curr;
 }
 
@@ -739,7 +747,6 @@
       dStr_free(entry->Data, 1);
       entry->Data = dStr_sized_new(MIN(entry->ExpectedSize, MAX_INIT_BUF));
    }
-   Cache_ref_data(entry);
 
    /* Get Content-Type */
    if ((Type = Cache_parse_field(header, "Content-Type")) == NULL) {
@@ -750,10 +757,12 @@
    } else {
       /* This HTTP Content-Type is not trusted. It's checked against real data
        * in Cache_process_queue(); only then CA_GotContentType becomes true. */
-      entry->TypeHdr = Type;
+      a_Cache_set_content_type(entry->Url, Type);
       _MSG("TypeHdr  {%s} {%s}\n", Type, URL_STR(entry->Url));
       _MSG("TypeMeta {%s}\n", entry->TypeMeta);
+      dFree(Type);
    }
+   Cache_ref_data(entry);
 }
 
 /*
--- a/src/html.cc	Sun Jan 18 17:04:56 2009 +0100
+++ b/src/html.cc	Wed Jan 21 18:54:29 2009 -0300
@@ -571,8 +571,8 @@
    dFree(aux);
 #endif
 
-   dReturn_if_fail (dw != NULL);
-   dReturn_if_fail (stop_parser == FALSE);
+   dReturn_if (dw == NULL);
+   dReturn_if (stop_parser == TRUE);
 
    Start_Buf = Buf;
    token_start = Html_write_raw(this, buf, bufsize, Eof);
@@ -2736,7 +2736,7 @@
 " <tr><td bgcolor='#a0a0a0' colspan='2'>The author wanted you to go\n"
 " <a href='%s'>here</a>%s</td></tr></table><br>\n";
 
-   const char *equiv, *content;
+   const char *equiv, *content, *new_content;
    char delay_str[64];
    Dstr *ds_msg;
    int delay;
@@ -2778,15 +2778,14 @@
 
       } else if (!dStrcasecmp(equiv, "content-type") &&
                  (content = a_Html_get_attr(html, tag, tagsize, "content"))) {
-         if (a_Misc_content_type_cmp(html->content_type, content)) {
-            const char *new_content =
-               a_Capi_set_content_type(html->page_url, content);
-            /* Cannot ask cache whether the content type was changed, as
-             * this code in another bw might have already changed it for us.
-             */
-            if (a_Misc_content_type_cmp(html->content_type, new_content)) {
-               html->repush_after_head = true;
-            }
+         _MSG("Html_tag_open_meta: content={%s}\n", content);
+         /* Cannot ask cache whether the content type was changed, as
+          * this code in another bw might have already changed it for us.
+          */
+         new_content = a_Capi_set_content_type(html->page_url, content);
+         if (a_Misc_content_type_cmp(html->content_type, new_content)) {
+            html->stop_parser = true; /* Avoid a race condition */
+            html->repush_after_head = true;
          }
       }   
    }
@@ -3303,7 +3302,7 @@
    char *start = tag + 1; /* discard the '<' */
    int IsCloseTag = (*start == '/');
 
-   dReturn_if_fail ( html->stop_parser == false );
+   dReturn_if (html->stop_parser == TRUE);
 
    ni = a_Html_tag_index(start + IsCloseTag);
    if (ni == -1) {
@@ -3586,7 +3585,7 @@
     * boundary. Iterate through tokens until end of buffer is reached. */
    buf_index = 0;
    token_start = buf_index;
-   while ((buf_index < bufsize) && (html->stop_parser == false)) {
+   while ((buf_index < bufsize) && !html->stop_parser) {
       /* invariant: buf_index == bufsize || token_start == buf_index */
 
       if (S_TOP(html)->parse_mode ==
--- a/src/nav.c	Sun Jan 18 17:04:56 2009 +0100
+++ b/src/nav.c	Wed Jan 21 18:54:29 2009 -0300
@@ -370,6 +370,7 @@
 
 static void Nav_repush_callback(void *data)
 {
+   _MSG(">>>   Nav_repush_callback <<<<\n");
    Nav_repush(data);
    a_Timeout_remove();
 }