aboutsummaryrefslogtreecommitdiffhomepage
path: root/mimedb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mimedb.cpp')
-rw-r--r--mimedb.cpp1471
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;
-}