Introduce the MimeHandler class
This commit is contained in:
parent
e5f5729e56
commit
94c0dae8a9
|
@ -32,6 +32,7 @@
|
||||||
# define LIBDESKTOP_DESKTOP_MIME_H
|
# define LIBDESKTOP_DESKTOP_MIME_H
|
||||||
|
|
||||||
# include <gtk/gtk.h>
|
# include <gtk/gtk.h>
|
||||||
|
# include "mimehandler.h"
|
||||||
|
|
||||||
|
|
||||||
/* Mime */
|
/* Mime */
|
||||||
|
@ -47,7 +48,7 @@ Mime * mime_new(GtkIconTheme * theme);
|
||||||
void mime_delete(Mime * mime);
|
void mime_delete(Mime * mime);
|
||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
char const * mime_get_handler(Mime * mime, char const * type,
|
MimeHandler * mime_get_handler(Mime * mime, char const * type,
|
||||||
char const * action);
|
char const * action);
|
||||||
int mime_set_handler(Mime * mime, char const * type, char const * action,
|
int mime_set_handler(Mime * mime, char const * type, char const * action,
|
||||||
char const * handler);
|
char const * handler);
|
||||||
|
|
70
include/Desktop/mimehandler.h
Normal file
70
include/Desktop/mimehandler.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2017 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS Desktop libDesktop */
|
||||||
|
/* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LIBDESKTOP_DESKTOP_MIMEHANDLER_H
|
||||||
|
# define LIBDESKTOP_DESKTOP_MIMEHANDLER_H
|
||||||
|
|
||||||
|
# include <System/config.h>
|
||||||
|
# include <System/string.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* MimeHandler */
|
||||||
|
/* types */
|
||||||
|
typedef struct _Hash MimeHandler;
|
||||||
|
|
||||||
|
typedef enum _MimeHandlerType
|
||||||
|
{
|
||||||
|
MIME_HANDLER_TYPE_UNKNOWN = 0,
|
||||||
|
MIME_HANDLER_TYPE_APPLICATION,
|
||||||
|
MIME_HANDLER_TYPE_DIRECTORY,
|
||||||
|
MIME_HANDLER_TYPE_URL
|
||||||
|
} MimeHandlerType;
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
MimeHandler * mimehandler_new(void);
|
||||||
|
MimeHandler * mimehandler_new_load(String const * name);
|
||||||
|
void mimehandler_delete(MimeHandler * handler);
|
||||||
|
|
||||||
|
/* accessors */
|
||||||
|
int mimehandler_can_display(MimeHandler * handler);
|
||||||
|
int mimehandler_can_execute(MimeHandler * handler);
|
||||||
|
|
||||||
|
String const * mimehandler_get_name(MimeHandler * handler);
|
||||||
|
String const * mimehandler_get_program(MimeHandler * handler);
|
||||||
|
MimeHandlerType mimehandler_get_type(MimeHandler * handler);
|
||||||
|
|
||||||
|
int mimehandler_is_hidden(MimeHandler * handler);
|
||||||
|
|
||||||
|
/* useful */
|
||||||
|
int mimehandler_load_by_name(MimeHandler * handler, String const * name);
|
||||||
|
int mimehandler_save(MimeHandler * handler);
|
||||||
|
|
||||||
|
#endif /* !LIBDESKTOP_DESKTOP_MIMEHANDLER_H */
|
|
@ -1,4 +1,4 @@
|
||||||
includes=about.h,accel.h,compat.h,help.h,menubar.h,message.h,mime.h,toolbar.h,widget.h
|
includes=about.h,accel.h,compat.h,help.h,menubar.h,message.h,mime.h,mimehandler.h,toolbar.h,widget.h
|
||||||
dist=Makefile
|
dist=Makefile
|
||||||
|
|
||||||
[about.h]
|
[about.h]
|
||||||
|
@ -22,6 +22,9 @@ install=$(INCLUDEDIR)/Desktop
|
||||||
[mime.h]
|
[mime.h]
|
||||||
install=$(INCLUDEDIR)/Desktop
|
install=$(INCLUDEDIR)/Desktop
|
||||||
|
|
||||||
|
[mimehandler.h]
|
||||||
|
install=$(INCLUDEDIR)/Desktop
|
||||||
|
|
||||||
[toolbar.h]
|
[toolbar.h]
|
||||||
install=$(INCLUDEDIR)/Desktop
|
install=$(INCLUDEDIR)/Desktop
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ void mime_delete(Mime * mime)
|
||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
/* mime_get_handler */
|
/* mime_get_handler */
|
||||||
char const * mime_get_handler(Mime * mime, char const * type,
|
MimeHandler * mime_get_handler(Mime * mime, char const * type,
|
||||||
char const * action)
|
char const * action)
|
||||||
{
|
{
|
||||||
char const * program;
|
char const * program;
|
||||||
|
@ -250,7 +250,7 @@ char const * mime_get_handler(Mime * mime, char const * type,
|
||||||
q[2] = '\0';
|
q[2] = '\0';
|
||||||
program = config_get(mime->config, p, action);
|
program = config_get(mime->config, p, action);
|
||||||
free(p);
|
free(p);
|
||||||
return program;
|
return mimehandler_new_load(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
257
src/mimehandler.c
Normal file
257
src/mimehandler.c
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2017 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS libDesktop */
|
||||||
|
/* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "Desktop.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
/* constants */
|
||||||
|
#define EXTENSION ".desktop"
|
||||||
|
#define SECTION "Desktop Entry"
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* functions */
|
||||||
|
/* mimehandler_new */
|
||||||
|
MimeHandler * mimehandler_new(void)
|
||||||
|
{
|
||||||
|
return config_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mimehandler_new_load */
|
||||||
|
MimeHandler * mimehandler_new_load(String const * name)
|
||||||
|
{
|
||||||
|
MimeHandler * handler;
|
||||||
|
|
||||||
|
if((handler = mimehandler_new()) == NULL)
|
||||||
|
return NULL;
|
||||||
|
if(mimehandler_load_by_name(handler, name) != 0)
|
||||||
|
{
|
||||||
|
mimehandler_delete(handler);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mimehandler_delete */
|
||||||
|
void mimehandler_delete(MimeHandler * handler)
|
||||||
|
{
|
||||||
|
config_delete(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* accessors */
|
||||||
|
/* mimehandler_can_display */
|
||||||
|
int mimehandler_can_display(MimeHandler * handler)
|
||||||
|
{
|
||||||
|
String const * p;
|
||||||
|
|
||||||
|
if((p = config_get(handler, SECTION, "NoDisplay")) == NULL)
|
||||||
|
return 1;
|
||||||
|
return (string_compare(p, "true") == 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mimehandler_can_execute */
|
||||||
|
static int _can_execute_access(String const * path, int mode);
|
||||||
|
static int _can_execute_access_path(String const * path,
|
||||||
|
String const * filename, int mode);
|
||||||
|
|
||||||
|
int mimehandler_can_execute(MimeHandler * handler)
|
||||||
|
{
|
||||||
|
String const * p;
|
||||||
|
|
||||||
|
if(mimehandler_get_type(handler) != MIME_HANDLER_TYPE_APPLICATION)
|
||||||
|
return 0;
|
||||||
|
if((p = config_get(handler, SECTION, "TryExec")) == NULL)
|
||||||
|
return 1;
|
||||||
|
return _can_execute_access(p, X_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _can_execute_access(String const * path, int mode)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
String const * p;
|
||||||
|
String * q;
|
||||||
|
String * last;
|
||||||
|
|
||||||
|
if(path[0] == '/')
|
||||||
|
return access(path, mode);
|
||||||
|
if((p = getenv("PATH")) == NULL)
|
||||||
|
return 0;
|
||||||
|
if((q = string_new(p)) == NULL)
|
||||||
|
return 0;
|
||||||
|
for(p = strtok_r(q, ":", &last); p != NULL;
|
||||||
|
p = strtok_r(NULL, ":", &last))
|
||||||
|
ret = _can_execute_access_path(p, path, mode);
|
||||||
|
string_delete(q);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _can_execute_access_path(String const * path,
|
||||||
|
String const * filename, int mode)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
String * p;
|
||||||
|
|
||||||
|
if((p = string_new_append(path, "/", filename, NULL)) == NULL)
|
||||||
|
return -1;
|
||||||
|
ret = access(p, mode);
|
||||||
|
string_delete(p);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mimehandler_get_name */
|
||||||
|
String const * mimehandler_get_name(MimeHandler * handler)
|
||||||
|
{
|
||||||
|
return config_get(handler, SECTION, "Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mimehandler_get_program */
|
||||||
|
String const * mimehandler_get_program(MimeHandler * handler)
|
||||||
|
{
|
||||||
|
switch(mimehandler_get_type(handler))
|
||||||
|
{
|
||||||
|
case MIME_HANDLER_TYPE_APPLICATION:
|
||||||
|
/* XXX may be a format string */
|
||||||
|
return config_get(handler, SECTION, "Exec");
|
||||||
|
case MIME_HANDLER_TYPE_DIRECTORY:
|
||||||
|
case MIME_HANDLER_TYPE_UNKNOWN:
|
||||||
|
case MIME_HANDLER_TYPE_URL:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mimehandler_get_type */
|
||||||
|
MimeHandlerType mimehandler_get_type(MimeHandler * handler)
|
||||||
|
{
|
||||||
|
String const * type;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
String const * name;
|
||||||
|
MimeHandlerType type;
|
||||||
|
} types[] =
|
||||||
|
{
|
||||||
|
{ "Application",MIME_HANDLER_TYPE_APPLICATION },
|
||||||
|
{ "Directory", MIME_HANDLER_TYPE_DIRECTORY },
|
||||||
|
{ "URL", MIME_HANDLER_TYPE_URL }
|
||||||
|
};
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if((type = config_get(handler, SECTION, "Type")) == NULL)
|
||||||
|
return MIME_HANDLER_TYPE_UNKNOWN;
|
||||||
|
for(i = 0; i < sizeof(types) / sizeof(*types); i++)
|
||||||
|
if(string_compare(types[i].name, type) == 0)
|
||||||
|
return types[i].type;
|
||||||
|
return MIME_HANDLER_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mimehandler_is_hidden */
|
||||||
|
int mimehandler_is_hidden(MimeHandler * handler)
|
||||||
|
{
|
||||||
|
String const * p;
|
||||||
|
|
||||||
|
if((p = config_get(handler, SECTION, "Hidden")) == NULL)
|
||||||
|
return 0;
|
||||||
|
return (string_compare(p, "true") == 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* useful */
|
||||||
|
/* mimehandler_load_by_name */
|
||||||
|
static int _load_by_name_path(MimeHandler * handler, String const * name,
|
||||||
|
String const * path);
|
||||||
|
|
||||||
|
int mimehandler_load_by_name(MimeHandler * handler, String const * name)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
String const fallback[] = ".local/share";
|
||||||
|
String const * path;
|
||||||
|
String const * homedir;
|
||||||
|
String * p;
|
||||||
|
String const * q;
|
||||||
|
String * last;
|
||||||
|
|
||||||
|
/* use $XDG_DATA_HOME if set and not empty */
|
||||||
|
if((path = getenv("XDG_DATA_HOME")) != NULL && strlen(path) > 0
|
||||||
|
&& _load_by_name_path(handler, name, path) == 0)
|
||||||
|
return 0;
|
||||||
|
/* fallback to "$HOME/.local/share" */
|
||||||
|
if((homedir = getenv("HOME")) == NULL)
|
||||||
|
homedir = g_get_home_dir();
|
||||||
|
if((p = string_new_append(homedir, "/", fallback, NULL)) == NULL)
|
||||||
|
return -1;
|
||||||
|
ret = _load_by_name_path(handler, name, p);
|
||||||
|
string_delete(p);
|
||||||
|
if(ret == 0)
|
||||||
|
return ret;
|
||||||
|
/* read through every XDG application folder */
|
||||||
|
if((path = getenv("XDG_DATA_DIRS")) == NULL || strlen(path) == 0)
|
||||||
|
path = "/usr/local/share:/usr/share";
|
||||||
|
if((p = string_new(path)) == NULL)
|
||||||
|
return -1;
|
||||||
|
for(q = strtok_r(p, ":", &last); q != NULL;
|
||||||
|
q = strtok_r(NULL, ":", &last))
|
||||||
|
if((ret = _load_by_name_path(handler, name, q)) == 0)
|
||||||
|
break;
|
||||||
|
string_delete(p);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _load_by_name_path(MimeHandler * handler, String const * name,
|
||||||
|
String const * path)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
String const applications[] = "/applications/";
|
||||||
|
String * pathname;
|
||||||
|
|
||||||
|
if((pathname = string_new_append(path, applications, name, EXTENSION,
|
||||||
|
NULL)) == NULL)
|
||||||
|
return -1;
|
||||||
|
ret = (config_reset(handler) == 0
|
||||||
|
&& config_load(handler, pathname) == 0
|
||||||
|
&& mimehandler_get_type(handler)
|
||||||
|
!= MIME_HANDLER_TYPE_UNKNOWN
|
||||||
|
&& mimehandler_get_name(handler) != NULL
|
||||||
|
&& mimehandler_is_hidden(handler) == 0)
|
||||||
|
? 0 : -1;
|
||||||
|
string_delete(pathname);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ dist=Makefile
|
||||||
|
|
||||||
[libDesktop]
|
[libDesktop]
|
||||||
type=library
|
type=library
|
||||||
sources=about.c,accel.c,compat.c,help.c,menubar.c,message.c,mime.c,toolbar.c,widget.c
|
sources=about.c,accel.c,compat.c,help.c,menubar.c,message.c,mime.c,mimehandler.c,toolbar.c,widget.c
|
||||||
install=$(PREFIX)/lib
|
install=$(PREFIX)/lib
|
||||||
|
|
||||||
[help.c]
|
[help.c]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user