📄 xdgmime.c
字号:
/* -*- mode: C; c-file-style: "gnu" -*- *//* xdgmime.c: XDG Mime Spec mime resolver. Based on version 0.11 of the spec. * * More info can be found at http://www.freedesktop.org/standards/ * * Copyright (C) 2003,2004 Red Hat, Inc. * Copyright (C) 2003,2004 Jonathan Blandford <jrb@alum.mit.edu> * Copyright (C) 2006 Hong Jen Yee <pcman.tw@gmail.com> * * Licensed under the Academic Free License version 2.0 * Or under the following terms: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * xdgmime is originally provided by freedesktop.org * This copy has been "heavily modified" by Hong Jen Yee to * be used in PCMan File Manager. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "xdgmime.h"#include "xdgmimeint.h"#include "xdgmimeglob.h"#include "xdgmimemagic.h"#include "xdgmimealias.h"#include "xdgmimeparent.h"#include "xdgmimecache.h"#include <stdio.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <sys/time.h>#include <unistd.h>#include <assert.h>#include <glib.h>#include "vfs-file-monitor.h"/* typedef struct XdgDirTimeList XdgDirTimeList; */typedef struct XdgCallbackList XdgCallbackList;static time_t last_stat_time = 0;static XdgGlobHash *global_hash = NULL;static XdgMimeMagic *global_magic = NULL;static XdgAliasList *alias_list = NULL;static XdgParentList *parent_list = NULL;/* static XdgDirTimeList *dir_time_list = NULL; */static XdgCallbackList *callback_list = NULL;XdgMimeCache **_caches = NULL;static int n_caches = 0;const char xdg_mime_type_unknown[] = "application/octet-stream";/* 2006.01.16 added by Hong Jen Yee (PCMan) */const char xdg_mime_type_directory[] = "inode/directory";const char xdg_mime_type_executable[] = "application/x-executable";const char xdg_mime_type_plain_text[] = "text/plain";/* VFSFileMonotors used to monitor the change of mime data files */static GSList* monitor_list = NULL;static guint update_timout = 0;enum{ XDG_CHECKED_UNCHECKED, XDG_CHECKED_VALID, XDG_CHECKED_INVALID};struct XdgCallbackList{ XdgCallbackList *next; XdgCallbackList *prev; int callback_id; XdgMimeCallback callback; void *data; XdgMimeDestroy destroy;};/* Function called by xdg_run_command_on_dirs. If it returns TRUE, further * directories aren't looked at */typedef int ( *XdgDirectoryFunc ) ( const char *directory, void *user_data );static gboolean xdg_mime_reload_cache( gpointer user_data );static void xdg_mime_file_changed ( VFSFileMonitor* fm, VFSFileMonitorEvent event, const char* file_name, gpointer user_data ){ if ( 0 == update_timout ) /* Update cache */ update_timout = g_timeout_add( 1000, ( GSourceFunc ) xdg_mime_reload_cache, NULL );}static intxdg_mime_init_from_directory ( const char *directory ){ char * file_name; struct stat st; assert ( directory != NULL ); file_name = malloc ( strlen ( directory ) + strlen ( "/mime/mime.cache" ) + 1 ); strcpy ( file_name, directory ); strcat ( file_name, "/mime/mime.cache" ); XdgMimeCache * cache = _xdg_mime_cache_new_from_file ( file_name ); /* If non-existant files are monitored, the callback functions will be called when the file is created. */ VFSFileMonitor* monitor = vfs_file_monitor_add( file_name, xdg_mime_file_changed, NULL ); monitor_list = g_slist_prepend( monitor_list, monitor ); if ( stat ( file_name, &st ) == 0 ) { if ( cache != NULL ) { _caches = realloc ( _caches, sizeof ( XdgMimeCache * ) * ( n_caches + 2 ) ); _caches[ n_caches ] = cache; _caches[ n_caches + 1 ] = NULL; n_caches++; return FALSE; } } free ( file_name ); file_name = malloc ( strlen ( directory ) + strlen ( "/mime/globs" ) + 1 ); strcpy ( file_name, directory ); strcat ( file_name, "/mime/globs" ); if ( stat ( file_name, &st ) == 0 ) { _xdg_mime_glob_read_from_file ( global_hash, file_name ); } free ( file_name ); file_name = malloc ( strlen ( directory ) + strlen ( "/mime/magic" ) + 1 ); strcpy ( file_name, directory ); strcat ( file_name, "/mime/magic" ); if ( stat ( file_name, &st ) == 0 ) { _xdg_mime_magic_read_from_file ( global_magic, file_name ); } free ( file_name ); file_name = malloc ( strlen ( directory ) + strlen ( "/mime/aliases" ) + 1 ); strcpy ( file_name, directory ); strcat ( file_name, "/mime/aliases" ); _xdg_mime_alias_read_from_file ( alias_list, file_name ); free ( file_name ); file_name = malloc ( strlen ( directory ) + strlen ( "/mime/subclasses" ) + 1 ); strcpy ( file_name, directory ); strcat ( file_name, "/mime/subclasses" ); _xdg_mime_parent_read_from_file ( parent_list, file_name ); free ( file_name ); return FALSE; /* Keep processing */}/* Runs a command on all the directories in the search path */void xdg_run_command_on_dirs ( XdgDirectoryFunc func, void *user_data ){ const char * xdg_data_home; const char *xdg_data_dirs; const char *ptr; xdg_data_home = getenv ( "XDG_DATA_HOME" ); if ( xdg_data_home ) { if ( ( func ) ( xdg_data_home, user_data ) ) return ; } else { const char *home; home = getenv ( "HOME" ); if ( home != NULL ) { char * guessed_xdg_home; int stop_processing; guessed_xdg_home = malloc ( strlen ( home ) + strlen ( "/.local/share" ) + 1 ); strcpy ( guessed_xdg_home, home ); strcat ( guessed_xdg_home, "/.local/share" ); stop_processing = ( func ) ( guessed_xdg_home, user_data ); free ( guessed_xdg_home ); if ( stop_processing ) return ; } } xdg_data_dirs = getenv ( "XDG_DATA_DIRS" ); if ( xdg_data_dirs == NULL ) xdg_data_dirs = "/usr/local/share:/usr/share"; ptr = xdg_data_dirs; while ( *ptr != '\000' ) { const char * end_ptr; char *dir; int len; int stop_processing; end_ptr = ptr; while ( *end_ptr != ':' && *end_ptr != '\000' ) end_ptr ++; if ( end_ptr == ptr ) { ptr++; continue; } if ( *end_ptr == ':' ) len = end_ptr - ptr; else len = end_ptr - ptr + 1; dir = malloc ( len + 1 ); strncpy ( dir, ptr, len ); dir[ len ] = '\0'; stop_processing = ( func ) ( dir, user_data ); free ( dir ); if ( stop_processing ) return ; ptr = end_ptr; }}void xdg_mime_init ( void ){ global_hash = _xdg_glob_hash_new (); global_magic = _xdg_mime_magic_new (); alias_list = _xdg_mime_alias_list_new (); parent_list = _xdg_mime_parent_list_new (); xdg_run_command_on_dirs ( ( XdgDirectoryFunc ) xdg_mime_init_from_directory, NULL );}gboolean xdg_mime_reload_cache( gpointer user_data ){ XdgCallbackList * list; xdg_mime_shutdown(); xdg_mime_init(); update_timout = 0; for ( list = callback_list; list; list = list->next ) ( list->callback ) ( list->data ); return FALSE;}const char *xdg_mime_get_mime_type_for_data ( const void *data, size_t len ){ const char * mime_type; if ( _caches ) return _xdg_mime_cache_get_mime_type_for_data ( data, len ); mime_type = _xdg_mime_magic_lookup_data ( global_magic, data, len, NULL, 0 ); if ( mime_type ) return mime_type; return XDG_MIME_TYPE_UNKNOWN;}/* 2006.02.26 added by Hong Jen Yee */int xdg_mime_is_text_file( const char *file_path, const char* mime_type ){ int file; unsigned char data[ 256 ]; int rlen; int i; int ret = 0; if ( mime_type && xdg_mime_mime_type_subclass( mime_type, XDG_MIME_TYPE_PLAIN_TEXT ) ) { return 1; } if ( !file_path ) { return 0; } file = open ( file_path, O_RDONLY ); if ( file != -1 ) { rlen = read ( file, data, sizeof( data ) ); if ( rlen != -1 ) { for ( i = 0; i < rlen; ++i ) { if ( data[ i ] == '\0' ) { break; } } if ( i >= rlen ) { ret = 1; } } close ( file ); } return ret;}/* 2006.02.26 added by Hong Jen Yee */int xdg_mime_is_executable_file( const char *file_path, const char* mime_type ){ int file; int i; int ret = 0; if ( !mime_type ) { mime_type = xdg_mime_get_mime_type_for_file( file_path, NULL, NULL ); } /* * Only executable types can be executale. * Since some common types, such as application/x-shellscript, * are not in mime database, we have to add them ourselves. */ if ( xdg_mime_mime_type_subclass( mime_type, XDG_MIME_TYPE_EXECUTABLE ) || xdg_mime_mime_type_subclass( mime_type, "application/x-shellscript" ) ) { if ( file_path ) { if ( ! g_file_test( file_path, G_FILE_TEST_IS_EXECUTABLE ) ) return 0; } return 1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -