[msitools] Start a msiextract tool
- From: Marc-Andre Lureau <malureau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [msitools] Start a msiextract tool
- Date: Thu, 17 Jan 2013 02:33:16 +0000 (UTC)
commit ceb4e1d3de8304c233b5294e2161fca1b7a3785e
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date: Thu Jan 17 03:32:23 2013 +0100
Start a msiextract tool
Makefile.am | 23 ++++++++
tools/msiextract.vala | 146 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 1c44715..7f790ad 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -29,6 +29,29 @@ msiinfo_SOURCES = tools/msiinfo.c
msiinfo_LDADD = -lmsi $(GLIB_LIBS) $(GSF_LIBS)
msiinfo_DEPENDENCIES = libmsi/libmsi.la
+# msiextract, something on the TODO list...
+
+noinst_PROGRAMS = msiextract
+
+msiextract_CFLAGS = -w
+
+msiextract_VALAFLAGS = \
+ --enable-experimental \
+ --pkg config \
+ --pkg gio-unix-2.0 \
+ --pkg libgcab-1.0 \
+ --pkg libmsi-1.0 \
+ --pkg posix \
+ --vapidir=. \
+ $(NULL)
+
+msiextract_SOURCES = \
+ tools/msiextract.vala \
+ $(NULL)
+
+msiextract_CPPFLAGS = $(wixl_CPPFLAGS)
+msiextract_LDADD = $(wixl_LDADD)
+
# Wixl
bin_PROGRAMS += wixl
diff --git a/tools/msiextract.vala b/tools/msiextract.vala
new file mode 100644
index 0000000..ba9b21a
--- /dev/null
+++ b/tools/msiextract.vala
@@ -0,0 +1,146 @@
+using Posix;
+
+static bool version;
+static bool list_only;
+[CCode (array_length = false, array_null_terminated = true)]
+static string[] files;
+
+private const OptionEntry[] options = {
+ { "version", 0, 0, OptionArg.NONE, ref version, N_("Display version number"), null },
+ { "list", 0, 0, OptionArg.NONE, ref list_only, N_("List files only"), null },
+ { "", 0, 0, OptionArg.FILENAME_ARRAY, ref files, null, N_("MSI_FILE...") },
+ { null }
+};
+
+public string get_long_name (string str) {
+ var names = str.split ("|", 2);
+ if (names.length == 2)
+ return names[1];
+
+ return str;
+}
+
+public void extract_cab (Libmsi.Database db, string cab,
+ HashTable<string, string> cab_to_name) throws GLib.Error
+{
+ if (cab.has_prefix ("#")) {
+ var name = cab.substring (1);
+ var query = new Libmsi.Query (db, "SELECT `Data` FROM `_Streams` WHERE `Name` = '%s'".printf (name));
+ query.execute (null);
+ var rec = query.fetch ();
+ var cabinet = new GCab.Cabinet ();
+ cabinet.load (rec.get_stream (1));
+ }
+}
+
+public int main (string[] args) {
+ Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
+ Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");
+ Intl.textdomain (Config.GETTEXT_PACKAGE);
+ GLib.Environment.set_application_name ("msiextract");
+
+ var parameter_string = _("- a msi files extracting tool");
+ var opt_context = new OptionContext (parameter_string);
+ opt_context.set_help_enabled (true);
+ opt_context.add_main_entries (options, null);
+
+ try {
+ opt_context.parse (ref args);
+ } catch (OptionError.BAD_VALUE err) {
+ GLib.stdout.printf (opt_context.get_help (true, null));
+ return 1;
+ } catch (OptionError error) {
+ warning (error.message);
+ }
+
+ if (version) {
+ GLib.stdout.printf ("%s\n", Config.PACKAGE_VERSION);
+ exit (0);
+ }
+
+ if (files.length < 1) {
+ GLib.stderr.printf (_("Please specify input files.\n"));
+ exit (1);
+ }
+
+ Libmsi.Database? db = null;
+ try {
+ db = new Libmsi.Database (files[0], null);
+ } catch (GLib.Error error) {
+ GLib.stderr.printf (error.message);
+ exit (1);
+ }
+
+ var directories = new HashTable<string, Libmsi.Record> (str_hash, str_equal);
+ try {
+ var query = new Libmsi.Query (db, "SELECT * FROM `Directory`");
+ query.execute (null);
+ do {
+ var rec = query.fetch ();
+ directories.insert (rec.get_string (1), rec);
+ } while (true);
+ } catch (GLib.Error error) {
+ }
+
+ var components_dir = new HashTable<string, string> (str_hash, str_equal);
+ try {
+ var query = new Libmsi.Query (db, "SELECT * FROM `Component`");
+ query.execute (null);
+ do {
+ var rec = query.fetch ();
+ var dir_id = rec.get_string (3);
+ var dir_rec = directories.lookup (dir_id);
+ var dir = get_long_name (dir_rec.get_string (3));
+ do {
+ var parent = dir_rec.get_string (2);
+ dir_rec = directories.lookup (parent);
+ if (dir_rec == null)
+ break;
+ parent = get_long_name (dir_rec.get_string (3));
+ // only by intuition...
+ if (dir_rec.get_string (1) == "ProgramFilesFolder")
+ parent = "Program Files";
+ else if (parent == ".")
+ continue;
+ else if (parent == "SourceDir")
+ break;
+ dir = Path.build_filename (parent, dir);
+ } while (true);
+
+ components_dir.insert (rec.get_string (1), dir);
+ } while (true);
+ } catch (GLib.Error error) {
+ }
+
+ var cab_to_name = new HashTable<string, string> (str_hash, str_equal);
+ try {
+ var query = new Libmsi.Query (db, "SELECT * FROM `File`");
+ query.execute (null);
+ do {
+ var rec = query.fetch ();
+ var dir = components_dir.lookup (rec.get_string (2));
+ var file = Path.build_filename (dir, get_long_name (rec.get_string (3)));
+ if (list_only)
+ GLib.stdout.printf ("%s\n", file);
+ cab_to_name.insert (rec.get_string (1), file);
+ } while (true);
+ } catch (GLib.Error error) {
+ }
+
+ if (list_only)
+ exit (0);
+
+ message ("FIXME: gcab doesn't support extraction yet!");
+ try {
+ var query = new Libmsi.Query (db, "SELECT * FROM `Media`");
+ query.execute (null);
+ do {
+ var rec = query.fetch ();
+ var cab = rec.get_string (4);
+ extract_cab (db, cab, cab_to_name);
+ } while (true);
+ } catch (GLib.Error error) {
+ }
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]