diff options
Diffstat (limited to 'mimedb.cpp')
-rw-r--r-- | mimedb.cpp | 1471 |
1 files changed, 0 insertions, 1471 deletions
diff --git a/mimedb.cpp b/mimedb.cpp deleted file mode 100644 index bbc29227..00000000 --- a/mimedb.cpp +++ /dev/null @@ -1,1471 +0,0 @@ -/** \file mimedb.c - -mimedb is a program for checking the mimetype, description and -default action associated with a file or mimetype. It uses the -xdgmime library written by the fine folks at freedesktop.org. There does -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. - -This code is Copyright 2005-2008 Axel Liljencrantz. -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" - - -#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> -#include <regex.h> -#include <locale.h> -#include <vector> -#include <string> -#include <map> - - - -#ifdef HAVE_GETOPT_H -#include <getopt.h> -#endif - -#if HAVE_LIBINTL_H -#include <libintl.h> -#endif - -#include "xdgmime.h" -#include "fallback.h" -#include "util.h" -#include "print_help.h" -#include "fish_version.h" - -typedef std::vector<std::string> string_list_t; - -/** - 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" - -/** - Start tag for langauge-specific comment -*/ -#define START_TAG "<comment( +xml:lang *= *(\"%s\"|'%s'))? *>" - -/** - End tab for comment -*/ -#define STOP_TAG "</comment *>" - -/** - File contains cached list of mime actions -*/ -#define DESKTOP_DEFAULT "applications/defaults.list" - -/** - Size for temporary string buffer used to make a regex for language - specific descriptions -*/ -#define BUFF_SIZE 1024 - -/** - Program name -*/ -#define MIMEDB "mimedb" - -/** - Getopt short switches for mimedb -*/ -#define GETOPT_STRING "tfimdalhv" - -/** - Error message if system call goes wrong. -*/ -#define ERROR_SYSTEM "%s: Could not execute command \"%s\"\n" - -/** - Exit code if system call goes wrong. -*/ -#define STATUS_ERROR_SYSTEM 1 - - -/** - All types of input and output possible -*/ -enum -{ - FILEDATA, - FILENAME, - MIMETYPE, - DESCRIPTION, - ACTION, - LAUNCH -} -; - -/** - 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; - -/** - 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; - -/** - gettext alias -*/ -#ifdef USE_GETTEXT -#define _(string) fish_gettext(string) -#else -#define _(string) (string) -#endif - -/** - Call malloc, set error flag and print message on failure -*/ -void *my_malloc(size_t s) -{ - void *res = malloc(s); - if (!s) - { - error=1; - fprintf(stderr, _("%s: Out of memory\n"), MIMEDB); - } - return res; -} - -/** - Duplicate string, set error flag and print message on failure -*/ -char *my_strdup(const char *s) -{ - char *res = strdup(s); - if (!s) - { - error=1; - fprintf(stderr, _("%s: Out of memory\n"), MIMEDB); - } - return res; -} - - -/** - Search the file \c filename for the first line starting with \c - match, which is returned in a newly allocated string. -*/ -static const char * search_ini(const char *filename, const char *match) -{ - /* OK to not use CLO_EXEC here because mimedb is single threaded */ - FILE *f = fopen(filename, "r"); - char buf[4096]; - int len=strlen(match); - int done = 0; - - if (!f) - { - perror("fopen"); - error=1; - return 0; - } - while (!done) - { - if (!fgets(buf, 4096, f)) - { - if (!feof(f)) - { - perror("fgets"); - error=1; - } - buf[0]=0; - done = 1; - } - else if (strncmp(buf, match, len) == 0 && buf[len] == '=') - { - done=1; - } - } - 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) -{ - int dir_len = strlen(dir); - int need_sep = dir[dir_len - 1] != '/'; - char *filename = (char *)my_malloc(dir_len + need_sep + strlen(in) + 1); - char *replaceme; - struct stat buf; - -// fprintf( stderr, "Check %s%s\n", dir, in ); - - if (!filename) - { - return 0; - } - strcpy(filename, dir); - if (need_sep) - filename[dir_len++] = '/'; - strcpy(filename + dir_len, in); - - if (!stat(filename, &buf)) - return filename; - - free(filename); - - /* - 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 - a dash with a slash and try again. - */ - replaceme = const_cast<char*>(strchr(in, '-')); - if (replaceme) - { - char *res; - - *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. - - \param list Full file paths will be appended to this list. - \param f The relative filename search for the data directories. - \param all If zero, then stop after the first filename. - \return The number of filenames added to the list. -*/ -static int append_filenames(string_list_t &list, const char *f, int all) -{ - size_t prev_count = list.size(); - 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) - { - result = file_exists(xdg_data_home, f); - if (result) - { - list.push_back(result); - if (!all) - return 1; - } - } - else - { - const char *home; - - home = getenv("HOME"); - if (home != NULL) - { - char *guessed_xdg_home; - - guessed_xdg_home = (char *)my_malloc(strlen(home) + strlen("/.local/share") + 1); - if (!guessed_xdg_home) - return 0; - - strcpy(guessed_xdg_home, home); - strcat(guessed_xdg_home, "/.local/share"); - result = file_exists(guessed_xdg_home, f); - free(guessed_xdg_home); - - if (result) - { - list.push_back(result); - if (!all) - return 1; - } - } - } - - 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; - - end_ptr = ptr; - while (*end_ptr != ':' && *end_ptr != '\000') - end_ptr ++; - - if (end_ptr == ptr) - { - ptr++; - continue; - } - - len = end_ptr - ptr; - dir = (char *)my_malloc(len + 1); - if (!dir) - return 0; - - strncpy(dir, ptr, len); - dir[len] = '\0'; - result = file_exists(dir, f); - - free(dir); - - if (result) - { - list.push_back(result); - if (!all) - { - return 1; - } - } - - ptr = end_ptr; - } - return list.size() - prev_count; -} - -/** - Find at most one file relative to the XDG data directories; returns the empty string on failure -*/ -static std::string get_filename(char *f) -{ - string_list_t list; - - append_filenames(list, f, 0); - if (list.empty()) - { - return ""; - } - else - { - return list.back(); - } -} - -/** - 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) -{ - char *out = (char *)my_malloc(strlen(in)+1); - char *p=out; - int had_whitespace = 0; - int printed = 0; - if (!out) - { - return 0; - } - - while (1) - { -// fprintf( stderr, "%c\n", *in ); - - 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; - had_whitespace=0; - *(p++)=*in; - break; - } - } - in++; - } - fprintf(stderr, _("%s: Unknown error in munge()\n"), MIMEDB); - error=1; - return 0; -} - -/** - Return a regular expression that matches all strings specifying the current locale -*/ -static char *get_lang_re() -{ - - static char buff[BUFF_SIZE]; - const char *lang = setlocale(LC_MESSAGES, 0); - int close=0; - char *out=buff; - - if ((1+strlen(lang)*4) >= BUFF_SIZE) - { - fprintf(stderr, _("%s: Locale string too long\n"), MIMEDB); - error = 1; - return 0; - } - - for (; *lang; lang++) - { - switch (*lang) - { - case '@': - case '.': - case '_': - if (close) - { - *out++ = ')'; - *out++ = '?'; - } - - close=1; - *out++ = '('; - *out++ = *lang; - break; - - default: - *out++ = *lang; - } - } - - if (close) - { - *out++ = ')'; - *out++ = '?'; - } - *out++=0; - - return buff; -} - -/** - Get description for a specified mimetype. -*/ -static char *get_description(const char *mimetype) -{ - char *fn_part; - - std::string fn; - int fd; - struct stat st; - char *contents; - char *start=0, *stop=0, *best_start=0; - - if (!start_re) - { - char *lang; - char buff[BUFF_SIZE]; - - lang = get_lang_re(); - if (!lang) - return 0; - - snprintf(buff, BUFF_SIZE, START_TAG, lang, lang); - - start_re = (regex_t *)my_malloc(sizeof(regex_t)); - stop_re = (regex_t *)my_malloc(sizeof(regex_t)); - - 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; - - } - else if ((reg_status = regcomp(stop_re, STOP_TAG, REG_EXTENDED))) - { - 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); - error=1; - - } - - if (error) - { - free(start_re); - free(stop_re); - start_re = stop_re = 0; - - return 0; - } - } - - fn_part = (char *)my_malloc(strlen(MIME_DIR) + strlen(mimetype) + strlen(MIME_SUFFIX) + 1); - - 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); - - if (fn.empty()) - { - return 0; - } - - /* OK to not use CLO_EXEC here because mimedb is single threaded */ - fd = open(fn.c_str(), O_RDONLY); - -// fprintf( stderr, "%s\n", fn ); - - if (fd == -1) - { - perror("open"); - error=1; - return 0; - } - - if (stat(fn.c_str(), &st)) - { - perror("stat"); - error=1; - return 0; - } - - contents = (char *)my_malloc(st.st_size + 1); - if (!contents) - { - return 0; - } - - if (read(fd, contents, st.st_size) != st.st_size) - { - perror("read"); - error=1; - free((void *)contents); - close(fd); - return 0; - } - - /* - Don't need to check exit status of close on read-only file descriptors - */ - close(fd); - - contents[st.st_size]=0; - regmatch_t match[1]; - int w = -1; - - start=contents; - - /* - On multiple matches, use the longest match, should be a pretty - good heuristic for best match... - */ - while (!regexec(start_re, start, 1, match, 0)) - { - int new_w = match[0].rm_eo - match[0].rm_so; - start += match[0].rm_eo; - - if (new_w > w) - { - /* - New match is for a longer match then the previous - match, so we use the new match - */ - w=new_w; - best_start = start; - } - } - - if (w != -1) - { - start = best_start; - if (!regexec(stop_re, start, 1, match, 0)) - { - /* - We've found the beginning and the end of a suitable description - */ - char *res; - - stop = start + match[0].rm_so; - *stop = '\0'; - res = munge(start); - free(contents); - return res; - } - } - free(contents); - fprintf(stderr, _("%s: No description for type %s\n"), MIMEDB, mimetype); - error=1; - return 0; - -} - - -/** - Get default action for a specified mimetype. -*/ -static char *get_action(const char *mimetype) -{ - char *res=0; - - const char *launcher, *end; - string_list_t mime_filenames; - - const char *launcher_str = NULL; - const char *launcher_command_str, *launcher_command; - char *launcher_full; - - if (!append_filenames(mime_filenames, DESKTOP_DEFAULT, 1)) - { - return 0; - } - - for (size_t i = 0; i < mime_filenames.size(); i++) - { - launcher_str = search_ini(mime_filenames.at(i).c_str(), mimetype); - if (launcher_str) - break; - } - - - if (!launcher_str) - { - /* - This type does not have a launcher. Try the supertype! - */ -// fprintf( stderr, "mimedb: %s does not have launcher, try supertype\n", mimetype ); - const char ** parents = xdg_mime_get_mime_parents(mimetype); - - 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. - */ - - if (strncmp(mimetype, "text/plain", 10) != 0 && strncmp(mimetype, "text/", 5) == 0) - return get_action("text/plain"); - - return 0; - } - -// fprintf( stderr, "WOOT %s\n", launcher_str ); - launcher = const_cast<char*>(strchr(launcher_str, '=')); - - if (!launcher) - { - fprintf(stderr, _("%s: Could not parse launcher string '%s'\n"), MIMEDB, launcher_str); - error=1; - return 0; - } - - /* Skip the = */ - launcher++; - - /* Make one we can change */ - std::string mut_launcher = launcher; - - /* Only use first launcher */ - end = strchr(launcher, ';'); - if (end) - mut_launcher.resize(end - launcher); - - launcher_full = (char *)my_malloc(mut_launcher.size() + strlen(APPLICATIONS_DIR)+1); - if (!launcher_full) - { - free((void *)launcher_str); - return 0; - } - - strcpy(launcher_full, APPLICATIONS_DIR); - strcat(launcher_full, mut_launcher.c_str()); - free((void *)launcher_str); - - std::string launcher_filename = get_filename(launcher_full); - - free(launcher_full); - - launcher_command_str = search_ini(launcher_filename.c_str(), "Exec"); - - if (!launcher_command_str) - { - fprintf(stderr, - _("%s: Default launcher '%s' does not specify how to start\n"), MIMEDB, - launcher_filename.c_str()); - return 0; - } - - launcher_command = strchr(launcher_command_str, '='); - launcher_command++; - - res = my_strdup(launcher_command); - - free((void *)launcher_command_str); - - 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; - - if (launch_len <= launch_pos) - { - int new_len = launch_len?2*launch_len:256; - char *new_buff = (char *)realloc(launch_buff, new_len); - if (!new_buff) - { - free(launch_buff); - launch_len = -1; - error=1; - return; - } - launch_buff = new_buff; - launch_len = new_len; - - } - 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; - - 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() -{ - size_t size = 100; - 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 const char *get_fullfile(const char *file) -{ - const char *fullfile; - - if (file[0] == '/') - { - fullfile = file; - } - else - { - char *cwd = my_getcwd(); - if (!cwd) - { - error = 1; - perror("getcwd"); - return 0; - } - - int l = strlen(cwd); - - char *tmp = (char *)my_malloc(l + strlen(file)+2); - if (!tmp) - { - free(cwd); - return 0; - } - strcpy(tmp, cwd); - if (cwd[l-1] != '/') - strcat(tmp, "/"); - strcat(tmp, file); - - free(cwd); - fullfile = tmp; - } - return fullfile; -} - - -/** - Write specified file as an URL -*/ -static void write_url(const char *file) -{ - const char *fullfile = get_fullfile(file); - const char *str = fullfile; - - if (str == 0) - { - launch_len = -1; - return; - } - - 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')) || - (strchr("-_.~/",*str) != 0)) - { - writer(*str); - } - else if (strchr("()?&=",*str) != 0) - { - writer('\\'); - writer(*str); - } - else - { - writer('%'); - writer_hex((unsigned char)*str); - } - str++; - } - if (fullfile != file) - free((void *)fullfile); - -} - -/** - Write specified file -*/ -static void write_file(const char *file, int print_path) -{ - const char *fullfile; - const char *str; - if (print_path) - { - fullfile = get_fullfile(file); - str = fullfile; - } - else - { - char *tmp = my_strdup(file); - if (!tmp) - { - return; - } - str = basename(tmp); - fullfile = tmp; - } - - 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((void *)fullfile); -} - -/** - Use the specified launch filter to launch all the files in the specified list. - - \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, const string_list_t &files, size_t fileno) -{ - char *filter_org=filter; - int count=0; - int launch_again=0; - - if (files.size() <= fileno) - return; - - - launch_pos=0; - - for (; *filter && !error; filter++) - { - if (*filter == '%') - { - filter++; - switch (*filter) - { - case 'u': - { - launch_again = 1; - write_url(files.at(fileno).c_str()); - break; - } - case 'U': - { - for (size_t i=0; i<files.size(); i++) - { - if (i != 0) - writer(' '); - write_url(files.at(i).c_str()); - if (error) - break; - } - - break; - } - - case 'f': - case 'n': - { - launch_again = 1; - write_file(files.at(fileno).c_str(), *filter == 'f'); - break; - } - - case 'F': - case 'N': - { - for (size_t i=0; i<files.size(); i++) - { - if (i != 0) - writer(' '); - write_file(files.at(i).c_str(), *filter == 'F'); - if (error) - break; - } - break; - } - - - case 'd': - { - const char *cpy = get_fullfile(files.at(fileno).c_str()); - char *dir; - - launch_again=1; - /* - We wish to modify this string, make sure it is only a copy - */ - if (cpy == files.at(fileno).c_str()) - cpy = my_strdup(cpy); - - if (cpy == 0) - { - break; - } - - dir=dirname((char *)cpy); - write_file(dir, 1); - free((void *)cpy); - - break; - } - - case 'D': - { - for (size_t i=0; i<files.size(); i++) - { - const char *cpy = get_fullfile(files.at(i).c_str()); - char *dir; - - /* - We wish to modify this string, make sure it is only a copy - */ - if (cpy == files.at(i).c_str()) - cpy = my_strdup(cpy); - - if (cpy == 0) - { - break; - } - dir=dirname((char *)cpy); - - if (i != 0) - writer(' '); - - write_file(dir, 1); - free((void *)cpy); - - } - break; - } - - default: - fprintf(stderr, _("%s: Unsupported switch '%c' in launch string '%s'\n"), MIMEDB, *filter, filter_org); - launch_len=0; - break; - - } - } - else - { - writer(*filter); - count++; - } - } - - if (error) - return; - - switch (launch_len) - { - case -1: - { - launch_len = 0; - fprintf(stderr, _("%s: Out of memory\n"), MIMEDB); - return; - } - case 0: - { - return; - } - default: - { - - writer(' '); - writer('&'); - writer('\0'); - - /* - Calling writer might fail in which case launch_buff gets freed. - */ - if (error) - return; - - if (system(launch_buff) == -1) - { - fprintf(stderr, _(ERROR_SYSTEM), MIMEDB, launch_buff); - exit(STATUS_ERROR_SYSTEM); - } - - break; - } - } - if (launch_again) - { - launch(filter_org, files, fileno+1); - } - -} - -/** - Do locale specific init -*/ -static void locale_init() -{ - setlocale(LC_ALL, ""); - fish_bindtextdomain(PACKAGE_NAME, LOCALEDIR); - fish_textdomain(PACKAGE_NAME); -} - - -/** - Main function. Parses options and calls helper function for any heavy lifting. -*/ -int main(int argc, char *argv[]) -{ - int input_type=FILEDATA; - int output_type=MIMETYPE; - - const char *mimetype; - char *output=0; - - int i; - - typedef std::map<std::string, string_list_t> launch_hash_t; - launch_hash_t launch_hash; - - locale_init(); - - /* - Parse options - */ - while (1) - { - static struct option - long_options[] = - { - { - "input-file-data", no_argument, 0, 't' - } - , - { - "input-filename", no_argument, 0, 'f' - } - , - { - "input-mime", no_argument, 0, 'i' - } - , - { - "output-mime", no_argument, 0, 'm' - } - , - { - "output-description", no_argument, 0, 'd' - } - , - { - "output-action", no_argument, 0, 'a' - } - , - { - "help", no_argument, 0, 'h' - } - , - { - "version", no_argument, 0, 'v' - } - , - { - "launch", no_argument, 0, 'l' - } - , - { - 0, 0, 0, 0 - } - } - ; - - int opt_index = 0; - - int opt = getopt_long(argc, - argv, - GETOPT_STRING, - long_options, - &opt_index); - - if (opt == -1) - break; - - switch (opt) - { - case 0: - break; - - case 't': - input_type=FILEDATA; - break; - - case 'f': - input_type=FILENAME; - break; - - case 'i': - input_type=MIMETYPE; - break; - - case 'm': - output_type=MIMETYPE; - break; - - case 'd': - output_type=DESCRIPTION; - break; - - case 'a': - output_type=ACTION; - break; - - case 'l': - output_type=LAUNCH; - break; - - case 'h': - print_help(argv[0], 1); - exit(0); - - case 'v': - printf(_("%s, version %s\n"), MIMEDB, get_fish_version()); - exit(0); - - case '?': - return 1; - - } - } - - if ((output_type == LAUNCH)&&(input_type==MIMETYPE)) - { - fprintf(stderr, _("%s: Can not launch a mimetype\n"), MIMEDB); - print_help(argv[0], 2); - exit(1); - } - - /* - Loop over all non option arguments and do the specified lookup - */ - - //fprintf( stderr, "Input %d, output %d\n", input_type, output_type ); - - 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) - { - fprintf(stderr, _("%s: Could not parse mimetype from argument '%s'\n"), MIMEDB, argv[i]); - error=1; - return 1; - } - - /* - Convert from mimetype to whatever, if needed - */ - switch (output_type) - { - case MIMETYPE: - { - output = (char *)mimetype; - break; - - } - case DESCRIPTION: - { - output = get_description(mimetype); - if (!output) - output = strdup(_("Unknown")); - - break; - } - case ACTION: - { - output = get_action(mimetype); - break; - } - 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. - */ - output = 0; - string_list_t &l = launch_hash[mimetype]; - l.push_back(argv[i]); - } - } - - /* - Print the glorious result - */ - if (output) - { - printf("%s\n", output); - if (output != mimetype) - free(output); - } - output = 0; - } - - /* - Perform the actual launching - */ - if (output_type == LAUNCH && !error) - { - for (launch_hash_t::iterator iter = launch_hash.begin(); iter != launch_hash.end(); ++iter) - { - const char *mimetype = iter->first.c_str(); - string_list_t &files = iter->second; - - char *launcher = get_action(mimetype); - - if (launcher) - { - launch(launcher, files, 0); - free(launcher); - } - } - } - - if (launch_buff) - free(launch_buff); - - if (start_re) - { - regfree(start_re); - regfree(stop_re); - free(start_re); - free(stop_re); - } - - xdg_mime_shutdown(); - - return error; -} |