📄 xdgmimecache.c
字号:
n++; i++; } } return n; } } return 0;}static intcache_glob_lookup_suffix (const char *file_name, int len, int ignore_case, MimeWeight mime_types[], int n_mime_types){ int i, n; for (i = 0; _caches[i]; i++) { XdgMimeCache *cache = _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, file_name, len, ignore_case, mime_types, n_mime_types); if (n > 0) return n; } return 0;}static int compare_mime_weight (const void *a, const void *b){ const MimeWeight *aa = (const MimeWeight *)a; const MimeWeight *bb = (const MimeWeight *)b; return aa->weight - bb->weight;}static intcache_glob_lookup_file_name (const char *file_name, const char *mime_types[], int n_mime_types){ int n; MimeWeight mimes[10]; int n_mimes = 10; int i; int len; assert (file_name != NULL && n_mime_types > 0); /* First, check the literals */ n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types); if (n > 0) return n; len = strlen (file_name); n = cache_glob_lookup_suffix (file_name, len, FALSE, mimes, n_mimes); if (n == 0) n = cache_glob_lookup_suffix (file_name, len, TRUE, mimes, n_mimes); /* Last, try fnmatch */ if (n == 0) n = cache_glob_lookup_fnmatch (file_name, mimes, n_mimes); qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight); if (n_mime_types < n) n = n_mime_types; for (i = 0; i < n; i++) mime_types[i] = mimes[i].mime; return n;}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; _caches[i]; i++) { XdgMimeCache *cache = _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, int *result_prio, const char *mime_types[], int n_mime_types){ const char *mime_type; int i, n, priority; priority = 0; mime_type = NULL; for (i = 0; _caches[i]; i++) { XdgMimeCache *cache = _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 (result_prio) *result_prio = priority; 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, int *result_prio){ return cache_get_mime_type_for_data (data, len, result_prio, 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[10]; 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, 10); 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, NULL, 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_type; if (cache_glob_lookup_file_name (file_name, &mime_type, 1)) return mime_type; else return XDG_MIME_TYPE_UNKNOWN;}int_xdg_mime_cache_get_mime_types_from_file_name (const char *file_name, const char *mime_types[], int n_mime_types){ return cache_glob_lookup_file_name (file_name, mime_types, n_mime_types);}#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; _caches[i]; i++) { XdgMimeCache *cache = _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, k, l, p; char *all_parents[128]; /* we'll stop at 128 */ char **result; mime = xdg_mime_unalias_mime_type (mime); p = 0; for (i = 0; _caches[i]; i++) { XdgMimeCache *cache = _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) { 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); /* Don't add same parent multiple times. * This can happen for instance if the same type is listed in multiple directories */ for (l = 0; l < p; l++) { if (strcmp (all_parents[l], cache->buffer + parent_mime_offset) == 0) break; } if (l == p) all_parents[p++] = cache->buffer + parent_mime_offset; } break; } } } all_parents[p++] = NULL; result = (char **) malloc (p * sizeof (char *)); memcpy (result, all_parents, p * sizeof (char *)); return result;}static const char *cache_lookup_icon (const char *mime, int header){ const char *ptr; int i, min, max, mid, cmp; for (i = 0; _caches[i]; i++) { XdgMimeCache *cache = _caches[i]; xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, header); xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); xdg_uint32_t offset; min = 0; max = n_entries - 1; while (max >= min) { mid = (min + max) / 2; offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid); ptr = cache->buffer + offset; cmp = strcmp (ptr, mime); if (cmp < 0) min = mid + 1; else if (cmp > 0) max = mid - 1; else { offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid + 4); return cache->buffer + offset; } } } return NULL;}const char *_xdg_mime_cache_get_generic_icon (const char *mime){ return cache_lookup_icon (mime, 36);}const char *_xdg_mime_cache_get_icon (const char *mime){ return cache_lookup_icon (mime, 32);}static voiddump_glob_node (XdgMimeCache *cache, xdg_uint32_t offset, int depth){ xdg_unichar_t character; xdg_uint32_t mime_offset; xdg_uint32_t n_children; xdg_uint32_t child_offset; int i; character = GET_UINT32 (cache->buffer, offset); mime_offset = GET_UINT32 (cache->buffer, offset + 4); n_children = GET_UINT32 (cache->buffer, offset + 8); child_offset = GET_UINT32 (cache->buffer, offset + 12); for (i = 0; i < depth; i++) printf (" "); printf ("%c", character); if (mime_offset) printf (" - %s", cache->buffer + mime_offset); printf ("\n"); if (child_offset) { for (i = 0; i < n_children; i++) dump_glob_node (cache, child_offset + 20 * i, depth + 1); }}void_xdg_mime_cache_glob_dump (void){ int i, j; for (i = 0; _caches[i]; i++) { XdgMimeCache *cache = _caches[i]; xdg_uint32_t list_offset; xdg_uint32_t n_entries; xdg_uint32_t offset; list_offset = GET_UINT32 (cache->buffer, 16); n_entries = GET_UINT32 (cache->buffer, list_offset); offset = GET_UINT32 (cache->buffer, list_offset + 4); for (j = 0; j < n_entries; j++) dump_glob_node (cache, offset + 20 * j, 0); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -