diff --git a/gio/xdgmime/xdgmimecache.c b/gio/xdgmime/xdgmimecache.c index 0f2d83a4d..60e2e4fc8 100644 --- a/gio/xdgmime/xdgmimecache.c +++ b/gio/xdgmime/xdgmimecache.c @@ -361,7 +361,8 @@ typedef struct { static int cache_glob_lookup_literal (const char *file_name, const char *mime_types[], - int n_mime_types) + int n_mime_types, + int case_sensitive_check) { const char *ptr; int i, min, max, mid, cmp; @@ -382,17 +383,25 @@ cache_glob_lookup_literal (const char *file_name, offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid); ptr = cache->buffer + offset; cmp = strcmp (ptr, file_name); - + if (cmp < 0) min = mid + 1; else if (cmp > 0) max = mid - 1; else { - offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid + 4); - mime_types[0] = (const char *)(cache->buffer + offset); - - return 1; + int weight = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid + 8); + int case_sensitive = weight & 0x100; + weight = weight & 0xff; + + if (case_sensitive_check || !case_sensitive) + { + offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid + 4); + mime_types[0] = (const char *)(cache->buffer + offset); + + return 1; + } + return 0; } } } @@ -423,6 +432,7 @@ cache_glob_lookup_fnmatch (const char *file_name, xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j); xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 4); int weight = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 8); + weight = weight & 0xff; ptr = cache->buffer + offset; mime_type = cache->buffer + mimetype_offset; @@ -448,7 +458,7 @@ cache_glob_node_lookup_suffix (XdgMimeCache *cache, xdg_uint32_t offset, const char *file_name, int len, - int ignore_case, + int case_sensitive_check, MimeWeight mime_types[], int n_mime_types) { @@ -458,12 +468,11 @@ cache_glob_node_lookup_suffix (XdgMimeCache *cache, xdg_uint32_t n_children; xdg_uint32_t child_offset; int weight; + int case_sensitive; int min, max, mid, n, i; character = file_name[len - 1]; - if (ignore_case) - character = tolower (character); assert (character != 0); @@ -489,7 +498,7 @@ cache_glob_node_lookup_suffix (XdgMimeCache *cache, n = cache_glob_node_lookup_suffix (cache, n_children, child_offset, file_name, len, - ignore_case, + case_sensitive_check, mime_types, n_mime_types); } @@ -504,10 +513,15 @@ cache_glob_node_lookup_suffix (XdgMimeCache *cache, mimetype_offset = GET_UINT32 (cache->buffer, child_offset + 12 * i + 4); weight = GET_UINT32 (cache->buffer, child_offset + 12 * i + 8); + case_sensitive = weight & 0x100; + weight = weight & 0xff; - mime_types[n].mime = cache->buffer + mimetype_offset; - mime_types[n].weight = weight; - n++; + if (case_sensitive_check || !case_sensitive) + { + mime_types[n].mime = cache->buffer + mimetype_offset; + mime_types[n].weight = weight; + n++; + } i++; } } @@ -555,6 +569,22 @@ static int compare_mime_weight (const void *a, const void *b) return aa->weight - bb->weight; } +#define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z') +static char * +ascii_tolower (const char *str) +{ + char *p, *lower; + + lower = strdup (str); + p = lower; + while (*p != 0) + { + char c = *p; + *p++ = ISUPPER (c) ? c - 'A' + 'a' : c; + } + return lower; +} + static int cache_glob_lookup_file_name (const char *file_name, const char *mime_types[], @@ -565,20 +595,36 @@ cache_glob_lookup_file_name (const char *file_name, int n_mimes = 10; int i; int len; - + char *lower_case; + int try_lower_case; + assert (file_name != NULL && n_mime_types > 0); /* First, check the literals */ - n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types); + + lower_case = ascii_tolower (file_name); + + n = cache_glob_lookup_literal (lower_case, mime_types, n_mime_types, FALSE); if (n > 0) - return n; + { + free (lower_case); + return n; + } + + n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types, TRUE); + if (n > 0) + { + free (lower_case); + return n; + } len = strlen (file_name); - n = cache_glob_lookup_suffix (file_name, len, FALSE, mimes, n_mimes); - + n = cache_glob_lookup_suffix (lower_case, len, FALSE, mimes, n_mimes); if (n == 0) n = cache_glob_lookup_suffix (file_name, len, TRUE, mimes, n_mimes); - + + free (lower_case); + /* Last, try fnmatch */ if (n == 0) n = cache_glob_lookup_fnmatch (file_name, mimes, n_mimes); diff --git a/gio/xdgmime/xdgmimeglob.c b/gio/xdgmime/xdgmimeglob.c index 392eaabee..b2ebda829 100644 --- a/gio/xdgmime/xdgmimeglob.c +++ b/gio/xdgmime/xdgmimeglob.c @@ -54,6 +54,7 @@ struct XdgGlobHashNode xdg_unichar_t character; const char *mime_type; int weight; + int case_sensitive; XdgGlobHashNode *next; XdgGlobHashNode *child; }; @@ -62,6 +63,7 @@ struct XdgGlobList const char *data; const char *mime_type; int weight; + int case_sensitive; XdgGlobList *next; }; @@ -111,15 +113,27 @@ static XdgGlobList * _xdg_glob_list_append (XdgGlobList *glob_list, void *data, const char *mime_type, - int weight) + int weight, + int case_sensitive) { XdgGlobList *new_element; XdgGlobList *tmp_element; + tmp_element = glob_list; + while (tmp_element != NULL) + { + if (strcmp (tmp_element->data, data) == 0 && + strcmp (tmp_element->mime_type, mime_type) == 0) + return glob_list; + + tmp_element = tmp_element->next; + } + new_element = _xdg_glob_list_new (); new_element->data = data; new_element->mime_type = mime_type; new_element->weight = weight; + new_element->case_sensitive = case_sensitive; if (glob_list == NULL) return new_element; @@ -168,7 +182,8 @@ static XdgGlobHashNode * _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node, xdg_unichar_t *text, const char *mime_type, - int weight) + int weight, + int case_sensitive) { XdgGlobHashNode *node; xdg_unichar_t character; @@ -232,11 +247,11 @@ _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node, { if (node->mime_type) { - if (strcmp (node->mime_type, mime_type)) + if (strcmp (node->mime_type, mime_type) != 0) { XdgGlobHashNode *child; int found_node = FALSE; - + child = node->child; while (child && child->character == 0) { @@ -254,6 +269,7 @@ _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node, child->character = 0; child->mime_type = strdup (mime_type); child->weight = weight; + child->case_sensitive = case_sensitive; child->child = NULL; child->next = node->child; node->child = child; @@ -264,11 +280,12 @@ _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node, { node->mime_type = strdup (mime_type); node->weight = weight; + node->case_sensitive = case_sensitive; } } else { - node->child = _xdg_glob_hash_insert_ucs4 (node->child, text, mime_type, weight); + node->child = _xdg_glob_hash_insert_ucs4 (node->child, text, mime_type, weight, case_sensitive); } return glob_hash_node; } @@ -278,7 +295,8 @@ static XdgGlobHashNode * _xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node, const char *text, const char *mime_type, - int weight) + int weight, + int case_sensitive) { XdgGlobHashNode *node; xdg_unichar_t *unitext; @@ -286,7 +304,7 @@ _xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node, unitext = _xdg_convert_to_ucs4 (text, &len); _xdg_reverse_ucs4 (unitext, len); - node = _xdg_glob_hash_insert_ucs4 (glob_hash_node, unitext, mime_type, weight); + node = _xdg_glob_hash_insert_ucs4 (glob_hash_node, unitext, mime_type, weight, case_sensitive); free (unitext); return node; } @@ -300,7 +318,7 @@ static int _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node, const char *file_name, int len, - int ignore_case, + int case_sensitive_check, MimeWeight mime_types[], int n_mime_types) { @@ -312,8 +330,6 @@ _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node, return 0; character = file_name[len - 1]; - if (ignore_case) - character = tolower(character); for (node = glob_hash_node; node && character >= node->character; node = node->next) { @@ -326,13 +342,15 @@ _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node, n = _xdg_glob_hash_node_lookup_file_name (node->child, file_name, len, - ignore_case, + case_sensitive_check, mime_types, n_mime_types); } if (n == 0) { - if (node->mime_type) + if (node->mime_type && + (case_sensitive_check || + !node->case_sensitive)) { mime_types[n].mime = node->mime_type; mime_types[n].weight = node->weight; @@ -341,7 +359,9 @@ _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node, node = node->child; while (n < n_mime_types && node && node->character == 0) { - if (node->mime_type) + if (node->mime_type && + (case_sensitive_check || + !node->case_sensitive)) { mime_types[n].mime = node->mime_type; mime_types[n].weight = node->weight; @@ -365,6 +385,22 @@ static int compare_mime_weight (const void *a, const void *b) return aa->weight - bb->weight; } +#define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z') +static char * +ascii_tolower (const char *str) +{ + char *p, *lower; + + lower = strdup (str); + p = lower; + while (*p != 0) + { + char c = *p; + *p++ = ISUPPER (c) ? c - 'A' + 'a' : c; + } + return lower; +} + int _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, const char *file_name, @@ -376,6 +412,8 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, MimeWeight mimes[10]; int n_mimes = 10; int len; + char *lower_case; + int try_lower_case; /* First, check the literals */ @@ -383,17 +421,32 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, n = 0; + lower_case = ascii_tolower (file_name); + for (list = glob_hash->literal_list; list; list = list->next) { if (strcmp ((const char *)list->data, file_name) == 0) { mime_types[0] = list->mime_type; + free (lower_case); return 1; } } + for (list = glob_hash->literal_list; list; list = list->next) + { + if (!list->case_sensitive && + strcmp ((const char *)list->data, lower_case) == 0) + { + mime_types[0] = list->mime_type; + free (lower_case); + return 1; + } + } + + len = strlen (file_name); - n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, file_name, len, FALSE, + n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, lower_case, len, FALSE, mimes, n_mimes); if (n == 0) n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, file_name, len, TRUE, @@ -411,6 +464,7 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, } } } + free (lower_case); qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight); @@ -506,13 +560,13 @@ _xdg_glob_hash_append_glob (XdgGlobHash *glob_hash, switch (type) { case XDG_GLOB_LITERAL: - glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type), weight); + glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type), weight, case_sensitive); break; case XDG_GLOB_SIMPLE: - glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, mime_type, weight); + glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, mime_type, weight, case_sensitive); break; case XDG_GLOB_FULL: - glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type), weight); + glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type), weight, case_sensitive); break; } }