2011-12-26 19:18:46 -08:00
/** \file mimedb.c
2005-09-20 23:26:39 +10:00
mimedb is a program for checking the mimetype , description and
default action associated with a file or mimetype . It uses the
2011-12-26 19:18:46 -08:00
xdgmime library written by the fine folks at freedesktop . org . There does
2005-09-20 23:26:39 +10:00
not seem to be any standard way for the user to change the preferred
application yet .
The first implementation of mimedb used xml_grep to parse the xml
file for the mime entry to determine the description . This was abandoned
because of the performance implications of parsing xml . The current
version only does a simple string search , which is much , much
faster but it might fall on it ' s head .
2008-01-13 05:18:48 +10:00
This code is Copyright 2005 - 2008 Axel Liljencrantz .
2005-09-20 23:26:39 +10:00
It is released under the GPL .
The xdgmime library is dual licensed under LGPL / artistic
license . Read the source code of the library for more information .
*/
# include "config.h"
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10:00
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <fcntl.h>
# include <libgen.h>
# include <errno.h>
2006-01-24 01:45:00 +10:00
# include <regex.h>
# include <locale.h>
2005-09-20 23:26:39 +10:00
# ifdef HAVE_GETOPT_H
# include <getopt.h>
# endif
2006-01-24 01:45:00 +10:00
# if HAVE_LIBINTL_H
# include <libintl.h>
# endif
2005-09-20 23:26:39 +10:00
# include "xdgmime.h"
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-09-20 23:26:39 +10:00
# include "util.h"
2006-11-18 02:24:38 +10:00
# include "print_help.h"
2005-09-20 23:26:39 +10:00
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10:00
/**
Location of the applications . desktop file , relative to a base mime directory
*/
# define APPLICATIONS_DIR "applications / "
/**
Location of the mime xml database , relative to a base mime directory
*/
# define MIME_DIR "mime / "
/**
Filename suffix for XML files
*/
# define MIME_SUFFIX ".xml"
/**
2006-01-24 01:45:00 +10:00
Start tag for langauge - specific comment
2005-09-20 23:26:39 +10:00
*/
2007-05-24 16:37:28 +10:00
# define START_TAG "<comment( +xml:lang *= *(\"%s\"|'%s'))? *>"
2005-09-20 23:26:39 +10:00
/**
End tab for comment
*/
2006-01-24 01:45:00 +10:00
# define STOP_TAG "< / comment *>"
2005-09-20 23:26:39 +10:00
/**
File contains cached list of mime actions
*/
# define DESKTOP_DEFAULT "applications / defaults.list"
2006-01-24 01:45:00 +10:00
/**
Size for temporary string buffer used to make a regex for language
specific descriptions
*/
# define BUFF_SIZE 1024
2006-01-24 06:40:14 +10:00
/**
2006-01-24 01:45:00 +10:00
Program name
*/
# define MIMEDB "mimedb"
2005-09-20 23:26:39 +10:00
2006-05-27 00:55:51 +10:00
/**
Getopt short switches for mimedb
*/
# define GETOPT_STRING "tfimdalhv"
2009-02-23 06:28:52 +10:00
/**
Error message if system call goes wrong .
*/
2011-12-26 19:18:46 -08:00
# define ERROR_SYSTEM "%s: Could not execute command \"%s\"\n"
2009-02-23 06:28:52 +10:00
/**
Exit code if system call goes wrong .
*/
# define STATUS_ERROR_SYSTEM 1
2005-09-20 23:26:39 +10:00
/**
All types of input and output possible
*/
enum
{
FILEDATA ,
FILENAME ,
MIMETYPE ,
DESCRIPTION ,
ACTION ,
LAUNCH
}
;
2006-01-24 06:40:14 +10:00
/**
Regular expression variable used to find start tag of description
*/
static regex_t * start_re = 0 ;
/**
Regular expression variable used to find end tag of description
*/
static regex_t * stop_re = 0 ;
2006-01-24 01:45:00 +10:00
2005-09-20 23:26:39 +10:00
/**
Error flag . Non - zero if something bad happened .
*/
static int error = 0 ;
/**
String of characters to send to system ( ) to launch a file
*/
static char * launch_buff = 0 ;
/**
Length of the launch_buff buffer
*/
static int launch_len = 0 ;
/**
Current position in the launch_buff buffer
*/
static int launch_pos = 0 ;
2006-01-24 06:40:14 +10:00
/**
gettext alias
*/
2006-11-30 00:18:22 +10:00
# ifdef USE_GETTEXT
2006-01-24 01:45:00 +10:00
# define _(string) gettext(string)
2006-11-30 00:18:22 +10:00
# else
# define _(string) (string)
# endif
2005-09-20 23:26:39 +10:00
/**
Call malloc , set error flag and print message on failure
*/
void * my_malloc ( size_t s )
{
void * res = malloc ( s ) ;
if ( ! s )
{
error = 1 ;
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Out of memory \n " ) , MIMEDB ) ;
2005-09-20 23:26:39 +10:00
}
return res ;
}
/**
Duplicate string , set error flag and print message on failure
*/
char * my_strdup ( char * s )
{
char * res = strdup ( s ) ;
if ( ! s )
{
error = 1 ;
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Out of memory \n " ) , MIMEDB ) ;
2005-09-20 23:26:39 +10:00
}
return res ;
}
/**
Search the file \ c filename for the first line starting with \ c
match , which is returned in a newly allocated string .
*/
static char * search_ini ( const char * filename , const char * match )
{
FILE * f = fopen ( filename , " r " ) ;
char buf [ 4096 ] ;
int len = strlen ( match ) ;
2011-12-26 19:18:46 -08:00
int done = 0 ;
2005-09-20 23:26:39 +10:00
if ( ! f )
{
perror ( " fopen " ) ;
error = 1 ;
return 0 ;
}
while ( ! done )
{
if ( ! fgets ( buf , 4096 , f ) )
{
if ( ! feof ( f ) )
{
perror ( " fgets " ) ;
error = 1 ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
buf [ 0 ] = 0 ;
done = 1 ;
}
2010-11-26 11:28:51 -05:00
else if ( strncmp ( buf , match , len ) = = 0 & & buf [ len ] = = ' = ' )
2005-09-20 23:26:39 +10:00
{
done = 1 ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
}
fclose ( f ) ;
if ( buf [ 0 ] )
{
char * res = strdup ( buf ) ;
if ( res )
{
if ( res [ strlen ( res ) - 1 ] = = ' \n ' )
res [ strlen ( res ) - 1 ] = ' \0 ' ;
}
return res ;
}
else
return ( char * ) 0 ;
}
/**
Test if the specified file exists . If it does not , also try
replacing dashes with slashes in \ c in .
*/
static char * file_exists ( const char * dir , const char * in )
{
2010-11-26 11:25:30 -05:00
int dir_len = strlen ( dir ) ;
int need_sep = dir [ dir_len - 1 ] ! = ' / ' ;
2011-12-26 19:18:46 -08:00
char * filename = ( char * ) my_malloc ( dir_len + need_sep + strlen ( in ) + 1 ) ;
char * replaceme ;
2005-09-20 23:26:39 +10:00
struct stat buf ;
// fprintf( stderr, "Check %s%s\n", dir, in );
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! filename )
{
return 0 ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
strcpy ( filename , dir ) ;
2010-11-26 11:25:30 -05:00
if ( need_sep )
filename [ dir_len + + ] = ' / ' ;
strcpy ( filename + dir_len , in ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! stat ( filename , & buf ) )
return filename ;
free ( filename ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/*
DOH ! File does not exist . But all is not lost . KDE sometimes uses
a slash in the name as a directory separator . We try to replace
2011-12-26 19:18:46 -08:00
a dash with a slash and try again .
2005-09-20 23:26:39 +10:00
*/
2011-12-26 19:18:46 -08:00
replaceme = strchr ( in , ' - ' ) ;
2005-09-20 23:26:39 +10:00
if ( replaceme )
{
char * res ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
* replaceme = ' / ' ;
res = file_exists ( dir , in ) ;
* replaceme = ' - ' ;
return res ;
}
/*
OK , no more slashes left . We really are screwed . Nothing to to
but admit defeat and go home .
*/
return 0 ;
}
/**
Try to find the specified file in any of the possible directories
where mime files can be located . This code is shamelessly stolen
from xdg_run_command_on_dirs .
2010-11-26 13:46:54 -05:00
\ param list Full file paths will be appended to this list .
\ param f The relative filename search for the the data directories .
\ param all If zero , then stop after the first filename .
\ return The number of filenames added to the list .
2005-09-20 23:26:39 +10:00
*/
2010-11-26 13:46:54 -05:00
static int append_filenames ( array_list_t * list , char * f , int all )
2005-09-20 23:26:39 +10:00
{
2010-11-26 13:46:54 -05:00
int prev_count = al_get_count ( list ) ;
2005-09-20 23:26:39 +10:00
char * result ;
const char * xdg_data_home ;
const char * xdg_data_dirs ;
const char * ptr ;
xdg_data_home = getenv ( " XDG_DATA_HOME " ) ;
if ( xdg_data_home )
{
2011-12-26 19:18:46 -08:00
result = file_exists ( xdg_data_home , f ) ;
if ( result )
2010-11-26 13:46:54 -05:00
{
al_push ( list , result ) ;
if ( ! all )
return 1 ;
}
2005-09-20 23:26:39 +10:00
}
else
{
const char * home ;
home = getenv ( " HOME " ) ;
if ( home ! = NULL )
{
char * guessed_xdg_home ;
2011-12-26 19:18:46 -08:00
guessed_xdg_home = ( char * ) my_malloc ( strlen ( home ) + strlen ( " /.local/share " ) + 1 ) ;
2005-09-20 23:26:39 +10:00
if ( ! guessed_xdg_home )
return 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
strcpy ( guessed_xdg_home , home ) ;
2010-11-26 11:25:30 -05:00
strcat ( guessed_xdg_home , " /.local/share " ) ;
2011-12-26 19:18:46 -08:00
result = file_exists ( guessed_xdg_home , f ) ;
2005-09-20 23:26:39 +10:00
free ( guessed_xdg_home ) ;
2011-12-26 19:18:46 -08:00
if ( result )
2010-11-26 13:46:54 -05:00
{
al_push ( list , result ) ;
if ( ! all )
return 1 ;
}
2005-09-20 23:26:39 +10:00
}
}
xdg_data_dirs = getenv ( " XDG_DATA_DIRS " ) ;
if ( xdg_data_dirs = = NULL )
2010-11-26 11:25:30 -05:00
xdg_data_dirs = " /usr/local/share:/usr/share " ;
2005-09-20 23:26:39 +10:00
ptr = xdg_data_dirs ;
while ( * ptr ! = ' \000 ' )
{
const char * end_ptr ;
char * dir ;
int len ;
end_ptr = ptr ;
while ( * end_ptr ! = ' : ' & & * end_ptr ! = ' \000 ' )
end_ptr + + ;
if ( end_ptr = = ptr )
{
ptr + + ;
continue ;
}
2011-12-26 19:18:46 -08:00
len = end_ptr - ptr ;
dir = ( char * ) my_malloc ( len + 1 ) ;
2005-09-20 23:26:39 +10:00
if ( ! dir )
return 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
strncpy ( dir , ptr , len ) ;
dir [ len ] = ' \0 ' ;
2011-12-26 19:18:46 -08:00
result = file_exists ( dir , f ) ;
2005-09-20 23:26:39 +10:00
free ( dir ) ;
2011-12-26 19:18:46 -08:00
if ( result )
2010-11-26 13:46:54 -05:00
{
al_push ( list , result ) ;
if ( ! all ) {
return 1 ;
}
}
2005-09-20 23:26:39 +10:00
ptr = end_ptr ;
}
2010-11-26 13:46:54 -05:00
return al_get_count ( list ) - prev_count ;
}
/**
Find at most one file relative to the XDG data directories .
*/
static char * get_filename ( char * f )
{
array_list_t list ;
char * first = NULL ;
al_init ( & list ) ;
append_filenames ( & list , f , 0 ) ;
2011-12-26 19:18:46 -08:00
first = ( char * ) al_pop ( & list ) ;
2010-11-26 13:46:54 -05:00
al_destroy ( & list ) ;
return first ;
2005-09-20 23:26:39 +10:00
}
/**
Remove excessive whitespace from string . Replaces arbitrary sequence
of whitespace with a single space . Also removes any leading and
trailing whitespace
*/
static char * munge ( char * in )
{
2011-12-26 19:18:46 -08:00
char * out = ( char * ) my_malloc ( strlen ( in ) + 1 ) ;
2005-09-20 23:26:39 +10:00
char * p = out ;
int had_whitespace = 0 ;
int printed = 0 ;
if ( ! out )
{
return 0 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
while ( 1 )
{
// fprintf( stderr, "%c\n", *in );
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
switch ( * in )
{
case ' ' :
case ' \n ' :
case ' \t ' :
case ' \r ' :
{
had_whitespace = 1 ;
break ;
}
case ' \0 ' :
* p = ' \0 ' ;
return out ;
default :
{
if ( printed & & had_whitespace )
{
* ( p + + ) = ' ' ;
}
printed = 1 ;
2011-12-26 19:18:46 -08:00
had_whitespace = 0 ;
2005-09-20 23:26:39 +10:00
* ( p + + ) = * in ;
break ;
}
}
in + + ;
}
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Unknown error in munge() \n " ) , MIMEDB ) ;
2005-09-20 23:26:39 +10:00
error = 1 ;
return 0 ;
}
2006-01-24 01:45:00 +10:00
/**
Return a regular expression that matches all strings specifying the current locale
*/
static char * get_lang_re ( )
{
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
static char buff [ BUFF_SIZE ] ;
const char * lang = setlocale ( LC_MESSAGES , 0 ) ;
int close = 0 ;
char * out = buff ;
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
if ( ( 1 + strlen ( lang ) * 4 ) > = BUFF_SIZE )
{
fprintf ( stderr , _ ( " %s: Locale string too long \n " ) , MIMEDB ) ;
error = 1 ;
return 0 ;
}
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
for ( ; * lang ; lang + + )
{
switch ( * lang )
{
case ' @ ' :
case ' . ' :
case ' _ ' :
if ( close )
2007-05-24 16:37:28 +10:00
{
2006-01-24 01:45:00 +10:00
* out + + = ' ) ' ;
2007-05-24 16:37:28 +10:00
* out + + = ' ? ' ;
}
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
close = 1 ;
* out + + = ' ( ' ;
* out + + = * lang ;
break ;
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
default :
* out + + = * lang ;
}
}
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
if ( close )
2007-05-24 16:37:28 +10:00
{
2006-01-24 01:45:00 +10:00
* out + + = ' ) ' ;
2007-05-24 16:37:28 +10:00
* out + + = ' ? ' ;
}
2006-01-24 01:45:00 +10:00
* out + + = 0 ;
2007-05-16 05:37:51 +10:00
2006-01-24 01:45:00 +10:00
return buff ;
}
2005-09-20 23:26:39 +10:00
/**
2011-12-26 19:18:46 -08:00
Get description for a specified mimetype .
2005-09-20 23:26:39 +10:00
*/
static char * get_description ( const char * mimetype )
{
char * fn_part ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
char * fn ;
int fd ;
struct stat st ;
char * contents ;
2009-02-01 23:37:34 +10:00
char * start = 0 , * stop = 0 , * best_start = 0 ;
2006-01-24 01:45:00 +10:00
if ( ! start_re )
{
char * lang ;
char buff [ BUFF_SIZE ] ;
2005-09-20 23:26:39 +10:00
2006-01-24 01:45:00 +10:00
lang = get_lang_re ( ) ;
if ( ! lang )
return 0 ;
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
snprintf ( buff , BUFF_SIZE , START_TAG , lang , lang ) ;
2011-12-26 19:18:46 -08:00
start_re = ( regex_t * ) my_malloc ( sizeof ( regex_t ) ) ;
stop_re = ( regex_t * ) my_malloc ( sizeof ( regex_t ) ) ;
2007-05-16 05:37:51 +10:00
int reg_status ;
if ( ( reg_status = regcomp ( start_re , buff , REG_EXTENDED ) ) )
{
char regerrbuf [ BUFF_SIZE ] ;
regerror ( reg_status , start_re , regerrbuf , BUFF_SIZE ) ;
fprintf ( stderr , _ ( " %s: Could not compile regular expressions %s with error %s \n " ) , MIMEDB , buff , regerrbuf ) ;
error = 1 ;
2011-12-26 19:18:46 -08:00
2007-05-16 05:37:51 +10:00
}
else if ( ( reg_status = regcomp ( stop_re , STOP_TAG , REG_EXTENDED ) ) )
2006-01-24 01:45:00 +10:00
{
2007-05-16 05:37:51 +10:00
char regerrbuf [ BUFF_SIZE ] ;
regerror ( reg_status , stop_re , regerrbuf , BUFF_SIZE ) ;
fprintf ( stderr , _ ( " %s: Could not compile regular expressions %s with error %s \n " ) , MIMEDB , buff , regerrbuf ) ;
2006-01-24 01:45:00 +10:00
error = 1 ;
2011-12-26 19:18:46 -08:00
2007-05-16 05:37:51 +10:00
}
2006-01-24 01:45:00 +10:00
2007-05-16 05:37:51 +10:00
if ( error )
{
2006-01-24 01:45:00 +10:00
free ( start_re ) ;
free ( stop_re ) ;
start_re = stop_re = 0 ;
return 0 ;
2007-05-16 05:37:51 +10:00
}
2006-01-24 01:45:00 +10:00
}
2011-12-26 19:18:46 -08:00
fn_part = ( char * ) my_malloc ( strlen ( MIME_DIR ) + strlen ( mimetype ) + strlen ( MIME_SUFFIX ) + 1 ) ;
2005-09-20 23:26:39 +10:00
if ( ! fn_part )
{
return 0 ;
}
strcpy ( fn_part , MIME_DIR ) ;
strcat ( fn_part , mimetype ) ;
strcat ( fn_part , MIME_SUFFIX ) ;
fn = get_filename ( fn_part ) ; //malloc( strlen(MIME_DIR) +strlen( MIME_SUFFIX)+ strlen( mimetype ) + 1 );
free ( fn_part ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! fn )
{
return 0 ;
}
fd = open ( fn , O_RDONLY ) ;
// fprintf( stderr, "%s\n", fn );
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( fd = = - 1 )
{
perror ( " open " ) ;
error = 1 ;
return 0 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( stat ( fn , & st ) )
{
perror ( " stat " ) ;
error = 1 ;
return 0 ;
}
2011-12-26 19:18:46 -08:00
contents = ( char * ) my_malloc ( st . st_size + 1 ) ;
2005-09-20 23:26:39 +10:00
if ( ! contents )
{
return 0 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( read ( fd , contents , st . st_size ) ! = st . st_size )
{
perror ( " read " ) ;
error = 1 ;
return 0 ;
}
2006-06-21 19:54:30 +10:00
/*
Don ' t need to check exit status of close on read - only file descriptors
*/
2005-09-20 23:26:39 +10:00
close ( fd ) ;
free ( fn ) ;
contents [ st . st_size ] = 0 ;
2006-01-24 01:45:00 +10:00
regmatch_t match [ 1 ] ;
int w = - 1 ;
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
start = contents ;
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
/*
On multiple matches , use the longest match , should be a pretty
good heuristic for best match . . .
*/
while ( ! regexec ( start_re , start , 1 , match , 0 ) )
2005-09-20 23:26:39 +10:00
{
2006-01-24 01:45:00 +10:00
int new_w = match [ 0 ] . rm_eo - match [ 0 ] . rm_so ;
2009-02-01 23:37:34 +10:00
start + = match [ 0 ] . rm_eo ;
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
if ( new_w > w )
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
/*
2006-01-24 01:45:00 +10:00
New match is for a longer match then the previous
match , so we use the new match
*/
w = new_w ;
2009-02-01 23:37:34 +10:00
best_start = start ;
2006-01-24 01:45:00 +10:00
}
}
2011-12-26 19:18:46 -08:00
2006-01-24 01:45:00 +10:00
if ( w ! = - 1 )
{
2009-02-01 23:37:34 +10:00
start = best_start ;
2006-01-24 01:45:00 +10:00
if ( ! regexec ( stop_re , start , 1 , match , 0 ) )
{
/*
We ' ve found the beginning and the end of a suitable description
*/
2005-09-20 23:26:39 +10:00
char * res ;
2006-01-24 01:45:00 +10:00
stop = start + match [ 0 ] . rm_so ;
2005-09-20 23:26:39 +10:00
* stop = ' \0 ' ;
res = munge ( start ) ;
free ( contents ) ;
return res ;
}
}
free ( contents ) ;
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: No description for type %s \n " ) , MIMEDB , mimetype ) ;
2005-09-20 23:26:39 +10:00
error = 1 ;
return 0 ;
}
/**
2011-12-26 19:18:46 -08:00
Get default action for a specified mimetype .
2005-09-20 23:26:39 +10:00
*/
static char * get_action ( const char * mimetype )
{
char * res = 0 ;
2010-11-26 13:46:54 -05:00
int i ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
char * launcher ;
char * end ;
2010-11-26 13:46:54 -05:00
array_list_t mime_filenames ;
2011-12-26 19:18:46 -08:00
2010-11-26 13:46:54 -05:00
char * launcher_str = NULL ;
2005-09-20 23:26:39 +10:00
char * launcher_filename , * launcher_command_str , * launcher_command ;
char * launcher_full ;
2011-12-26 19:18:46 -08:00
2010-11-26 13:46:54 -05:00
al_init ( & mime_filenames ) ;
if ( ! append_filenames ( & mime_filenames , DESKTOP_DEFAULT , 1 ) )
{
al_destroy ( & mime_filenames ) ;
2005-09-20 23:26:39 +10:00
return 0 ;
2010-11-26 13:46:54 -05:00
}
2011-12-26 19:18:46 -08:00
2010-11-26 13:46:54 -05:00
for ( i = 0 ; i < al_get_count ( & mime_filenames ) ; i + + )
{
2011-12-26 19:18:46 -08:00
launcher_str = ( char * ) search_ini ( ( char * ) al_get ( & mime_filenames , i ) , mimetype ) ;
2010-11-26 13:46:54 -05:00
if ( launcher_str )
break ;
}
2005-09-20 23:26:39 +10:00
2010-11-26 13:46:54 -05:00
al_foreach ( & mime_filenames , free ) ;
al_destroy ( & mime_filenames ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! launcher_str )
{
/*
This type does not have a launcher . Try the supertype !
*/
2011-12-26 19:18:46 -08:00
// fprintf( stderr, "mimedb: %s does not have launcher, try supertype\n", mimetype );
2005-09-20 23:26:39 +10:00
const char * * parents = xdg_mime_get_mime_parents ( mimetype ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
const char * * p ;
if ( parents )
{
for ( p = parents ; * p ; p + + )
{
char * a = get_action ( * p ) ;
if ( a ! = 0 )
return a ;
}
}
/*
Just in case subclassing doesn ' t work , ( It doesn ' t on Fedora
Core 3 ) we also test some common subclassings .
*/
2011-12-26 19:18:46 -08:00
2009-02-25 04:36:01 +10:00
if ( strncmp ( mimetype , " text/plain " , 10 ) ! = 0 & & strncmp ( mimetype , " text/ " , 5 ) = = 0 )
2005-09-20 23:26:39 +10:00
return get_action ( " text/plain " ) ;
return 0 ;
}
2011-12-26 19:18:46 -08:00
// fprintf( stderr, "WOOT %s\n", launcher_str );
2005-09-20 23:26:39 +10:00
launcher = strchr ( launcher_str , ' = ' ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! launcher )
{
2011-12-26 19:18:46 -08:00
fprintf ( stderr , _ ( " %s: Could not parse launcher string '%s' \n " ) , MIMEDB , launcher_str ) ;
2005-09-20 23:26:39 +10:00
error = 1 ;
return 0 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/* Skip the = */
launcher + + ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/* Only use first launcher */
end = strchr ( launcher , ' ; ' ) ;
if ( end )
* end = ' \0 ' ;
2011-12-26 19:18:46 -08:00
launcher_full = ( char * ) my_malloc ( strlen ( launcher ) + strlen ( APPLICATIONS_DIR ) + 1 ) ;
2005-09-20 23:26:39 +10:00
if ( ! launcher_full )
{
free ( launcher_str ) ;
return 0 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
strcpy ( launcher_full , APPLICATIONS_DIR ) ;
strcat ( launcher_full , launcher ) ;
free ( launcher_str ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
launcher_filename = get_filename ( launcher_full ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
free ( launcher_full ) ;
2011-12-26 19:18:46 -08:00
2010-11-26 11:28:51 -05:00
launcher_command_str = search_ini ( launcher_filename , " Exec " ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! launcher_command_str )
{
2011-12-26 19:18:46 -08:00
fprintf ( stderr ,
_ ( " %s: Default launcher '%s' does not specify how to start \n " ) , MIMEDB ,
2005-09-20 23:26:39 +10:00
launcher_filename ) ;
free ( launcher_filename ) ;
2011-12-26 19:18:46 -08:00
return 0 ;
2005-09-20 23:26:39 +10:00
}
free ( launcher_filename ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
launcher_command = strchr ( launcher_command_str , ' = ' ) ;
launcher_command + + ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
res = my_strdup ( launcher_command ) ;
2011-12-26 19:18:46 -08:00
free ( launcher_command_str ) ;
2005-09-20 23:26:39 +10:00
return res ;
}
/**
Helper function for launch . Write the specified byte to the string we will execute
*/
static void writer ( char c )
{
if ( launch_len = = - 1 )
return ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( launch_len < = launch_pos )
{
int new_len = launch_len ? 2 * launch_len : 256 ;
2011-12-26 19:18:46 -08:00
char * new_buff = ( char * ) realloc ( launch_buff , new_len ) ;
2005-09-20 23:26:39 +10:00
if ( ! new_buff )
{
free ( launch_buff ) ;
launch_len = - 1 ;
error = 1 ;
return ;
}
launch_buff = new_buff ;
launch_len = new_len ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
launch_buff [ launch_pos + + ] = c ;
}
/**
Write out the specified byte in hex
*/
static void writer_hex ( int num )
{
int a , b ;
a = num / 16 ;
b = num % 16 ;
2007-04-17 16:29:32 +10:00
2005-09-20 23:26:39 +10:00
writer ( a > 9 ? ( ' A ' + a - 10 ) : ( ' 0 ' + a ) ) ;
writer ( b > 9 ? ( ' A ' + b - 10 ) : ( ' 0 ' + b ) ) ;
}
/**
Return current directory in newly allocated string
*/
static char * my_getcwd ( )
{
2011-12-26 19:18:46 -08:00
size_t size = 100 ;
2005-09-20 23:26:39 +10:00
while ( 1 )
{
char * buffer = ( char * ) malloc ( size ) ;
if ( getcwd ( buffer , size ) = = buffer )
return buffer ;
free ( buffer ) ;
if ( errno ! = ERANGE )
return 0 ;
size * = 2 ;
}
}
/**
Return absolute filename of specified file
*/
static char * get_fullfile ( char * file )
{
char * fullfile ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( file [ 0 ] = = ' / ' )
{
fullfile = file ;
}
else
{
char * cwd = my_getcwd ( ) ;
if ( ! cwd )
{
error = 1 ;
perror ( " getcwd " ) ;
return 0 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
int l = strlen ( cwd ) ;
2011-12-26 19:18:46 -08:00
fullfile = ( char * ) my_malloc ( l + strlen ( file ) + 2 ) ;
2005-09-20 23:26:39 +10:00
if ( ! fullfile )
{
free ( cwd ) ;
return 0 ;
}
strcpy ( fullfile , cwd ) ;
if ( cwd [ l - 1 ] ! = ' / ' )
strcat ( fullfile , " / " ) ;
strcat ( fullfile , file ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
free ( cwd ) ;
}
return fullfile ;
}
/**
Write specified file as an URL
*/
static void write_url ( char * file )
{
char * fullfile = get_fullfile ( file ) ;
char * str = fullfile ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( str = = 0 )
{
launch_len = - 1 ;
return ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
writer ( ' f ' ) ;
writer ( ' i ' ) ;
writer ( ' l ' ) ;
writer ( ' e ' ) ;
writer ( ' : ' ) ;
writer ( ' / ' ) ;
writer ( ' / ' ) ;
while ( * str )
{
if ( ( ( * str > = ' a ' ) & & ( * str < = ' z ' ) ) | |
( ( * str > = ' A ' ) & & ( * str < = ' Z ' ) ) | |
( ( * str > = ' 0 ' ) & & ( * str < = ' 9 ' ) ) | |
2007-04-17 16:29:32 +10:00
( strchr ( " -_.~/ " , * str ) ! = 0 ) )
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
writer ( * str ) ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
else if ( strchr ( " ()?&= " , * str ) ! = 0 )
2005-09-20 23:26:39 +10:00
{
writer ( ' \\ ' ) ;
writer ( * str ) ;
}
else
{
writer ( ' % ' ) ;
2007-04-17 16:29:32 +10:00
writer_hex ( ( unsigned char ) * str ) ;
2005-09-20 23:26:39 +10:00
}
str + + ;
}
if ( fullfile ! = file )
free ( fullfile ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
/**
Write specified file
*/
static void write_file ( char * file , int print_path )
{
char * fullfile ;
char * str ;
if ( print_path )
{
fullfile = get_fullfile ( file ) ;
str = fullfile ;
}
else
{
fullfile = my_strdup ( file ) ;
if ( ! fullfile )
{
return ;
}
str = basename ( fullfile ) ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! str )
{
error = 1 ;
return ;
}
while ( * str )
{
switch ( * str )
{
case ' ) ' :
case ' ( ' :
case ' - ' :
case ' # ' :
case ' $ ' :
case ' } ' :
case ' { ' :
case ' ] ' :
case ' [ ' :
case ' * ' :
case ' ? ' :
case ' ' :
case ' | ' :
case ' < ' :
case ' > ' :
case ' ^ ' :
case ' & ' :
case ' \\ ' :
case ' ` ' :
case ' \' ' :
case ' \" ' :
writer ( ' \\ ' ) ;
writer ( * str ) ;
break ;
case ' \n ' :
writer ( ' \\ ' ) ;
writer ( ' n ' ) ;
break ;
case ' \r ' :
writer ( ' \\ ' ) ;
writer ( ' r ' ) ;
break ;
case ' \t ' :
writer ( ' \\ ' ) ;
writer ( ' t ' ) ;
break ;
case ' \b ' :
writer ( ' \\ ' ) ;
writer ( ' b ' ) ;
break ;
case ' \v ' :
writer ( ' \\ ' ) ;
writer ( ' v ' ) ;
break ;
default :
writer ( * str ) ;
break ;
}
str + + ;
}
if ( fullfile ! = file )
free ( fullfile ) ;
}
/**
2011-12-26 19:18:46 -08:00
Use the specified launch filter to launch all the files in the specified list .
2005-09-20 23:26:39 +10:00
\ param filter the action to take
\ param files the list of files for which to perform the action
\ param fileno an internal value . Should always be set to zero .
*/
static void launch ( char * filter , array_list_t * files , int fileno )
{
char * filter_org = filter ;
int count = 0 ;
int launch_again = 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( al_get_count ( files ) < = fileno )
return ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
launch_pos = 0 ;
for ( ; * filter & & ! error ; filter + + )
{
if ( * filter = = ' % ' )
{
filter + + ;
switch ( * filter )
{
case ' u ' :
{
launch_again = 1 ;
write_url ( ( char * ) al_get ( files , fileno ) ) ;
break ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
case ' U ' :
{
int i ;
for ( i = 0 ; i < al_get_count ( files ) ; i + + )
{
if ( i ! = 0 )
writer ( ' ' ) ;
write_url ( ( char * ) al_get ( files , i ) ) ;
if ( error )
break ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
break ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
case ' f ' :
case ' n ' :
{
launch_again = 1 ;
write_file ( ( char * ) al_get ( files , fileno ) , * filter = = ' f ' ) ;
break ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
case ' F ' :
case ' N ' :
{
int i ;
for ( i = 0 ; i < al_get_count ( files ) ; i + + )
{
if ( i ! = 0 )
writer ( ' ' ) ;
write_file ( ( char * ) al_get ( files , i ) , * filter = = ' F ' ) ;
if ( error )
break ;
}
break ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
case ' d ' :
{
char * cpy = get_fullfile ( ( char * ) al_get ( files , fileno ) ) ;
char * dir ;
2011-12-26 19:18:46 -08:00
launch_again = 1 ;
2005-09-20 23:26:39 +10:00
/*
We wish to modify this string , make sure it is only a copy
*/
if ( cpy = = al_get ( files , fileno ) )
cpy = my_strdup ( cpy ) ;
if ( cpy = = 0 )
{
break ;
}
dir = dirname ( cpy ) ;
write_file ( dir , 1 ) ;
free ( cpy ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
break ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
case ' D ' :
{
int i ;
for ( i = 0 ; i < al_get_count ( files ) ; i + + )
{
2011-12-26 19:18:46 -08:00
char * cpy = get_fullfile ( ( char * ) al_get ( files , i ) ) ;
2005-09-20 23:26:39 +10:00
char * dir ;
/*
We wish to modify this string , make sure it is only a copy
*/
if ( cpy = = al_get ( files , i ) )
cpy = my_strdup ( cpy ) ;
if ( cpy = = 0 )
{
break ;
}
dir = dirname ( cpy ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( i ! = 0 )
writer ( ' ' ) ;
write_file ( dir , 1 ) ;
free ( cpy ) ;
}
2011-12-26 19:18:46 -08:00
break ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
default :
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Unsupported switch '%c' in launch string '%s' \n " ) , MIMEDB , * filter , filter_org ) ;
2005-09-20 23:26:39 +10:00
launch_len = 0 ;
break ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
}
else
{
writer ( * filter ) ;
count + + ;
}
}
if ( error )
return ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
switch ( launch_len )
{
case - 1 :
{
launch_len = 0 ;
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Out of memory \n " ) , MIMEDB ) ;
2005-09-20 23:26:39 +10:00
return ;
}
case 0 :
{
return ;
}
default :
{
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
writer ( ' ' ) ;
writer ( ' & ' ) ;
writer ( ' \0 ' ) ;
2011-12-26 19:18:46 -08:00
2009-02-23 06:28:52 +10:00
if ( system ( launch_buff ) = = - 1 )
{
fprintf ( stderr , _ ( ERROR_SYSTEM ) , MIMEDB , launch_buff ) ;
exit ( STATUS_ERROR_SYSTEM ) ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
break ;
}
}
if ( launch_again )
{
launch ( filter_org , files , fileno + 1 ) ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
/**
Clean up one entry from the hash table of launch files
*/
2006-06-13 07:47:42 +10:00
static void clear_entry ( void * key , void * val )
2005-09-20 23:26:39 +10:00
{
/*
The key is a mime value , either from the libraries internal hash
table of mime types or from the command line . Either way , it
should not be freed .
The value is an array_list_t of filenames . The filenames com from
the argument list and should not be freed . The arraylist ,
however , should be destroyed and freed .
*/
array_list_t * l = ( array_list_t * ) val ;
al_destroy ( l ) ;
free ( l ) ;
}
2006-01-24 06:40:14 +10:00
/**
Do locale specific init
*/
2006-01-24 01:45:00 +10:00
static void locale_init ( )
{
setlocale ( LC_ALL , " " ) ;
bindtextdomain ( PACKAGE_NAME , LOCALEDIR ) ;
textdomain ( PACKAGE_NAME ) ;
}
2005-09-20 23:26:39 +10:00
/**
Main function . Parses options and calls helper function for any heavy lifting .
*/
int main ( int argc , char * argv [ ] )
2011-12-26 19:18:46 -08:00
{
2005-09-20 23:26:39 +10:00
int input_type = FILEDATA ;
int output_type = MIMETYPE ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
const char * mimetype ;
char * output = 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
int i ;
hash_table_t launch_hash ;
2006-01-24 01:45:00 +10:00
locale_init ( ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/*
Parse options
*/
while ( 1 )
{
static struct option
long_options [ ] =
{
{
2011-12-26 19:18:46 -08:00
" input-file-data " , no_argument , 0 , ' t '
2005-09-20 23:26:39 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" input-filename " , no_argument , 0 , ' f '
2005-09-20 23:26:39 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" input-mime " , no_argument , 0 , ' i '
2005-09-20 23:26:39 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" output-mime " , no_argument , 0 , ' m '
2005-09-20 23:26:39 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" output-description " , no_argument , 0 , ' d '
2005-09-20 23:26:39 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" output-action " , no_argument , 0 , ' a '
2005-09-20 23:26:39 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" help " , no_argument , 0 , ' h '
2005-09-20 23:26:39 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" version " , no_argument , 0 , ' v '
2005-09-20 23:26:39 +10:00
}
,
{
" launch " , no_argument , 0 , ' l '
}
,
2011-12-26 19:18:46 -08:00
{
0 , 0 , 0 , 0
2005-09-20 23:26:39 +10:00
}
}
;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
int opt_index = 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
int opt = getopt_long ( argc ,
2011-12-26 19:18:46 -08:00
argv ,
2006-05-27 00:55:51 +10:00
GETOPT_STRING ,
2011-12-26 19:18:46 -08:00
long_options ,
2005-09-20 23:26:39 +10:00
& opt_index ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( opt = = - 1 )
break ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
switch ( opt )
{
case 0 :
2011-12-26 19:18:46 -08:00
break ;
2005-09-20 23:26:39 +10:00
2011-12-26 19:18:46 -08:00
case ' t ' :
2005-09-20 23:26:39 +10:00
input_type = FILEDATA ;
break ;
2011-12-26 19:18:46 -08:00
case ' f ' :
2005-09-20 23:26:39 +10:00
input_type = FILENAME ;
break ;
2011-12-26 19:18:46 -08:00
case ' i ' :
2005-09-20 23:26:39 +10:00
input_type = MIMETYPE ;
break ;
2011-12-26 19:18:46 -08:00
case ' m ' :
2005-09-20 23:26:39 +10:00
output_type = MIMETYPE ;
break ;
2011-12-26 19:18:46 -08:00
case ' d ' :
2005-09-20 23:26:39 +10:00
output_type = DESCRIPTION ;
break ;
2011-12-26 19:18:46 -08:00
case ' a ' :
2005-09-20 23:26:39 +10:00
output_type = ACTION ;
break ;
2011-12-26 19:18:46 -08:00
case ' l ' :
2005-09-20 23:26:39 +10:00
output_type = LAUNCH ;
break ;
case ' h ' :
2006-11-18 02:24:38 +10:00
print_help ( argv [ 0 ] , 1 ) ;
2011-12-26 19:18:46 -08:00
exit ( 0 ) ;
2005-09-20 23:26:39 +10:00
case ' v ' :
2006-01-24 01:45:00 +10:00
printf ( _ ( " %s, version %s \n " ) , MIMEDB , PACKAGE_VERSION ) ;
2011-12-26 19:18:46 -08:00
exit ( 0 ) ;
2005-09-20 23:26:39 +10:00
case ' ? ' :
return 1 ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
}
if ( ( output_type = = LAUNCH ) & & ( input_type = = MIMETYPE ) )
{
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Can not launch a mimetype \n " ) , MIMEDB ) ;
2006-11-18 02:24:38 +10:00
print_help ( argv [ 0 ] , 2 ) ;
2005-09-20 23:26:39 +10:00
exit ( 1 ) ;
}
if ( output_type = = LAUNCH )
hash_init ( & launch_hash , & hash_str_func , & hash_str_cmp ) ;
2011-12-26 19:18:46 -08:00
/*
2005-09-20 23:26:39 +10:00
Loop over all non option arguments and do the specified lookup
*/
2011-12-26 19:18:46 -08:00
//fprintf( stderr, "Input %d, output %d\n", input_type, output_type );
2005-09-20 23:26:39 +10:00
for ( i = optind ; ( i < argc ) & & ( ! error ) ; i + + )
{
/* Convert from filename to mimetype, if needed */
if ( input_type = = FILENAME )
{
mimetype = xdg_mime_get_mime_type_from_file_name ( argv [ i ] ) ;
}
else if ( input_type = = FILEDATA )
{
mimetype = xdg_mime_get_mime_type_for_file ( argv [ i ] ) ;
}
else
mimetype = xdg_mime_is_valid_mime_type ( argv [ i ] ) ? argv [ i ] : 0 ;
mimetype = xdg_mime_unalias_mime_type ( mimetype ) ;
if ( ! mimetype )
{
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Could not parse mimetype from argument '%s' \n " ) , MIMEDB , argv [ i ] ) ;
2005-09-20 23:26:39 +10:00
error = 1 ;
return 1 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/*
Convert from mimetype to whatever , if needed
*/
switch ( output_type )
{
case MIMETYPE :
{
output = ( char * ) mimetype ;
break ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
case DESCRIPTION :
{
2011-12-26 19:18:46 -08:00
output = get_description ( mimetype ) ;
2007-05-25 03:10:53 +10:00
if ( ! output )
output = strdup ( _ ( " Unknown " ) ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
break ;
}
case ACTION :
{
output = get_action ( mimetype ) ;
break ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
case LAUNCH :
{
/*
There may be more files using the same launcher , we
add them all up in little array_list_ts and launched
them together after all the arguments have been
parsed .
*/
array_list_t * l = ( array_list_t * ) hash_get ( & launch_hash , mimetype ) ;
output = 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! l )
{
2011-12-26 19:18:46 -08:00
l = ( array_list_t * ) my_malloc ( sizeof ( array_list_t ) ) ;
2005-09-20 23:26:39 +10:00
if ( l = = 0 )
{
break ;
}
al_init ( l ) ;
hash_put ( & launch_hash , mimetype , l ) ;
}
2011-12-26 19:18:46 -08:00
al_push ( l , argv [ i ] ) ;
2005-09-20 23:26:39 +10:00
}
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/*
Print the glorious result
*/
if ( output )
{
printf ( " %s \n " , output ) ;
if ( output ! = mimetype )
free ( output ) ;
}
output = 0 ;
}
/*
Perform the actual launching
*/
2006-01-24 01:45:00 +10:00
if ( output_type = = LAUNCH & & ! error )
2005-09-20 23:26:39 +10:00
{
int i ;
array_list_t mimes ;
al_init ( & mimes ) ;
hash_get_keys ( & launch_hash , & mimes ) ;
for ( i = 0 ; i < al_get_count ( & mimes ) ; i + + )
{
char * mimetype = ( char * ) al_get ( & mimes , i ) ;
array_list_t * files = ( array_list_t * ) hash_get ( & launch_hash , mimetype ) ;
if ( ! files )
{
2006-01-24 01:45:00 +10:00
fprintf ( stderr , _ ( " %s: Unknown error \n " ) , MIMEDB ) ;
2005-09-20 23:26:39 +10:00
error = 1 ;
2011-12-26 19:18:46 -08:00
break ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
char * launcher = get_action ( mimetype ) ;
if ( launcher )
{
launch ( launcher , files , 0 ) ;
free ( launcher ) ;
}
}
hash_foreach ( & launch_hash , & clear_entry ) ;
hash_destroy ( & launch_hash ) ;
al_destroy ( & mimes ) ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( launch_buff )
free ( launch_buff ) ;
2006-01-24 01:45:00 +10:00
if ( start_re )
{
regfree ( start_re ) ;
regfree ( stop_re ) ;
free ( start_re ) ;
free ( stop_re ) ;
2011-12-26 19:18:46 -08:00
}
2006-01-24 01:45:00 +10:00
2005-09-20 23:26:39 +10:00
xdg_mime_shutdown ( ) ;
2011-12-26 19:18:46 -08:00
return error ;
2005-09-20 23:26:39 +10:00
}