📄 xdgmimecache.c
字号:
while (max >= min) { mid = (min + max) / 2; match_char = GET_UINT32 (cache->buffer, offset + 16 * mid); if (match_char < character) min = mid + 1; else if (match_char > character) max = mid - 1; else { suffix = _xdg_utf8_next_char (suffix); if (*suffix == '\0') { mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 4); n = 0; if (cache->buffer[mimetype_offset]) mime_types[n++] = cache->buffer + mimetype_offset; n_children = GET_UINT32 (cache->buffer, offset + 16 * mid + 8); child_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 12); i = 0; while (n < n_mime_types && i < n_children) { match_char = GET_UINT32 (cache->buffer, child_offset + 16 * i); mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * i + 4); if (match_char != 0) break; mime_types[n++] = cache->buffer + mimetype_offset; i++; } return n; } else { n_children = GET_UINT32 (cache->buffer, offset + 16 * mid + 8); child_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 12); return cache_glob_node_lookup_suffix (cache, n_children, child_offset, suffix, ignore_case, mime_types, n_mime_types); } } } return 0;}static intcache_glob_lookup_suffix (const char *suffix, int ignore_case, const char *mime_types[], int n_mime_types){ int i, n; for (i = 0; _xdg_mime_caches[i]; i++) { XdgMimeCache *cache = _xdg_mime_caches[i]; xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 16); xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4); n = cache_glob_node_lookup_suffix (cache, n_entries, offset, suffix, ignore_case, mime_types, n_mime_types); if (n > 0) return n; } return 0;}static voidfind_stopchars (char *stopchars){ int i, j, k, l; k = 0; for (i = 0; _xdg_mime_caches[i]; i++) { XdgMimeCache *cache = _xdg_mime_caches[i]; xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 16); xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4); for (j = 0; j < n_entries; j++) { xdg_uint32_t match_char = GET_UINT32 (cache->buffer, offset); if (match_char < 128) { for (l = 0; l < k; l++) if (stopchars[l] == match_char) break; if (l == k) { stopchars[k] = (char) match_char; k++; } } offset += 16; } } stopchars[k] = '\0';}static intcache_glob_lookup_file_name (const char *file_name, const char *mime_types[], int n_mime_types){ const char *ptr; char stopchars[128]; int n; assert (file_name != NULL); /* First, check the literals */ n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types); if (n > 0) return n; find_stopchars (stopchars); /* Next, check suffixes */ ptr = strpbrk (file_name, stopchars); while (ptr) { n = cache_glob_lookup_suffix (ptr, FALSE, mime_types, n_mime_types); if (n > 0) return n; n = cache_glob_lookup_suffix (ptr, TRUE, mime_types, n_mime_types); if (n > 0) return n; ptr = strpbrk (ptr + 1, stopchars); } /* Last, try fnmatch */ return cache_glob_lookup_fnmatch (file_name, mime_types, n_mime_types);}int_xdg_mime_cache_get_max_buffer_extents (void){ xdg_uint32_t offset; xdg_uint32_t max_extent; int i; max_extent = 0; for (i = 0; _xdg_mime_caches[i]; i++) { XdgMimeCache *cache = _xdg_mime_caches[i]; offset = GET_UINT32 (cache->buffer, 24); max_extent = MAX (max_extent, GET_UINT32 (cache->buffer, offset + 4)); } return max_extent;}static const char *cache_get_mime_type_for_data (const void *data, size_t len, const char *mime_types[], int n_mime_types){ const char *mime_type; int i, n, priority; priority = 0; mime_type = NULL; for (i = 0; _xdg_mime_caches[i]; i++) { XdgMimeCache *cache = _xdg_mime_caches[i]; int prio; const char *match; match = cache_magic_lookup_data (cache, data, len, &prio, mime_types, n_mime_types); if (prio > priority) { priority = prio; mime_type = match; } } if (priority > 0) return mime_type; for (n = 0; n < n_mime_types; n++) { if (mime_types[n]) return mime_types[n]; } return XDG_MIME_TYPE_UNKNOWN;}const char *_xdg_mime_cache_get_mime_type_for_data (const void *data, size_t len){ return cache_get_mime_type_for_data (data, len, NULL, 0);}const char *_xdg_mime_cache_get_mime_type_for_file (const char *file_name, struct stat *statbuf){ const char *mime_type; const char *mime_types[2]; FILE *file; unsigned char *data; int max_extent; int bytes_read; struct stat buf; const char *base_name; int n; if (file_name == NULL) return NULL; if (! _xdg_utf8_validate (file_name)) return NULL; base_name = _xdg_get_base_name (file_name); n = cache_glob_lookup_file_name (base_name, mime_types, 2); if (n == 1) return mime_types[0]; if (!statbuf) { if (stat (file_name, &buf) != 0) return XDG_MIME_TYPE_UNKNOWN; statbuf = &buf; } if (!S_ISREG (statbuf->st_mode)) return XDG_MIME_TYPE_UNKNOWN; /* FIXME: Need to make sure that max_extent isn't totally broken. This could * be large and need getting from a stream instead of just reading it all * in. */ max_extent = _xdg_mime_cache_get_max_buffer_extents (); data = malloc (max_extent); if (data == NULL) return XDG_MIME_TYPE_UNKNOWN; file = fopen (file_name, "r"); if (file == NULL) { free (data); return XDG_MIME_TYPE_UNKNOWN; } bytes_read = fread (data, 1, max_extent, file); if (ferror (file)) { free (data); fclose (file); return XDG_MIME_TYPE_UNKNOWN; } mime_type = cache_get_mime_type_for_data (data, bytes_read, mime_types, n); free (data); fclose (file); return mime_type;}const char *_xdg_mime_cache_get_mime_type_from_file_name (const char *file_name){ const char *mime_types[2]; if (cache_glob_lookup_file_name (file_name, mime_types, 2) == 1) return mime_types[0]; else return XDG_MIME_TYPE_UNKNOWN;}#if 1static intis_super_type (const char *mime){ int length; const char *type; length = strlen (mime); type = &(mime[length - 2]); if (strcmp (type, "/*") == 0) return 1; return 0;}#endifint_xdg_mime_cache_mime_type_subclass (const char *mime, const char *base){ const char *umime, *ubase; int i, j, min, max, med, cmp; umime = _xdg_mime_cache_unalias_mime_type (mime); ubase = _xdg_mime_cache_unalias_mime_type (base); if (strcmp (umime, ubase) == 0) return 1; /* We really want to handle text/ * in GtkFileFilter, so we just * turn on the supertype matching */#if 1 /* Handle supertypes */ if (is_super_type (ubase) && xdg_mime_media_type_equal (umime, ubase)) return 1;#endif /* Handle special cases text/plain and application/octet-stream */ if (strcmp (ubase, "text/plain") == 0 && strncmp (umime, "text/", 5) == 0) return 1; if (strcmp (ubase, "application/octet-stream") == 0) return 1; for (i = 0; _xdg_mime_caches[i]; i++) { XdgMimeCache *cache = _xdg_mime_caches[i]; xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 8); xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); xdg_uint32_t offset, n_parents, parent_offset; min = 0; max = n_entries - 1; while (max >= min) { med = (min + max)/2; offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * med); cmp = strcmp (cache->buffer + offset, umime); if (cmp < 0) min = med + 1; else if (cmp > 0) max = med - 1; else { offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * med + 4); n_parents = GET_UINT32 (cache->buffer, offset); for (j = 0; j < n_parents; j++) { parent_offset = GET_UINT32 (cache->buffer, offset + 4 + 4 * j); if (_xdg_mime_cache_mime_type_subclass (cache->buffer + parent_offset, ubase)) return 1; } break; } } } return 0;}const char *_xdg_mime_cache_unalias_mime_type (const char *mime){ const char *lookup; lookup = cache_alias_lookup (mime); if (lookup) return lookup; return mime; }char **_xdg_mime_cache_list_mime_parents (const char *mime){ int i, j, p; char *all_parents[128]; /* we'll stop at 128 */ char **result; mime = xdg_mime_unalias_mime_type (mime); p = 0; for (i = 0; _xdg_mime_caches[i]; i++) { XdgMimeCache *cache = _xdg_mime_caches[i]; xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 8); xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); for (j = 0; j < n_entries; j++) { xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j); xdg_uint32_t parents_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j + 4); if (strcmp (cache->buffer + mimetype_offset, mime) == 0) { int k; xdg_uint32_t parent_mime_offset; xdg_uint32_t n_parents = GET_UINT32 (cache->buffer, parents_offset); for (k = 0; k < n_parents && p < 127; k++) { parent_mime_offset = GET_UINT32 (cache->buffer, parents_offset + 4 + 4 * k); all_parents[p++] = cache->buffer + parent_mime_offset; } break; } } } all_parents[p++] = 0; result = (char **) malloc (p * sizeof (char *)); memcpy (result, all_parents, p * sizeof (char *)); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -