mirror of
https://github.com/rozniak/xfce-winxp-tc.git
synced 2026-05-01 03:31:33 +00:00
Enhancement: Fixes #324, ZIP archive shell extension
This commit is contained in:
@@ -16,6 +16,7 @@ shell/cpl/sysdm
|
||||
shell/desktop
|
||||
shell/explorer
|
||||
shell/run
|
||||
shell/shext/zip
|
||||
shell/taskband
|
||||
shell/winver
|
||||
wallpapers
|
||||
|
||||
@@ -23,7 +23,8 @@ GType wintc_sh_view_fs_get_type(void) G_GNUC_CONST;
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCIShextView* wintc_sh_view_fs_new(
|
||||
const gchar* path
|
||||
WinTCShextHost* shext_host,
|
||||
const gchar* path
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,14 +14,16 @@
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static WinTCIShextView* factory_view_by_guid_cb(
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const gchar* url
|
||||
WinTCShextHost* shext_host,
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const WinTCShextPathInfo* path_info
|
||||
);
|
||||
static WinTCIShextView* factory_view_for_filesystem(
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const gchar* url
|
||||
WinTCShextHost* shext_host,
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const WinTCShextPathInfo* path_info
|
||||
);
|
||||
|
||||
//
|
||||
@@ -79,9 +81,10 @@ void wintc_sh_init_namespace_tree(
|
||||
// CALLBACKS
|
||||
//
|
||||
static WinTCIShextView* factory_view_by_guid_cb(
|
||||
WINTC_UNUSED(WinTCShextViewAssoc assoc),
|
||||
WINTC_UNUSED(WinTCShextHost* shext_host),
|
||||
WINTC_UNUSED(WinTCShextViewAssoc assoc),
|
||||
const gchar* assoc_str,
|
||||
WINTC_UNUSED(const gchar* url)
|
||||
WINTC_UNUSED(const WinTCShextPathInfo* url)
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("shell: create new shell view for %s", assoc_str);
|
||||
@@ -107,14 +110,16 @@ static WinTCIShextView* factory_view_by_guid_cb(
|
||||
}
|
||||
|
||||
static WinTCIShextView* factory_view_for_filesystem(
|
||||
WinTCShextHost* shext_host,
|
||||
WINTC_UNUSED(WinTCShextViewAssoc assoc),
|
||||
WINTC_UNUSED(const gchar* assoc_str),
|
||||
const gchar* url
|
||||
const WinTCShextPathInfo* path_info
|
||||
)
|
||||
{
|
||||
const gchar* path_in_url = url + g_utf8_strlen("file://", -1);
|
||||
const gchar* path_in_url =
|
||||
path_info->base_path + g_utf8_strlen("file://", -1);
|
||||
|
||||
WINTC_LOG_DEBUG("shell: create new fs view for %s", url);
|
||||
WINTC_LOG_DEBUG("shell: create new fs view for %s", path_in_url);
|
||||
|
||||
return wintc_sh_view_fs_new(path_in_url);
|
||||
return wintc_sh_view_fs_new(shext_host, path_in_url);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/exec.h>
|
||||
#include <wintc/shcommon.h>
|
||||
#include <wintc/shellext.h>
|
||||
|
||||
#include "../public/vwfs.h"
|
||||
|
||||
@@ -9,7 +11,8 @@
|
||||
//
|
||||
enum
|
||||
{
|
||||
PROP_PATH = 1
|
||||
PROP_SHEXT_HOST = 1,
|
||||
PROP_PATH
|
||||
};
|
||||
|
||||
//
|
||||
@@ -19,6 +22,9 @@ static void wintc_sh_view_fs_ishext_view_interface_init(
|
||||
WinTCIShextViewInterface* iface
|
||||
);
|
||||
|
||||
static void wintc_sh_view_fs_dispose(
|
||||
GObject* object
|
||||
);
|
||||
static void wintc_sh_view_fs_finalize(
|
||||
GObject* object
|
||||
);
|
||||
@@ -94,6 +100,8 @@ struct _WinTCShViewFS
|
||||
GArray* items;
|
||||
gchar* parent_path;
|
||||
gchar* path;
|
||||
|
||||
WinTCShextHost* shext_host;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -115,10 +123,22 @@ static void wintc_sh_view_fs_class_init(
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = wintc_sh_view_fs_dispose;
|
||||
object_class->finalize = wintc_sh_view_fs_finalize;
|
||||
object_class->get_property = wintc_sh_view_fs_get_property;
|
||||
object_class->set_property = wintc_sh_view_fs_set_property;
|
||||
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_SHEXT_HOST,
|
||||
g_param_spec_object(
|
||||
"shext-host",
|
||||
"ShextHost",
|
||||
"The shell extension host.",
|
||||
WINTC_TYPE_SHEXT_HOST,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY
|
||||
)
|
||||
);
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_PATH,
|
||||
@@ -161,6 +181,17 @@ static void wintc_sh_view_fs_ishext_view_interface_init(
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_sh_view_fs_dispose(
|
||||
GObject* object
|
||||
)
|
||||
{
|
||||
WinTCShViewFS* view = WINTC_SH_VIEW_FS(object);
|
||||
|
||||
g_clear_object(&(view->shext_host));
|
||||
|
||||
(G_OBJECT_CLASS(wintc_sh_view_fs_parent_class))->dispose(object);
|
||||
}
|
||||
|
||||
static void wintc_sh_view_fs_finalize(
|
||||
GObject* object
|
||||
)
|
||||
@@ -206,6 +237,10 @@ static void wintc_sh_view_fs_set_property(
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHEXT_HOST:
|
||||
view->shext_host = g_value_dup_object(value);
|
||||
break;
|
||||
|
||||
case PROP_PATH:
|
||||
view->path = g_value_dup_string(value);
|
||||
|
||||
@@ -234,20 +269,54 @@ static gboolean wintc_sh_view_fs_activate_item(
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(view);
|
||||
GError* local_error = NULL;
|
||||
WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(view);
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
gchar* next_path =
|
||||
g_build_path(
|
||||
G_DIR_SEPARATOR_S,
|
||||
view_fs->path,
|
||||
item->display_name,
|
||||
NULL
|
||||
);
|
||||
// Retrieve MIME for the item
|
||||
//
|
||||
gchar* next_path = g_build_path(
|
||||
G_DIR_SEPARATOR_S,
|
||||
view_fs->path,
|
||||
item->display_name,
|
||||
NULL
|
||||
);
|
||||
gchar* mime_type = wintc_query_mime_for_file(
|
||||
next_path,
|
||||
&local_error
|
||||
);
|
||||
|
||||
path_info->base_path = g_strdup_printf("file://%s", next_path);
|
||||
if (!mime_type)
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Handle the item based on MIME, if it's a directory then we can set that
|
||||
// as our next location - otherwise, it depends if there is a shell
|
||||
// extension for handling the MIME type or not
|
||||
//
|
||||
if (g_strcmp0(mime_type, "inode/directory") == 0)
|
||||
{
|
||||
path_info->base_path = g_strdup_printf("file://%s", next_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wintc_shext_host_has_view_for_mime(view_fs->shext_host, mime_type))
|
||||
{
|
||||
path_info->base_path = g_strdup_printf("file://%s", next_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wintc_launch_command(next_path, &local_error))
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_free(mime_type);
|
||||
g_free(next_path);
|
||||
|
||||
return TRUE;
|
||||
@@ -411,13 +480,15 @@ static gboolean wintc_sh_view_fs_has_parent(
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCIShextView* wintc_sh_view_fs_new(
|
||||
const gchar* path
|
||||
WinTCShextHost* shext_host,
|
||||
const gchar* path
|
||||
)
|
||||
{
|
||||
return WINTC_ISHEXT_VIEW(
|
||||
g_object_new(
|
||||
WINTC_TYPE_SH_VIEW_FS,
|
||||
"path", path,
|
||||
"path", path,
|
||||
"shext-host", shext_host,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
@@ -26,6 +26,7 @@ include(../../packaging/cmake-inc/resources/CMakeLists.txt)
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
wintc_resolve_library(wintc-exec WINTC_EXEC)
|
||||
|
||||
configure_file(src/host_priv.h.in ${PROJECT_ROOT}/src/host_priv.h @ONLY)
|
||||
|
||||
@@ -61,6 +62,7 @@ target_include_directories(
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_EXEC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
@@ -68,6 +70,7 @@ target_link_directories(
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_EXEC_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
@@ -75,6 +78,7 @@ target_link_libraries(
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_EXEC_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-exec
|
||||
|
||||
@@ -29,24 +29,11 @@ typedef enum
|
||||
WINTC_SHEXT_VIEW_ASSOC_PATH
|
||||
} WinTCShextViewAssoc;
|
||||
|
||||
//
|
||||
// PUBLIC CALLBACK PROTOTYPES
|
||||
//
|
||||
typedef GtkWidget** (*WinTCShextPropertyPagesCtor) (
|
||||
const gchar* url,
|
||||
const gchar* mime_type
|
||||
);
|
||||
typedef WinTCIShextView* (*WinTCShextViewCtor) (
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const gchar* url
|
||||
);
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCShextHostClass WinTCShextHostClass;
|
||||
typedef struct _WinTCShextHost WinTCShextHost;
|
||||
typedef struct _WinTCShextHost WinTCShextHost;
|
||||
|
||||
#define WINTC_TYPE_SHEXT_HOST (wintc_shext_host_get_type())
|
||||
#define WINTC_SHEXT_HOST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_SHEXT_HOST, WinTCShextHost))
|
||||
@@ -57,6 +44,21 @@ typedef struct _WinTCShextHost WinTCShextHost;
|
||||
|
||||
GType wintc_shext_host_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC CALLBACK PROTOTYPES
|
||||
//
|
||||
typedef GtkWidget** (*WinTCShextPropertyPagesCtor) (
|
||||
WinTCShextHost* shext_host,
|
||||
const gchar* url,
|
||||
const gchar* mime_type
|
||||
);
|
||||
typedef WinTCIShextView* (*WinTCShextViewCtor) (
|
||||
WinTCShextHost* shext_host,
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const WinTCShextPathInfo* path_info
|
||||
);
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
@@ -84,6 +86,11 @@ WinTCIShextView* wintc_shext_host_get_view_for_path(
|
||||
GError** error
|
||||
);
|
||||
|
||||
gboolean wintc_shext_host_has_view_for_mime(
|
||||
WinTCShextHost* host,
|
||||
const gchar* mime_type
|
||||
);
|
||||
|
||||
gboolean wintc_shext_host_load_extensions(
|
||||
WinTCShextHost* host,
|
||||
WinTCShextLoadMode mode,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <dlfcn.h>
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/exec.h>
|
||||
|
||||
#include "../public/category.h"
|
||||
#include "../public/error.h"
|
||||
@@ -17,9 +18,9 @@ typedef gboolean (*ShextInitFunc) (
|
||||
);
|
||||
|
||||
typedef WinTCIShextView* (*LookupViewFunc) (
|
||||
WinTCShextHost* host,
|
||||
const gchar* path,
|
||||
GError** error
|
||||
WinTCShextHost* host,
|
||||
const WinTCShextPathInfo* path_info,
|
||||
GError** error
|
||||
);
|
||||
|
||||
//
|
||||
@@ -30,14 +31,14 @@ static void wintc_shext_host_finalize(
|
||||
);
|
||||
|
||||
WinTCIShextView* lookup_view_for_path_by_guid(
|
||||
WinTCShextHost* host,
|
||||
const gchar* path,
|
||||
GError** error
|
||||
WinTCShextHost* host,
|
||||
const WinTCShextPathInfo* path_info,
|
||||
GError** error
|
||||
);
|
||||
WinTCIShextView* lookup_view_for_path_by_mime(
|
||||
WinTCShextHost* host,
|
||||
const gchar* path,
|
||||
GError** error
|
||||
WinTCShextHost* host,
|
||||
const WinTCShextPathInfo* path_info,
|
||||
GError** error
|
||||
);
|
||||
|
||||
//
|
||||
@@ -186,7 +187,7 @@ WinTCIShextView* wintc_shext_host_get_view_for_path(
|
||||
view =
|
||||
s_lookup_view_funcs[i](
|
||||
host,
|
||||
path_info->base_path,
|
||||
path_info,
|
||||
&local_error
|
||||
);
|
||||
|
||||
@@ -231,6 +232,19 @@ WinTCIShextView* wintc_shext_host_get_view_for_path(
|
||||
return view;
|
||||
}
|
||||
|
||||
gboolean wintc_shext_host_has_view_for_mime(
|
||||
WinTCShextHost* host,
|
||||
const gchar* mime_type
|
||||
)
|
||||
{
|
||||
gchar* mime_u = g_ascii_strup(mime_type, -1);
|
||||
gboolean ret = g_hash_table_contains(host->map_views_by_mime, mime_u);
|
||||
|
||||
g_free(mime_u);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean wintc_shext_host_load_extensions(
|
||||
WinTCShextHost* host,
|
||||
WINTC_UNUSED(WinTCShextLoadMode mode),
|
||||
@@ -360,7 +374,7 @@ gboolean wintc_shext_host_use_view_for_mime(
|
||||
factory_cb
|
||||
);
|
||||
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean wintc_shext_host_use_view_for_path_regex(
|
||||
@@ -387,9 +401,9 @@ gboolean wintc_shext_host_use_view_for_real_path(
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
WinTCIShextView* lookup_view_for_path_by_guid(
|
||||
WinTCShextHost* host,
|
||||
const gchar* path,
|
||||
GError** error
|
||||
WinTCShextHost* host,
|
||||
const WinTCShextPathInfo* path_info,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
static GRegex* regex_guid = NULL;
|
||||
@@ -420,7 +434,12 @@ WinTCIShextView* lookup_view_for_path_by_guid(
|
||||
|
||||
WINTC_LOG_DEBUG("%s", "shellext: view lookup - try guid...");
|
||||
|
||||
g_regex_match(regex_guid, path, 0, &match_info);
|
||||
g_regex_match(
|
||||
regex_guid,
|
||||
path_info->base_path,
|
||||
0,
|
||||
&match_info
|
||||
);
|
||||
|
||||
if (g_match_info_get_match_count(match_info))
|
||||
{
|
||||
@@ -439,9 +458,10 @@ WinTCIShextView* lookup_view_for_path_by_guid(
|
||||
{
|
||||
view =
|
||||
ctor(
|
||||
host,
|
||||
WINTC_SHEXT_VIEW_ASSOC_VIEW_GUID,
|
||||
guid_u,
|
||||
path
|
||||
path_info
|
||||
);
|
||||
}
|
||||
else
|
||||
@@ -460,18 +480,15 @@ WinTCIShextView* lookup_view_for_path_by_guid(
|
||||
}
|
||||
|
||||
WinTCIShextView* lookup_view_for_path_by_mime(
|
||||
WinTCShextHost* host,
|
||||
const gchar* path,
|
||||
GError** error
|
||||
WinTCShextHost* host,
|
||||
const WinTCShextPathInfo* path_info,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
static GRegex* regex_scheme = NULL;
|
||||
|
||||
WinTCShextViewCtor ctor;
|
||||
GMatchInfo* match_info = NULL;
|
||||
gchar* mime;
|
||||
gchar* mime_u;
|
||||
gchar* scheme;
|
||||
WinTCIShextView* view = NULL;
|
||||
|
||||
if (!regex_scheme)
|
||||
@@ -492,16 +509,87 @@ WinTCIShextView* lookup_view_for_path_by_mime(
|
||||
|
||||
WINTC_LOG_DEBUG("%s", "shellext: view lookup - try scheme...");
|
||||
|
||||
g_regex_match(regex_scheme, path, 0, &match_info);
|
||||
|
||||
if (g_match_info_get_match_count(match_info))
|
||||
if (
|
||||
!g_regex_match(
|
||||
regex_scheme,
|
||||
path_info->base_path,
|
||||
0,
|
||||
&match_info
|
||||
)
|
||||
)
|
||||
{
|
||||
scheme = g_match_info_fetch(match_info, 1);
|
||||
mime = g_strdup_printf("x-scheme-handler/%s", scheme);
|
||||
mime_u = g_ascii_strup(mime, -1);
|
||||
g_match_info_free(match_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WINTC_LOG_DEBUG("shellext: view lookup - match scheme %s", mime_u);
|
||||
// Matched a scheme successfully, pull it out...
|
||||
//
|
||||
gchar* scheme = g_match_info_fetch(match_info, 1);
|
||||
gchar* mime = g_strdup_printf("x-scheme-handler/%s", scheme);
|
||||
gchar* mime_u = g_ascii_strup(mime, -1);
|
||||
|
||||
g_match_info_free(match_info);
|
||||
|
||||
// ...if it's file://, first see if it's a file that we have a more
|
||||
// specific MIME type handler for...
|
||||
//
|
||||
if (g_strcmp0(mime_u, "X-SCHEME-HANDLER/FILE") == 0)
|
||||
{
|
||||
const gchar* local_path = path_info->base_path + strlen("file://");
|
||||
gchar* target_mime = wintc_query_mime_for_file(
|
||||
local_path,
|
||||
error
|
||||
);
|
||||
gchar* target_mime_u;
|
||||
|
||||
if (!target_mime)
|
||||
{
|
||||
g_free(scheme);
|
||||
g_free(mime);
|
||||
g_free(mime_u);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target_mime_u = g_ascii_strup(target_mime, -1);
|
||||
|
||||
// No special handling for inode/directory, it should be the same as
|
||||
// the file:// URI scheme
|
||||
//
|
||||
if (g_strcmp0(target_mime_u, "INODE/DIRECTORY") != 0)
|
||||
{
|
||||
ctor =
|
||||
g_hash_table_lookup(
|
||||
host->map_views_by_mime,
|
||||
target_mime_u
|
||||
);
|
||||
|
||||
if (ctor)
|
||||
{
|
||||
WINTC_LOG_DEBUG(
|
||||
"shellext: view lookup - match file MIME %s",
|
||||
target_mime_u
|
||||
);
|
||||
|
||||
view =
|
||||
ctor(
|
||||
host,
|
||||
WINTC_SHEXT_VIEW_ASSOC_MIME,
|
||||
target_mime_u,
|
||||
path_info
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(target_mime);
|
||||
g_free(target_mime_u);
|
||||
}
|
||||
|
||||
// ...if no special handling occurred, just look up a handler for the
|
||||
// scheme and use that
|
||||
//
|
||||
if (!view)
|
||||
{
|
||||
ctor =
|
||||
g_hash_table_lookup(
|
||||
host->map_views_by_mime,
|
||||
@@ -510,20 +598,24 @@ WinTCIShextView* lookup_view_for_path_by_mime(
|
||||
|
||||
if (ctor)
|
||||
{
|
||||
WINTC_LOG_DEBUG(
|
||||
"shellext: view lookup - match scheme %s",
|
||||
mime_u
|
||||
);
|
||||
|
||||
view =
|
||||
ctor(
|
||||
host,
|
||||
WINTC_SHEXT_VIEW_ASSOC_MIME,
|
||||
mime_u,
|
||||
path
|
||||
path_info
|
||||
);
|
||||
}
|
||||
|
||||
g_free(scheme);
|
||||
g_free(mime);
|
||||
g_free(mime_u);
|
||||
}
|
||||
|
||||
g_match_info_free(match_info);
|
||||
g_free(scheme);
|
||||
g_free(mime);
|
||||
g_free(mime_u);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ wintc_resolve_library(wintc-shellext WINTC_SHELLEXT)
|
||||
add_library(
|
||||
libwintc-cpl-printers
|
||||
src/shext.c
|
||||
src/shext.h
|
||||
src/vwprntrs.c
|
||||
src/vwprntrs.h
|
||||
)
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
#include <wintc/shcommon.h>
|
||||
#include <wintc/shellext.h>
|
||||
|
||||
#include "shext.h"
|
||||
#include "vwprntrs.h"
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static WinTCIShextView* factory_view_cpl_printers(
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const gchar* url
|
||||
WinTCShextHost* shext_host,
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const WinTCShextPathInfo* path_info
|
||||
);
|
||||
|
||||
//
|
||||
@@ -38,9 +38,10 @@ gboolean shext_init(
|
||||
// CALLBACKS
|
||||
//
|
||||
static WinTCIShextView* factory_view_cpl_printers(
|
||||
WINTC_UNUSED(WinTCShextViewAssoc assoc),
|
||||
WINTC_UNUSED(const gchar* assoc_str),
|
||||
WINTC_UNUSED(const gchar* url)
|
||||
WINTC_UNUSED(WinTCShextHost* shext_host),
|
||||
WINTC_UNUSED(WinTCShextViewAssoc assoc),
|
||||
WINTC_UNUSED(const gchar* assoc_str),
|
||||
WINTC_UNUSED(const WinTCShextPathInfo* path_info)
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("%s", "cpl-prntrs: create new cpl printers view");
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef __SHEXT_H__
|
||||
#define __SHEXT_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <wintc/shellext.h>
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
gboolean shext_init(
|
||||
WinTCShextHost* shext_host
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -204,7 +204,10 @@ static void on_explorer_wnd_location_changed(
|
||||
&path_info
|
||||
);
|
||||
|
||||
if (path_info.extended_path)
|
||||
if (
|
||||
path_info.extended_path &&
|
||||
strlen(path_info.extended_path) > 0
|
||||
)
|
||||
{
|
||||
gtk_entry_set_text(
|
||||
GTK_ENTRY(entry),
|
||||
|
||||
5
shell/shext/README.MD
Normal file
5
shell/shext/README.MD
Normal file
@@ -0,0 +1,5 @@
|
||||
# Shell Extensions
|
||||
This directory contains source code for the built-in shell extensions.
|
||||
|
||||
## Structure
|
||||
The structure under each directory is fairly typical for that of a CMake project library under `/shared`, only with some modifications for deploying a shell extension (aka, putting the library in the right place, so it gets loaded at runtime).
|
||||
78
shell/shext/zip/CMakeLists.txt
Normal file
78
shell/shext/zip/CMakeLists.txt
Normal file
@@ -0,0 +1,78 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(
|
||||
libwintc-shext-zip
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion ZIP file shell extension."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS true)
|
||||
set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
include(../../../packaging/cmake-inc/libraries/CMakeLists.txt)
|
||||
include(../../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
wintc_resolve_library(wintc-shellext WINTC_SHELLEXT)
|
||||
wintc_resolve_library(libzip ZIP)
|
||||
|
||||
add_library(
|
||||
libwintc-shext-zip
|
||||
src/shext.c
|
||||
src/vwzip.c
|
||||
src/vwzip.h
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
libwintc-shext-zip
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
libwintc-shext-zip
|
||||
SYSTEM
|
||||
BEFORE
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_SHELLEXT_INCLUDE_DIRS}
|
||||
PRIVATE ${ZIP_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
libwintc-shext-zip
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_SHELLEXT_LIBRARY_DIRS}
|
||||
PRIVATE ${ZIP_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
libwintc-shext-zip
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_SHELLEXT_LIBRARIES}
|
||||
PRIVATE ${ZIP_LIBRARIES}
|
||||
)
|
||||
|
||||
#
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
|
||||
install(
|
||||
TARGETS libwintc-shext-zip
|
||||
DESTINATION ${LIB_DIR}/wintc/shext
|
||||
)
|
||||
2
shell/shext/zip/README.MD
Normal file
2
shell/shext/zip/README.MD
Normal file
@@ -0,0 +1,2 @@
|
||||
# libwintc-shext-zip
|
||||
This directory contains the source code for the ZIP files shell extension, to allow ZIP file management within Explorer.
|
||||
5
shell/shext/zip/deps
Normal file
5
shell/shext/zip/deps
Normal file
@@ -0,0 +1,5 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-shellext
|
||||
bt,rt:zip
|
||||
52
shell/shext/zip/src/shext.c
Normal file
52
shell/shext/zip/src/shext.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/shellext.h>
|
||||
|
||||
#include "vwzip.h"
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static WinTCIShextView* factory_view_zip(
|
||||
WinTCShextHost* shext_host,
|
||||
WinTCShextViewAssoc assoc,
|
||||
const gchar* assoc_str,
|
||||
const WinTCShextPathInfo* path_info
|
||||
);
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
gboolean shext_init(
|
||||
WinTCShextHost* shext_host
|
||||
)
|
||||
{
|
||||
WINTC_RETURN_VAL_IF_FAIL(
|
||||
wintc_shext_host_use_view_for_mime(
|
||||
shext_host,
|
||||
"application/zip",
|
||||
factory_view_zip
|
||||
),
|
||||
FALSE
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static WinTCIShextView* factory_view_zip(
|
||||
WINTC_UNUSED(WinTCShextHost* shext_host),
|
||||
WINTC_UNUSED(WinTCShextViewAssoc assoc),
|
||||
WINTC_UNUSED(const gchar* assoc_str),
|
||||
const WinTCShextPathInfo* path_info
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("%s", "shext-zip: create new zip view");
|
||||
|
||||
return wintc_view_zip_new(
|
||||
path_info->base_path,
|
||||
path_info->extended_path
|
||||
);
|
||||
}
|
||||
566
shell/shext/zip/src/vwzip.c
Normal file
566
shell/shext/zip/src/vwzip.c
Normal file
@@ -0,0 +1,566 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/shellext.h>
|
||||
#include <string.h>
|
||||
#include <zip.h>
|
||||
|
||||
#include "vwzip.h"
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
//
|
||||
enum
|
||||
{
|
||||
PROP_PATH = 1,
|
||||
PROP_REL_PATH
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_view_zip_ishext_view_interface_init(
|
||||
WinTCIShextViewInterface* iface
|
||||
);
|
||||
|
||||
static void wintc_view_zip_finalize(
|
||||
GObject* object
|
||||
);
|
||||
static void wintc_view_zip_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
|
||||
static gboolean wintc_view_zip_activate_item(
|
||||
WinTCIShextView* view,
|
||||
WinTCShextViewItem* item,
|
||||
WinTCShextPathInfo* path_info,
|
||||
GError** error
|
||||
);
|
||||
|
||||
static void wintc_view_zip_refresh_items(
|
||||
WinTCIShextView* view
|
||||
);
|
||||
|
||||
static void wintc_view_zip_get_actions_for_item(
|
||||
WinTCIShextView* view,
|
||||
WinTCShextViewItem* item
|
||||
);
|
||||
|
||||
static void wintc_view_zip_get_actions_for_view(
|
||||
WinTCIShextView* view
|
||||
);
|
||||
|
||||
static const gchar* wintc_view_zip_get_display_name(
|
||||
WinTCIShextView* view
|
||||
);
|
||||
|
||||
static void wintc_view_zip_get_parent_path(
|
||||
WinTCIShextView* view,
|
||||
WinTCShextPathInfo* path_info
|
||||
);
|
||||
|
||||
static void wintc_view_zip_get_path(
|
||||
WinTCIShextView* view,
|
||||
WinTCShextPathInfo* path_info
|
||||
);
|
||||
|
||||
static gboolean wintc_view_zip_has_parent(
|
||||
WinTCIShextView* view
|
||||
);
|
||||
|
||||
static gboolean zip_entry_is_in_dir(
|
||||
const gchar* this_dir,
|
||||
const gchar* entry,
|
||||
gint* name_offset
|
||||
);
|
||||
|
||||
static void clear_view_item(
|
||||
WinTCShextViewItem* item
|
||||
);
|
||||
|
||||
//
|
||||
// GLIB OOP/CLASS INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCViewZipClass
|
||||
{
|
||||
GObjectClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCViewZip
|
||||
{
|
||||
GObject __parent__;
|
||||
|
||||
// ZIP state
|
||||
//
|
||||
GArray* items;
|
||||
gchar* parent_path;
|
||||
gchar* rel_path;
|
||||
gchar* zip_uri;
|
||||
};
|
||||
|
||||
//
|
||||
// GLIB TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE_WITH_CODE(
|
||||
WinTCViewZip,
|
||||
wintc_view_zip,
|
||||
G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE(
|
||||
WINTC_TYPE_ISHEXT_VIEW,
|
||||
wintc_view_zip_ishext_view_interface_init
|
||||
)
|
||||
)
|
||||
|
||||
static void wintc_view_zip_class_init(
|
||||
WinTCViewZipClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = wintc_view_zip_finalize;
|
||||
object_class->set_property = wintc_view_zip_set_property;
|
||||
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_PATH,
|
||||
g_param_spec_string(
|
||||
"path",
|
||||
"Path",
|
||||
"The path of the ZIP file to open.",
|
||||
NULL,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY
|
||||
)
|
||||
);
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_REL_PATH,
|
||||
g_param_spec_string(
|
||||
"relative-path",
|
||||
"RelativePath",
|
||||
"The relative path within the ZIP file to view.",
|
||||
NULL,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_view_zip_init(
|
||||
WinTCViewZip* self
|
||||
)
|
||||
{
|
||||
self->items = g_array_new(FALSE, TRUE, sizeof (WinTCShextViewItem));
|
||||
|
||||
g_array_set_clear_func(
|
||||
self->items,
|
||||
(GDestroyNotify) clear_view_item
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_view_zip_ishext_view_interface_init(
|
||||
WinTCIShextViewInterface* iface
|
||||
)
|
||||
{
|
||||
iface->activate_item = wintc_view_zip_activate_item;
|
||||
iface->refresh_items = wintc_view_zip_refresh_items;
|
||||
iface->get_actions_for_item = wintc_view_zip_get_actions_for_item;
|
||||
iface->get_actions_for_view = wintc_view_zip_get_actions_for_view;
|
||||
iface->get_display_name = wintc_view_zip_get_display_name;
|
||||
iface->get_parent_path = wintc_view_zip_get_parent_path;
|
||||
iface->get_path = wintc_view_zip_get_path;
|
||||
iface->has_parent = wintc_view_zip_has_parent;
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_view_zip_finalize(
|
||||
GObject* object
|
||||
)
|
||||
{
|
||||
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(object);
|
||||
|
||||
g_array_free(view_zip->items, TRUE);
|
||||
g_free(view_zip->parent_path);
|
||||
g_free(view_zip->rel_path);
|
||||
g_free(view_zip->zip_uri);
|
||||
|
||||
(G_OBJECT_CLASS(wintc_view_zip_parent_class))->finalize(object);
|
||||
}
|
||||
|
||||
static void wintc_view_zip_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PATH:
|
||||
view_zip->zip_uri = g_value_dup_string(value);
|
||||
view_zip->parent_path = g_path_get_dirname(view_zip->zip_uri);
|
||||
break;
|
||||
|
||||
case PROP_REL_PATH:
|
||||
view_zip->rel_path = g_value_dup_string(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// INTERFACE METHODS
|
||||
//
|
||||
static gboolean wintc_view_zip_activate_item(
|
||||
WinTCIShextView* view,
|
||||
WinTCShextViewItem* item,
|
||||
WinTCShextPathInfo* path_info,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(view);
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
gboolean is_dir = g_str_has_suffix(item->priv, G_DIR_SEPARATOR_S);
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
path_info->base_path = g_strdup(view_zip->zip_uri);
|
||||
path_info->extended_path = g_strdup(item->priv);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// TODO: We'll need to extract files first to tmp to be able to open
|
||||
// them - deal with in a separate issue
|
||||
//
|
||||
g_set_error(
|
||||
error,
|
||||
WINTC_GENERAL_ERROR,
|
||||
WINTC_GENERAL_ERROR_NOTIMPL,
|
||||
"ZIP file extraction not implemented yet."
|
||||
);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void wintc_view_zip_refresh_items(
|
||||
WinTCIShextView* view
|
||||
)
|
||||
{
|
||||
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(view);
|
||||
|
||||
WINTC_LOG_DEBUG("%s", "shext-zip: refresh zip view");
|
||||
|
||||
// Open the archive
|
||||
//
|
||||
const gchar* path = view_zip->zip_uri + strlen("file://");
|
||||
|
||||
gint zip_error = 0;
|
||||
zip_t* zip_file = zip_open(path, 0, &zip_error);
|
||||
|
||||
if (!zip_file)
|
||||
{
|
||||
zip_error_t zip_error_st;
|
||||
|
||||
zip_error_init_with_code(&zip_error_st, zip_error);
|
||||
|
||||
// FIXME: Need a proper way of returning error to caller!
|
||||
g_critical(
|
||||
"shext-zip: can't open %s , %s",
|
||||
path,
|
||||
zip_error_strerror(&zip_error_st)
|
||||
);
|
||||
|
||||
zip_error_fini(&zip_error_st);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Read through the entries
|
||||
// FIXME: Probably want to cap max num of entries? Check zip bombs to see
|
||||
// what happens - don't want to get nuked by a crazy zip archive
|
||||
//
|
||||
gint64 n_entries = zip_get_num_entries(zip_file, 0);
|
||||
gint64 n_local_entries = 0;
|
||||
|
||||
g_array_remove_range(
|
||||
view_zip->items,
|
||||
0,
|
||||
view_zip->items->len
|
||||
);
|
||||
g_array_set_size(
|
||||
view_zip->items,
|
||||
n_entries
|
||||
);
|
||||
|
||||
for (gint64 i = 0; i < n_entries; i++)
|
||||
{
|
||||
const gchar* entry_name = zip_get_name(zip_file, (guint64) i, 0);
|
||||
|
||||
// Only want to add the entries in the current relative dir
|
||||
//
|
||||
gint name_offset = 0;
|
||||
|
||||
if (!zip_entry_is_in_dir(view_zip->rel_path, entry_name, &name_offset))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
gchar* entry_copy = g_strdup(entry_name);
|
||||
WinTCShextViewItem* item = &g_array_index(
|
||||
view_zip->items,
|
||||
WinTCShextViewItem,
|
||||
n_local_entries
|
||||
);
|
||||
|
||||
item->display_name = entry_copy + name_offset;
|
||||
item->icon_name = g_str_has_suffix(entry_name, G_DIR_SEPARATOR_S) ?
|
||||
"inode-directory" : "empty";
|
||||
item->priv = entry_copy;
|
||||
|
||||
n_local_entries++;
|
||||
}
|
||||
|
||||
zip_close(zip_file);
|
||||
|
||||
// Emit the entries
|
||||
//
|
||||
WinTCShextViewItemsAddedData update = { 0 };
|
||||
|
||||
g_array_set_size(
|
||||
view_zip->items,
|
||||
n_local_entries
|
||||
);
|
||||
|
||||
update.items = &g_array_index(
|
||||
view_zip->items,
|
||||
WinTCShextViewItem,
|
||||
0
|
||||
);
|
||||
update.num_items = n_local_entries;
|
||||
update.done = TRUE;
|
||||
|
||||
_wintc_ishext_view_items_added(view, &update);
|
||||
}
|
||||
|
||||
static void wintc_view_zip_get_actions_for_item(
|
||||
WINTC_UNUSED(WinTCIShextView* view),
|
||||
WINTC_UNUSED(WinTCShextViewItem* item)
|
||||
)
|
||||
{
|
||||
g_critical("%s Not Implemented", __func__);
|
||||
}
|
||||
|
||||
static void wintc_view_zip_get_actions_for_view(
|
||||
WINTC_UNUSED(WinTCIShextView* view)
|
||||
)
|
||||
{
|
||||
g_critical("%s Not Implemented", __func__);
|
||||
}
|
||||
|
||||
static const gchar* wintc_view_zip_get_display_name(
|
||||
WinTCIShextView* view
|
||||
)
|
||||
{
|
||||
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(view);
|
||||
|
||||
// FIXME: Like FS view in shell, this could be broken maybe if there's
|
||||
// an escaped dir separator in the filename?
|
||||
//
|
||||
if (view_zip->rel_path)
|
||||
{
|
||||
// This deals with the fact that the ZIP relative paths are essentially
|
||||
// a partial path, dirs are like this:
|
||||
// somedir/
|
||||
// somedir/another/
|
||||
//
|
||||
// This screws with the usual path APIs which assume absolute paths, or
|
||||
// at the very least they don't like trailing slashes - here we get the
|
||||
// last component by searching for the second-to-last slash, and return
|
||||
// everything after it
|
||||
//
|
||||
// Of course if the path is only a single component like the first
|
||||
// example, then next == end will be true on the very first iteration,
|
||||
// in which case we can just return the path as-is
|
||||
//
|
||||
const gchar* end = strrchr(view_zip->rel_path, G_DIR_SEPARATOR);
|
||||
const gchar* last = view_zip->rel_path;
|
||||
const gchar* next = strchr(view_zip->rel_path, G_DIR_SEPARATOR);
|
||||
|
||||
while (next != end)
|
||||
{
|
||||
next++;
|
||||
|
||||
last = next;
|
||||
next = strchr(next, G_DIR_SEPARATOR);
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
else
|
||||
{
|
||||
return strrchr(view_zip->zip_uri, G_DIR_SEPARATOR) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void wintc_view_zip_get_parent_path(
|
||||
WinTCIShextView* view,
|
||||
WinTCShextPathInfo* path_info
|
||||
)
|
||||
{
|
||||
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(view);
|
||||
|
||||
// If we have a relative path, then use the relative path parent... unless
|
||||
// the relative path parent is the root of the zip, in which case just
|
||||
// return the zip's path only
|
||||
//
|
||||
if (view_zip->rel_path)
|
||||
{
|
||||
// A bit like above, we can't just use g_path_get_dirname because it
|
||||
// doesn't like the trailing slash - so here we will deal with
|
||||
// retrieving the position of the second-to-last slash, and return
|
||||
// everything before it
|
||||
//
|
||||
// Have a look at the example paths in the above comment and this
|
||||
// logic should make sense to you
|
||||
//
|
||||
const gchar* end = strrchr(view_zip->rel_path, G_DIR_SEPARATOR);
|
||||
const gchar* last = view_zip->rel_path;
|
||||
const gchar* next = strchr(view_zip->rel_path, G_DIR_SEPARATOR);
|
||||
|
||||
while (next != end)
|
||||
{
|
||||
next++;
|
||||
|
||||
last = next;
|
||||
next = strchr(next, G_DIR_SEPARATOR);
|
||||
}
|
||||
|
||||
path_info->base_path = g_strdup(view_zip->zip_uri);
|
||||
|
||||
if (last != view_zip->rel_path)
|
||||
{
|
||||
gint len = last - view_zip->rel_path;
|
||||
gchar* rel_parent = g_malloc0((sizeof(gchar) * len) + 1);
|
||||
|
||||
strncpy(rel_parent, view_zip->rel_path, len);
|
||||
|
||||
path_info->extended_path = rel_parent;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
path_info->base_path = g_strdup(view_zip->parent_path);
|
||||
}
|
||||
|
||||
static void wintc_view_zip_get_path(
|
||||
WinTCIShextView* view,
|
||||
WinTCShextPathInfo* path_info
|
||||
)
|
||||
{
|
||||
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(view);
|
||||
|
||||
path_info->base_path = g_strdup(view_zip->zip_uri);
|
||||
path_info->extended_path = g_strdup(view_zip->rel_path);
|
||||
}
|
||||
|
||||
static gboolean wintc_view_zip_has_parent(
|
||||
WINTC_UNUSED(WinTCIShextView* view)
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCIShextView* wintc_view_zip_new(
|
||||
const gchar* path,
|
||||
const gchar* rel_path
|
||||
)
|
||||
{
|
||||
return WINTC_ISHEXT_VIEW(
|
||||
g_object_new(
|
||||
WINTC_TYPE_VIEW_ZIP,
|
||||
"path", path,
|
||||
"relative-path", rel_path,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static gboolean zip_entry_is_in_dir(
|
||||
const gchar* this_dir,
|
||||
const gchar* entry,
|
||||
gint* name_offset
|
||||
)
|
||||
{
|
||||
const gchar* next_ds;
|
||||
|
||||
*name_offset = 0;
|
||||
|
||||
// If we're at the root of the zip, then we just scrub off any file that is
|
||||
// in a subdir, nothing else needed
|
||||
//
|
||||
if (!this_dir)
|
||||
{
|
||||
next_ds = strchr(entry, G_DIR_SEPARATOR);
|
||||
|
||||
return !next_ds || next_ds == (entry + strlen(entry) - 1);
|
||||
}
|
||||
|
||||
// Exclude the dir itself
|
||||
//
|
||||
if (g_strcmp0(entry, this_dir) == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// We're in a subdir, so any file not in this subdir is obviously binned
|
||||
//
|
||||
if (!g_str_has_prefix(entry, this_dir))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Finally, check that there are no more directory components after our
|
||||
// path
|
||||
//
|
||||
const gchar* entry_in_dir = entry + strlen(this_dir);
|
||||
|
||||
next_ds = strchr(entry_in_dir, G_DIR_SEPARATOR);
|
||||
|
||||
if (!next_ds || next_ds == (entry + strlen(entry) - 1))
|
||||
{
|
||||
*name_offset = entry_in_dir - entry;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static void clear_view_item(
|
||||
WinTCShextViewItem* item
|
||||
)
|
||||
{
|
||||
// Don't need to bin display_name as it's an offset into priv which
|
||||
// contains the full path in the zip
|
||||
//
|
||||
g_clear_pointer(&(item->priv), g_free);
|
||||
}
|
||||
30
shell/shext/zip/src/vwzip.h
Normal file
30
shell/shext/zip/src/vwzip.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __VWZIP_H__
|
||||
#define __VWZIP_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <wintc/shellext.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCViewZipClass WinTCViewZipClass;
|
||||
typedef struct _WinTCViewZip WinTCViewZip;
|
||||
|
||||
#define WINTC_TYPE_VIEW_ZIP (wintc_view_zip_get_type())
|
||||
#define WINTC_VIEW_ZIP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_VIEW_ZIP, WinTCViewZip))
|
||||
#define WINTC_VIEW_ZIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_VIEW_ZIP, WinTCViewZipClass))
|
||||
#define IS_WINTC_VIEW_ZIP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_VIEW_ZIP))
|
||||
#define IS_WINTC_VIEW_ZIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_VIEW_ZIP))
|
||||
#define WINTC_VIEW_ZIP_GET_CLASS(obj) (G_TYPE_INSANCE_GET_CLASS((obj), WINTC_TYPE_VIEW_ZIP, WinTCViewZip))
|
||||
|
||||
GType wintc_view_zip_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCIShextView* wintc_view_zip_new(
|
||||
const gchar* path,
|
||||
const gchar* rel_path
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -40,3 +40,5 @@ wintc-syscfg-->bt,rt-->libwintc-syscfg
|
||||
wintc-winbrand-->bt,rt-->libwintc-winbrand
|
||||
xcursorgen-->bt,rt-->xcursorgen
|
||||
xdg-mime-->bt,rt-->xdg-utils
|
||||
zip-->bt-->libzip-dev
|
||||
zip-->rt-->libzip
|
||||
|
||||
@@ -31,3 +31,4 @@ wintc-syscfg-->bt,rt-->wintc-syscfg
|
||||
wintc-winbrand-->bt,rt-->wintc-winbrand
|
||||
xcursorgen-->bt,rt-->xorg-xcursorgen
|
||||
xdg-mime-->bt,rt-->xdg-utils
|
||||
zip-->bt,rt-->libzip
|
||||
|
||||
@@ -30,3 +30,4 @@ wintc-syscfg-->bt,rt-->wintc-syscfg
|
||||
wintc-winbrand-->bt,rt-->wintc-winbrand
|
||||
xcursorgen-->bt,rt-->xcursorgen
|
||||
xdg-mime-->bt,rt-->xdg-utils
|
||||
zip-->bt,rt-->libzip
|
||||
|
||||
@@ -41,3 +41,5 @@ wintc-syscfg-->bt,rt-->libwintc-syscfg
|
||||
wintc-winbrand-->bt,rt-->libwintc-winbrand
|
||||
xcursorgen-->bt,rt-->x11-apps
|
||||
xdg-mime-->bt,rt-->xdg-utils
|
||||
zip-->bt-->libzip-dev
|
||||
zip-->rt-->libzip4
|
||||
|
||||
@@ -40,3 +40,5 @@ wintc-syscfg-->bt,rt-->wintc-syscfg
|
||||
wintc-winbrand-->bt,rt-->wintc-winbrand
|
||||
xcursorgen-->bt,rt-->xcursorgen
|
||||
xdg-mime-->bt,rt-->xdg-utils
|
||||
zip-->bt-->libzip-devel
|
||||
zip-->rt-->libzip
|
||||
|
||||
@@ -40,3 +40,5 @@ wintc-syscfg-->bt,rt-->wintc-syscfg
|
||||
wintc-winbrand-->bt,rt-->wintc-winbrand
|
||||
xcursorgen-->bt,rt-->xcursorgen
|
||||
xdg-mime-->bt,rt-->xdg-utils
|
||||
zip-->bt-->libzip-devel
|
||||
zip-->rt-->libzip
|
||||
|
||||
Reference in New Issue
Block a user