📄 xdgmimemagic.c
字号:
bytes_read = fread (matchlet->value, 1, matchlet->value_length, magic_file); if (bytes_read != matchlet->value_length) { _xdg_mime_magic_matchlet_free (matchlet); if (feof (magic_file)) return XDG_MIME_MAGIC_EOF; else return XDG_MIME_MAGIC_ERROR; } c = getc_unlocked (magic_file); if (c == '&') { matchlet->mask = malloc (matchlet->value_length); /* OOM */ if (matchlet->mask == NULL) { _xdg_mime_magic_matchlet_free (matchlet); return XDG_MIME_MAGIC_ERROR; } bytes_read = fread (matchlet->mask, 1, matchlet->value_length, magic_file); if (bytes_read != matchlet->value_length) { _xdg_mime_magic_matchlet_free (matchlet); if (feof (magic_file)) return XDG_MIME_MAGIC_EOF; else return XDG_MIME_MAGIC_ERROR; } c = getc_unlocked (magic_file); } if (c == '~') { matchlet->word_size = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); if (end_of_file) { _xdg_mime_magic_matchlet_free (matchlet); return XDG_MIME_MAGIC_EOF; } if (matchlet->word_size != 0 && matchlet->word_size != 1 && matchlet->word_size != 2 && matchlet->word_size != 4) { _xdg_mime_magic_matchlet_free (matchlet); return XDG_MIME_MAGIC_ERROR; } c = getc_unlocked (magic_file); } if (c == '+') { matchlet->range_length = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); if (end_of_file) { _xdg_mime_magic_matchlet_free (matchlet); return XDG_MIME_MAGIC_EOF; } if (matchlet->range_length == -1) { _xdg_mime_magic_matchlet_free (matchlet); return XDG_MIME_MAGIC_ERROR; } c = getc_unlocked (magic_file); } if (c == '\n') { /* We clean up the matchlet, byte swapping if needed */ if (matchlet->word_size > 1) { int i; if (matchlet->value_length % matchlet->word_size != 0) { _xdg_mime_magic_matchlet_free (matchlet); return XDG_MIME_MAGIC_ERROR; } /* FIXME: need to get this defined in a <config.h> style file */#if LITTLE_ENDIAN for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size) { if (matchlet->word_size == 2) *((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i))); else if (matchlet->word_size == 4) *((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i))); if (matchlet->mask) { if (matchlet->word_size == 2) *((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i))); else if (matchlet->word_size == 4) *((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i))); } }#endif } matchlet->next = match->matchlet; match->matchlet = matchlet; return XDG_MIME_MAGIC_MAGIC; } _xdg_mime_magic_matchlet_free (matchlet); if (c == EOF) return XDG_MIME_MAGIC_EOF; return XDG_MIME_MAGIC_ERROR;}static int_xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet, const void *data, size_t len){ int i, j; for (i = matchlet->offset; i < matchlet->offset + matchlet->range_length; i++) { int valid_matchlet = TRUE; if (i + matchlet->value_length > len) return FALSE; if (matchlet->mask) { for (j = 0; j < matchlet->value_length; j++) { if ((matchlet->value[j] & matchlet->mask[j]) != ((((unsigned char *) data)[j + i]) & matchlet->mask[j])) { valid_matchlet = FALSE; break; } } } else { for (j = 0; j < matchlet->value_length; j++) { if (matchlet->value[j] != ((unsigned char *) data)[j + i]) { valid_matchlet = FALSE; break; } } } if (valid_matchlet) return TRUE; } return FALSE;}static int_xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet, const void *data, size_t len, int indent){ while ((matchlet != NULL) && (matchlet->indent == indent)) { if (_xdg_mime_magic_matchlet_compare_to_data (matchlet, data, len)) { if ((matchlet->next == NULL) || (matchlet->next->indent <= indent)) return TRUE; if (_xdg_mime_magic_matchlet_compare_level (matchlet->next, data, len, indent + 1)) return TRUE; } do { matchlet = matchlet->next; } while (matchlet && matchlet->indent > indent); } return FALSE;}static int_xdg_mime_magic_match_compare_to_data (XdgMimeMagicMatch *match, const void *data, size_t len){ return _xdg_mime_magic_matchlet_compare_level (match->matchlet, data, len, 0);}static void_xdg_mime_magic_insert_match (XdgMimeMagic *mime_magic, XdgMimeMagicMatch *match){ XdgMimeMagicMatch *list; if (mime_magic->match_list == NULL) { mime_magic->match_list = match; return; } if (match->priority > mime_magic->match_list->priority) { match->next = mime_magic->match_list; mime_magic->match_list = match; return; } list = mime_magic->match_list; while (list->next != NULL) { if (list->next->priority < match->priority) { match->next = list->next; list->next = match; return; } list = list->next; } list->next = match; match->next = NULL;}XdgMimeMagic *_xdg_mime_magic_new (void){ return calloc (1, sizeof (XdgMimeMagic));}void_xdg_mime_magic_free (XdgMimeMagic *mime_magic){ if (mime_magic) { _xdg_mime_magic_match_free (mime_magic->match_list); free (mime_magic); }}int_xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic){ return mime_magic->max_extent;}const char *_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic, const void *data, size_t len, const char *mime_types[], int n_mime_types){ XdgMimeMagicMatch *match; const char *mime_type; int n; mime_type = NULL; for (match = mime_magic->match_list; match; match = match->next) { if (_xdg_mime_magic_match_compare_to_data (match, data, len)) { if ((mime_type == NULL) || (xdg_mime_mime_type_subclass (match->mime_type, mime_type))) { mime_type = match->mime_type; } } else { for (n = 0; n < n_mime_types; n++) { if (mime_types[n] && xdg_mime_mime_type_equal (mime_types[n], match->mime_type)) mime_types[n] = NULL; } } } if (mime_type == NULL) { for (n = 0; n < n_mime_types; n++) { if (mime_types[n]) mime_type = mime_types[n]; } } return mime_type;}static void_xdg_mime_update_mime_magic_extents (XdgMimeMagic *mime_magic){ XdgMimeMagicMatch *match; int max_extent = 0; for (match = mime_magic->match_list; match; match = match->next) { XdgMimeMagicMatchlet *matchlet; for (matchlet = match->matchlet; matchlet; matchlet = matchlet->next) { int extent; extent = matchlet->value_length + matchlet->offset + matchlet->range_length; if (max_extent < extent) max_extent = extent; } } mime_magic->max_extent = max_extent;}static XdgMimeMagicMatchlet *_xdg_mime_magic_matchlet_mirror (XdgMimeMagicMatchlet *matchlets){ XdgMimeMagicMatchlet *new_list; XdgMimeMagicMatchlet *tmp; if ((matchlets == NULL) || (matchlets->next == NULL)) return matchlets; new_list = NULL; tmp = matchlets; while (tmp != NULL) { XdgMimeMagicMatchlet *matchlet; matchlet = tmp; tmp = tmp->next; matchlet->next = new_list; new_list = matchlet; } return new_list;}static void_xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic, FILE *magic_file){ XdgMimeMagicState state; XdgMimeMagicMatch *match = NULL; /* Quiet compiler */ state = XDG_MIME_MAGIC_SECTION; while (state != XDG_MIME_MAGIC_EOF) { switch (state) { case XDG_MIME_MAGIC_SECTION: match = _xdg_mime_magic_match_new (); state = _xdg_mime_magic_parse_header (magic_file, match); if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR) _xdg_mime_magic_match_free (match); break; case XDG_MIME_MAGIC_MAGIC: state = _xdg_mime_magic_parse_magic_line (magic_file, match); if (state == XDG_MIME_MAGIC_SECTION || (state == XDG_MIME_MAGIC_EOF && match->mime_type)) { match->matchlet = _xdg_mime_magic_matchlet_mirror (match->matchlet); _xdg_mime_magic_insert_match (mime_magic, match); } else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR) _xdg_mime_magic_match_free (match); break; case XDG_MIME_MAGIC_ERROR: state = _xdg_mime_magic_parse_error (magic_file); break; case XDG_MIME_MAGIC_EOF: default: /* Make the compiler happy */ assert (0); } } _xdg_mime_update_mime_magic_extents (mime_magic);}void_xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic, const char *file_name){ FILE *magic_file; char header[12]; magic_file = fopen (file_name, "r"); if (magic_file == NULL) return; if (fread (header, 1, 12, magic_file) == 12) { if (memcmp ("MIME-Magic\0\n", header, 12) == 0) _xdg_mime_magic_read_magic_file (mime_magic, magic_file); } fclose (magic_file);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -