summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2013-01-03 00:31:56 +0100
committerMarc-André Lureau <marcandre.lureau@gmail.com>2013-01-06 16:38:25 +0100
commit4f504716710736eab4c68e8b1fb2ece5f2373794 (patch)
tree51884083ff4b08664e88126bafe88687d8501eb6 /src
parentdd9db8647a05b2ba46fbd4df85f496f9de176741 (diff)
downloadmsitools-4f504716710736eab4c68e8b1fb2ece5f2373794.tar.gz
msitools-4f504716710736eab4c68e8b1fb2ece5f2373794.tar.xz
msitools-4f504716710736eab4c68e8b1fb2ece5f2373794.zip
Split ẅixl.vala in various files
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/builder.vala44
-rw-r--r--src/msi.vala399
-rw-r--r--src/wix.vala224
-rw-r--r--src/wixl.vala660
5 files changed, 670 insertions, 660 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 611952f..87323d1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,10 @@ AM_VALAFLAGS = \
$(NULL)
wixl_SOURCES = \
+ builder.vala \
+ msi.vala \
util.vala \
+ wix.vala \
wixl.vala \
$(NULL)
diff --git a/src/builder.vala b/src/builder.vala
new file mode 100644
index 0000000..439447b
--- /dev/null
+++ b/src/builder.vala
@@ -0,0 +1,44 @@
+namespace Wixl {
+
+ class WixBuilder: WixElementVisitor {
+ WixRoot root;
+ MsiDatabase db;
+
+ public WixBuilder (WixRoot root) {
+ this.root = root;
+ }
+
+ public MsiDatabase build () throws GLib.Error {
+ db = new MsiDatabase ();
+ root.accept (this);
+ return db;
+ }
+
+ public override void visit_product (WixProduct product) throws GLib.Error {
+ db.info.set_codepage (int.parse (product.Codepage));
+ db.info.set_author (product.Manufacturer);
+
+ db.table_property.add ("Manufacturer", product.Manufacturer);
+ db.table_property.add ("ProductLanguage", product.Codepage);
+ db.table_property.add ("ProductCode", add_braces (product.Id));
+ db.table_property.add ("ProductName", product.Name);
+ db.table_property.add ("ProductVersion", product.Version);
+ db.table_property.add ("UpgradeCode", add_braces (product.UpgradeCode));
+ }
+
+ public override void visit_package (WixPackage package) throws GLib.Error {
+ db.info.set_keywords (package.Keywords);
+ db.info.set_subject (package.Description);
+ db.info.set_comments (package.Comments);
+ }
+
+ public override void visit_icon (WixIcon icon) throws GLib.Error {
+ db.table_icon.add (icon.Id, icon.SourceFile);
+ }
+
+ public override void visit_property (WixProperty prop) throws GLib.Error {
+ db.table_property.add (prop.Id, prop.Value);
+ }
+ }
+
+} // Wixl
diff --git a/src/msi.vala b/src/msi.vala
new file mode 100644
index 0000000..f9920ee
--- /dev/null
+++ b/src/msi.vala
@@ -0,0 +1,399 @@
+namespace Wixl {
+
+ abstract class MsiTable: Object {
+ public string name;
+ public List<Libmsi.Record> records;
+
+ public abstract void create (Libmsi.Database db) throws GLib.Error;
+ }
+
+ class MsiTableIcon: MsiTable {
+ construct {
+ name = "Icon";
+ }
+
+ public void add (string id, string filename) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, id) ||
+ !rec.load_stream (2, filename))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `Icon` (`Name` CHAR(72) NOT NULL, `Data` OBJECT NOT NULL PRIMARY KEY `Name`)");
+ query.execute (null);
+ query = new Libmsi.Query (db, "INSERT INTO `Icon` (`Name`, `Data`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ class MsiTableAdminExecuteSequence: MsiTable {
+ construct {
+ name = "AdminExecuteSequence";
+ try {
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("InstallValidate", 1400);
+ add ("InstallInitialize", 1500);
+ add ("InstallAdminPackage", 3900);
+ add ("InstallFiles", 4000);
+ add ("InstallFinalize", 6600);
+ } catch (GLib.Error e) {
+ }
+ }
+
+ public void add (string action, int sequence) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, action) ||
+ !rec.set_int (2, sequence))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `AdminExecuteSequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
+ query.execute (null);
+
+ query = new Libmsi.Query (db, "INSERT INTO `AdminExecuteSequence` (`Action`, `Sequence`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ class MsiTableAdminUISequence: MsiTable {
+ construct {
+ name = "AdminUISequence";
+
+ try {
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("ExecuteAction", 1300);
+ } catch (GLib.Error e) {
+ }
+ }
+
+ public void add (string action, int sequence) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, action) ||
+ !rec.set_int (2, sequence))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `AdminUISequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
+ query.execute (null);
+
+ query = new Libmsi.Query (db, "INSERT INTO `AdminUISequence` (`Action`, `Sequence`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ class MsiTableAdvtExecuteSequence: MsiTable {
+ construct {
+ name = "AdvtExecuteSequence";
+
+ try {
+ add ("CostInitialize", 800);
+ add ("CostFinalize", 1000);
+ add ("InstallValidate", 1400);
+ add ("InstallInitialize", 1500);
+ add ("InstallFinalize", 6600);
+ add ("PublishFeatures", 6300);
+ add ("PublishProduct", 6400);
+ } catch (GLib.Error e) {
+ }
+ }
+
+ public void add (string action, int sequence) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, action) ||
+ !rec.set_int (2, sequence))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `AdvtExecuteSequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
+ query.execute (null);
+
+ query = new Libmsi.Query (db, "INSERT INTO `AdvtExecuteSequence` (`Action`, `Sequence`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ class MsiTableError: MsiTable {
+ construct {
+ name = "Error";
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `Error` (`Error` INT NOT NULL, `Message` CHAR(0) LOCALIZABLE PRIMARY KEY `Error`)");
+ query.execute (null);
+ }
+ }
+
+ class MsiTableFile: MsiTable {
+ construct {
+ name = "File";
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `File` (`File` CHAR(72) NOT NULL, `Component_` CHAR(72) NOT NULL, `FileName` CHAR(255) NOT NULL LOCALIZABLE, `FileSize` LONG NOT NULL, `Version` CHAR(72), `Language` CHAR(20), `Attributes` INT, `Sequence` LONG NOT NULL PRIMARY KEY `File`)");
+ query.execute (null);
+ }
+ }
+
+ class MsiTableInstallExecuteSequence: MsiTable {
+ construct {
+ name = "InstallExecuteSequence";
+
+ try {
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("InstallValidate", 1400);
+ add ("InstallInitialize", 1500);
+ add ("InstallFinalize", 6600);
+ add ("PublishFeatures", 6300);
+ add ("PublishProduct", 6400);
+ add ("ValidateProductID", 700);
+ add ("ProcessComponents", 1600);
+ add ("UnpublishFeatures", 1800);
+ add ("RegisterUser", 6000);
+ add ("RegisterProduct", 6100);
+ } catch (GLib.Error e) {
+ }
+ }
+
+ public void add (string action, int sequence) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, action) ||
+ !rec.set_int (2, sequence))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `InstallExecuteSequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
+ query.execute (null);
+
+ query = new Libmsi.Query (db, "INSERT INTO `InstallExecuteSequence` (`Action`, `Sequence`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ class MsiTableInstallUISequence: MsiTable {
+ construct {
+ name = "InstallUISequence";
+
+ try {
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("ExecuteAction", 1300);
+ add ("ValidateProductID", 700);
+ } catch (GLib.Error e) {
+ }
+ }
+
+ public void add (string action, int sequence) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, action) ||
+ !rec.set_int (2, sequence))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `InstallUISequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
+ query.execute (null);
+
+ query = new Libmsi.Query (db, "INSERT INTO `InstallUISequence` (`Action`, `Sequence`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+
+ }
+ }
+
+ class MsiTableMedia: MsiTable {
+ construct {
+ name = "Media";
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `Media` (`DiskId` INT NOT NULL, `LastSequence` LONG NOT NULL, `DiskPrompt` CHAR(64) LOCALIZABLE, `Cabinet` CHAR(255), `VolumeLabel` CHAR(32), `Source` CHAR(72) PRIMARY KEY `DiskId`)");
+ query.execute (null);
+ }
+ }
+
+ class MsiTableProperty: MsiTable {
+ construct {
+ name = "Property";
+ }
+
+ public void add (string prop, string value) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, prop) ||
+ !rec.set_string (2, value))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, "CREATE TABLE `Property` (`Property` CHAR(72) NOT NULL, `Value` CHAR(0) NOT NULL LOCALIZABLE PRIMARY KEY `Property`)");
+ query.execute (null);
+
+ query = new Libmsi.Query (db, "INSERT INTO `Property` (`Property`, `Value`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ class MsiTable_Validation: MsiTable {
+ construct {
+ name = "_Validation";
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ }
+ }
+
+ class MsiSummaryInfo: Object {
+ public Libmsi.SummaryInfo properties;
+
+ construct {
+ try {
+ properties = new Libmsi.SummaryInfo (null, uint.MAX);
+ } catch (GLib.Error error) {
+ critical (error.message);
+ }
+ }
+
+ public MsiSummaryInfo () {
+ }
+
+ public new void set_property (Libmsi.Property prop, Value value) throws GLib.Error {
+ if (value.type () == typeof (string))
+ properties.set_string (prop, (string) value);
+ else if (value.type () == typeof (int))
+ properties.set_int (prop, (int) value);
+ else if (value.type () == typeof (uint64))
+ properties.set_filetime (prop, (uint64) value);
+ else
+ critical ("Unhandled property type");
+ }
+
+ public void save (Libmsi.Database db) throws GLib.Error {
+ properties.save (db);
+ }
+
+ public void set_codepage (int value) throws GLib.Error {
+ set_property (Libmsi.Property.CODEPAGE, value);
+ }
+
+ public void set_author (string value) throws GLib.Error {
+ set_property (Libmsi.Property.AUTHOR, value);
+ }
+
+ public void set_keywords (string value) throws GLib.Error {
+ set_property (Libmsi.Property.KEYWORDS, value);
+ }
+
+ public void set_subject (string value) throws GLib.Error {
+ set_property (Libmsi.Property.SUBJECT, value);
+ }
+
+ public void set_comments (string value) throws GLib.Error {
+ set_property (Libmsi.Property.COMMENTS, value);
+ }
+
+ }
+
+ class MsiDatabase: Object {
+ public MsiSummaryInfo info;
+ public MsiTableProperty table_property;
+ public MsiTableIcon table_icon;
+
+ HashTable<string, MsiTable> tables;
+
+ construct {
+ info = new MsiSummaryInfo ();
+ try {
+ info.set_property (Libmsi.Property.TITLE, "Installation Database");
+ info.set_property (Libmsi.Property.TEMPLATE, "Intel;1033");
+ info.set_property (Libmsi.Property.UUID, uuid_generate ());
+ info.set_property (Libmsi.Property.CREATED_TM,
+ time_to_filetime (now ()));
+ info.set_property (Libmsi.Property.LASTSAVED_TM,
+ time_to_filetime (now ()));
+ info.set_property (Libmsi.Property.VERSION, 100);
+ info.set_property (Libmsi.Property.SOURCE, 2);
+ info.set_property (Libmsi.Property.APPNAME, Config.PACKAGE_STRING);
+ info.set_property (Libmsi.Property.SECURITY, 2);
+ } catch (GLib.Error error) {
+ critical (error.message);
+ }
+
+ tables = new HashTable<string, MsiTable> (str_hash, str_equal);
+ table_property = new MsiTableProperty ();
+ table_icon = new MsiTableIcon ();
+
+ foreach (var t in new MsiTable[] {
+ new MsiTableAdminExecuteSequence (),
+ new MsiTableAdminUISequence (),
+ new MsiTableAdvtExecuteSequence (),
+ new MsiTableError (),
+ new MsiTableFile (),
+ new MsiTableInstallExecuteSequence (),
+ new MsiTableInstallUISequence (),
+ new MsiTableMedia (),
+ table_property,
+ table_icon,
+ new MsiTable_Validation ()
+ }) {
+ tables.insert (t.name, t);
+ }
+ }
+
+ public MsiDatabase () {
+ // empty ctor
+ }
+
+ public void build (string filename) throws GLib.Error {
+ string name;
+ MsiTable table;
+
+ var db = new Libmsi.Database (filename, (string)2);
+ info.save (db);
+
+ var it = HashTableIter <string, MsiTable> (tables);
+ while (it.next (out name, out table))
+ table.create (db);
+
+ db.commit ();
+ }
+ }
+
+} // Wixl \ No newline at end of file
diff --git a/src/wix.vala b/src/wix.vala
new file mode 100644
index 0000000..3615912
--- /dev/null
+++ b/src/wix.vala
@@ -0,0 +1,224 @@
+namespace Wixl {
+
+ public abstract class WixElementVisitor: Object {
+ public abstract void visit_product (WixProduct product) throws GLib.Error;
+ public abstract void visit_icon (WixIcon icon) throws GLib.Error;
+ public abstract void visit_package (WixPackage package) throws GLib.Error;
+ public abstract void visit_property (WixProperty prop) throws GLib.Error;
+ }
+
+ public abstract class WixElement: Object {
+ public static string name;
+ public string Id { get; set; }
+ public List<WixElement> children;
+
+ static construct {
+ Value.register_transform_func (typeof (WixElement), typeof (string), (ValueTransform)WixElement.value_to_string);
+ }
+
+ public void add_child (WixElement e) {
+ children.append (e);
+ }
+
+ public virtual void load (Xml.Node *node) throws Wixl.Error {
+ if (node->name != name)
+ throw new Error.FAILED ("%s: invalid node %s".printf (name, node->name));
+
+ for (var prop = node->properties; prop != null; prop = prop->next) {
+ if (prop->type == Xml.ElementType.ATTRIBUTE_NODE)
+ set_property (prop->name, get_attribute_content (prop));
+ }
+ }
+
+ public string to_string () {
+ var type = get_type ();
+ var klass = (ObjectClass)type.class_ref ();
+ var str = type.name () + " {";
+
+ var i = 0;
+ foreach (var p in klass.list_properties ()) {
+ var value = Value (p.value_type);
+ get_property (p.name, ref value);
+ var valstr = value.holds (typeof (string)) ?
+ (string)value : value.strdup_contents ();
+ str += (i == 0 ? "" : ", ") + p.name + ": " + valstr;
+ i += 1;
+ }
+
+ return str + "}";
+ }
+
+ public static void value_to_string (Value src, out Value dest) {
+ WixElement e = value_get_element (src);
+
+ dest = e.to_string ();
+ }
+
+ public static WixElement? value_get_element (Value value) {
+ if (! value.holds (typeof (WixElement)))
+ return null;
+
+ return (WixElement)value.get_object ();
+ }
+
+ public virtual void accept (WixElementVisitor visitor) throws GLib.Error {
+ foreach (var child in children)
+ child.accept (visitor);
+ }
+ }
+
+ public class WixProperty: WixElement {
+ static construct {
+ name = "Property";
+ }
+
+ public string Value { get; set; }
+
+ public override void accept (WixElementVisitor visitor) throws GLib.Error {
+ visitor.visit_property (this);
+ }
+ }
+
+ public class WixPackage: WixElement {
+ static construct {
+ name = "Package";
+ }
+
+ public string Keywords { get; set; }
+ public string InstallerDescription { get; set; }
+ public string InstallerComments { get; set; }
+ public string Manufacturer { get; set; }
+ public string InstallerVersion { get; set; }
+ public string Languages { get; set; }
+ public string Compressed { get; set; }
+ public string SummaryCodepage { get; set; }
+ public string Comments { get; set; }
+ public string Description { get; set; }
+
+ public override void load (Xml.Node *node) throws Wixl.Error {
+ base.load (node);
+
+ for (var child = node->children; child != null; child = child->next) {
+ switch (child->type) {
+ case Xml.ElementType.COMMENT_NODE:
+ case Xml.ElementType.TEXT_NODE:
+ continue;
+ case Xml.ElementType.ELEMENT_NODE:
+ switch (child->name) {
+ }
+ break;
+ }
+ debug ("unhandled node %s", child->name);
+ }
+ }
+
+ public override void accept (WixElementVisitor visitor) throws GLib.Error {
+ visitor.visit_package (this);
+ base.accept (visitor);
+ }
+ }
+
+ public class WixIcon: WixElement {
+ static construct {
+ name = "Icon";
+ }
+
+ public string SourceFile { get; set; }
+
+ public override void accept (WixElementVisitor visitor) throws GLib.Error {
+ visitor.visit_icon (this);
+ }
+ }
+
+ public class WixProduct: WixElement {
+ static construct {
+ name = "Product";
+ }
+
+ public string Name { get; set; }
+ public string UpgradeCode { get; set; }
+ public string Language { get; set; }
+ public string Codepage { get; set; }
+ public string Version { get; set; }
+ public string Manufacturer { get; set; }
+
+ public WixProduct () {
+ }
+
+ public override void load (Xml.Node *node) throws Wixl.Error {
+ base.load (node);
+
+ for (var child = node->children; child != null; child = child->next) {
+ switch (child->type) {
+ case Xml.ElementType.COMMENT_NODE:
+ case Xml.ElementType.TEXT_NODE:
+ continue;
+ case Xml.ElementType.ELEMENT_NODE:
+ switch (child->name) {
+ case "Package":
+ var package = new WixPackage ();
+ package.load (child);
+ add_child (package);
+ continue;
+ case "Icon":
+ var icon = new WixIcon ();
+ icon.load (child);
+ add_child (icon);
+ continue;
+ case "Property":
+ var prop = new WixProperty ();
+ prop.load (child);
+ add_child (prop);
+ continue;
+ }
+ break;
+ }
+ debug ("unhandled node %s", child->name);
+ }
+ }
+
+ public override void accept (WixElementVisitor visitor) throws GLib.Error {
+ visitor.visit_product (this);
+ base.accept (visitor);
+ }
+ }
+
+ class WixRoot: WixElement {
+ static construct {
+ name = "Wix";
+ }
+
+ public string xmlns { get; set; }
+
+ public WixRoot () {
+ }
+
+ public void load_xml (Xml.Doc *doc) throws Wixl.Error {
+ var root = doc->children;
+ load (root);
+
+ if (root->ns != null)
+ xmlns = root->ns->href;
+
+ for (var child = root->children; child != null; child = child->next) {
+ switch (child->type) {
+ case Xml.ElementType.COMMENT_NODE:
+ case Xml.ElementType.TEXT_NODE:
+ continue;
+ case Xml.ElementType.ELEMENT_NODE:
+ switch (child->name) {
+ case "Product":
+ var product = new WixProduct ();
+ product.load (child);
+ add_child (product);
+ continue;
+ }
+ break;
+ }
+
+ debug ("unhandled node %s", child->name);
+ }
+ }
+ }
+
+} // Wixl \ No newline at end of file
diff --git a/src/wixl.vala b/src/wixl.vala
index 891961a..c2084fd 100644
--- a/src/wixl.vala
+++ b/src/wixl.vala
@@ -1,665 +1,5 @@
namespace Wixl {
- abstract class MsiTable: Object {
- public string name;
- public List<Libmsi.Record> records;
-
- public abstract void create (Libmsi.Database db) throws GLib.Error;
- }
-
- class MsiTableIcon: MsiTable {
- construct {
- name = "Icon";
- }
-
- public void add (string id, string filename) throws GLib.Error {
- var rec = new Libmsi.Record (2);
-
- if (!rec.set_string (1, id) ||
- !rec.load_stream (2, filename))
- throw new Wixl.Error.FAILED ("failed to add record");
-
- records.append (rec);
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `Icon` (`Name` CHAR(72) NOT NULL, `Data` OBJECT NOT NULL PRIMARY KEY `Name`)");
- query.execute (null);
- query = new Libmsi.Query (db, "INSERT INTO `Icon` (`Name`, `Data`) VALUES (?, ?)");
- foreach (var r in records)
- query.execute (r);
- }
- }
-
- class MsiTableAdminExecuteSequence: MsiTable {
- construct {
- name = "AdminExecuteSequence";
- try {
- add ("CostInitialize", 800);
- add ("FileCost", 900);
- add ("CostFinalize", 1000);
- add ("InstallValidate", 1400);
- add ("InstallInitialize", 1500);
- add ("InstallAdminPackage", 3900);
- add ("InstallFiles", 4000);
- add ("InstallFinalize", 6600);
- } catch (GLib.Error e) {
- }
- }
-
- public void add (string action, int sequence) throws GLib.Error {
- var rec = new Libmsi.Record (2);
-
- if (!rec.set_string (1, action) ||
- !rec.set_int (2, sequence))
- throw new Wixl.Error.FAILED ("failed to add record");
-
- records.append (rec);
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `AdminExecuteSequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
- query.execute (null);
-
- query = new Libmsi.Query (db, "INSERT INTO `AdminExecuteSequence` (`Action`, `Sequence`) VALUES (?, ?)");
- foreach (var r in records)
- query.execute (r);
- }
- }
-
- class MsiTableAdminUISequence: MsiTable {
- construct {
- name = "AdminUISequence";
-
- try {
- add ("CostInitialize", 800);
- add ("FileCost", 900);
- add ("CostFinalize", 1000);
- add ("ExecuteAction", 1300);
- } catch (GLib.Error e) {
- }
- }
-
- public void add (string action, int sequence) throws GLib.Error {
- var rec = new Libmsi.Record (2);
-
- if (!rec.set_string (1, action) ||
- !rec.set_int (2, sequence))
- throw new Wixl.Error.FAILED ("failed to add record");
-
- records.append (rec);
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `AdminUISequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
- query.execute (null);
-
- query = new Libmsi.Query (db, "INSERT INTO `AdminUISequence` (`Action`, `Sequence`) VALUES (?, ?)");
- foreach (var r in records)
- query.execute (r);
- }
- }
-
- class MsiTableAdvtExecuteSequence: MsiTable {
- construct {
- name = "AdvtExecuteSequence";
-
- try {
- add ("CostInitialize", 800);
- add ("CostFinalize", 1000);
- add ("InstallValidate", 1400);
- add ("InstallInitialize", 1500);
- add ("InstallFinalize", 6600);
- add ("PublishFeatures", 6300);
- add ("PublishProduct", 6400);
- } catch (GLib.Error e) {
- }
- }
-
- public void add (string action, int sequence) throws GLib.Error {
- var rec = new Libmsi.Record (2);
-
- if (!rec.set_string (1, action) ||
- !rec.set_int (2, sequence))
- throw new Wixl.Error.FAILED ("failed to add record");
-
- records.append (rec);
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `AdvtExecuteSequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
- query.execute (null);
-
- query = new Libmsi.Query (db, "INSERT INTO `AdvtExecuteSequence` (`Action`, `Sequence`) VALUES (?, ?)");
- foreach (var r in records)
- query.execute (r);
- }
- }
-
- class MsiTableError: MsiTable {
- construct {
- name = "Error";
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `Error` (`Error` INT NOT NULL, `Message` CHAR(0) LOCALIZABLE PRIMARY KEY `Error`)");
- query.execute (null);
- }
- }
-
- class MsiTableFile: MsiTable {
- construct {
- name = "File";
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `File` (`File` CHAR(72) NOT NULL, `Component_` CHAR(72) NOT NULL, `FileName` CHAR(255) NOT NULL LOCALIZABLE, `FileSize` LONG NOT NULL, `Version` CHAR(72), `Language` CHAR(20), `Attributes` INT, `Sequence` LONG NOT NULL PRIMARY KEY `File`)");
- query.execute (null);
- }
- }
-
- class MsiTableInstallExecuteSequence: MsiTable {
- construct {
- name = "InstallExecuteSequence";
-
- try {
- add ("CostInitialize", 800);
- add ("FileCost", 900);
- add ("CostFinalize", 1000);
- add ("InstallValidate", 1400);
- add ("InstallInitialize", 1500);
- add ("InstallFinalize", 6600);
- add ("PublishFeatures", 6300);
- add ("PublishProduct", 6400);
- add ("ValidateProductID", 700);
- add ("ProcessComponents", 1600);
- add ("UnpublishFeatures", 1800);
- add ("RegisterUser", 6000);
- add ("RegisterProduct", 6100);
- } catch (GLib.Error e) {
- }
- }
-
- public void add (string action, int sequence) throws GLib.Error {
- var rec = new Libmsi.Record (2);
-
- if (!rec.set_string (1, action) ||
- !rec.set_int (2, sequence))
- throw new Wixl.Error.FAILED ("failed to add record");
-
- records.append (rec);
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `InstallExecuteSequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
- query.execute (null);
-
- query = new Libmsi.Query (db, "INSERT INTO `InstallExecuteSequence` (`Action`, `Sequence`) VALUES (?, ?)");
- foreach (var r in records)
- query.execute (r);
- }
- }
-
- class MsiTableInstallUISequence: MsiTable {
- construct {
- name = "InstallUISequence";
-
- try {
- add ("CostInitialize", 800);
- add ("FileCost", 900);
- add ("CostFinalize", 1000);
- add ("ExecuteAction", 1300);
- add ("ValidateProductID", 700);
- } catch (GLib.Error e) {
- }
- }
-
- public void add (string action, int sequence) throws GLib.Error {
- var rec = new Libmsi.Record (2);
-
- if (!rec.set_string (1, action) ||
- !rec.set_int (2, sequence))
- throw new Wixl.Error.FAILED ("failed to add record");
-
- records.append (rec);
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `InstallUISequence` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)");
- query.execute (null);
-
- query = new Libmsi.Query (db, "INSERT INTO `InstallUISequence` (`Action`, `Sequence`) VALUES (?, ?)");
- foreach (var r in records)
- query.execute (r);
-
- }
- }
-
- class MsiTableMedia: MsiTable {
- construct {
- name = "Media";
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `Media` (`DiskId` INT NOT NULL, `LastSequence` LONG NOT NULL, `DiskPrompt` CHAR(64) LOCALIZABLE, `Cabinet` CHAR(255), `VolumeLabel` CHAR(32), `Source` CHAR(72) PRIMARY KEY `DiskId`)");
- query.execute (null);
- }
- }
-
- class MsiTableProperty: MsiTable {
- construct {
- name = "Property";
- }
-
- public void add (string prop, string value) throws GLib.Error {
- var rec = new Libmsi.Record (2);
-
- if (!rec.set_string (1, prop) ||
- !rec.set_string (2, value))
- throw new Wixl.Error.FAILED ("failed to add record");
-
- records.append (rec);
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- var query = new Libmsi.Query (db, "CREATE TABLE `Property` (`Property` CHAR(72) NOT NULL, `Value` CHAR(0) NOT NULL LOCALIZABLE PRIMARY KEY `Property`)");
- query.execute (null);
-
- query = new Libmsi.Query (db, "INSERT INTO `Property` (`Property`, `Value`) VALUES (?, ?)");
- foreach (var r in records)
- query.execute (r);
- }
- }
-
- class MsiTable_Validation: MsiTable {
- construct {
- name = "_Validation";
- }
-
- public override void create (Libmsi.Database db) throws GLib.Error {
- }
- }
-
- class MsiSummaryInfo: Object {
- public Libmsi.SummaryInfo properties;
-
- construct {
- try {
- properties = new Libmsi.SummaryInfo (null, uint.MAX);
- } catch (GLib.Error error) {
- critical (error.message);
- }
- }
-
- public MsiSummaryInfo () {
- }
-
- public new void set_property (Libmsi.Property prop, Value value) throws GLib.Error {
- if (value.type () == typeof (string))
- properties.set_string (prop, (string) value);
- else if (value.type () == typeof (int))
- properties.set_int (prop, (int) value);
- else if (value.type () == typeof (uint64))
- properties.set_filetime (prop, (uint64) value);
- else
- critical ("Unhandled property type");
- }
-
- public void save (Libmsi.Database db) throws GLib.Error {
- properties.save (db);
- }
-
- public void set_codepage (int value) throws GLib.Error {
- set_property (Libmsi.Property.CODEPAGE, value);
- }
-
- public void set_author (string value) throws GLib.Error {
- set_property (Libmsi.Property.AUTHOR, value);
- }
-
- public void set_keywords (string value) throws GLib.Error {
- set_property (Libmsi.Property.KEYWORDS, value);
- }
-
- public void set_subject (string value) throws GLib.Error {
- set_property (Libmsi.Property.SUBJECT, value);
- }
-
- public void set_comments (string value) throws GLib.Error {
- set_property (Libmsi.Property.COMMENTS, value);
- }
-
- }
-
- class MsiDatabase: Object {
- public MsiSummaryInfo info;
- public MsiTableProperty table_property;
- public MsiTableIcon table_icon;
-
- HashTable<string, MsiTable> tables;
-
- construct {
- info = new MsiSummaryInfo ();
- try {
- info.set_property (Libmsi.Property.TITLE, "Installation Database");
- info.set_property (Libmsi.Property.TEMPLATE, "Intel;1033");
- info.set_property (Libmsi.Property.UUID, uuid_generate ());
- info.set_property (Libmsi.Property.CREATED_TM,
- time_to_filetime (now ()));
- info.set_property (Libmsi.Property.LASTSAVED_TM,
- time_to_filetime (now ()));
- info.set_property (Libmsi.Property.VERSION, 100);
- info.set_property (Libmsi.Property.SOURCE, 2);
- info.set_property (Libmsi.Property.APPNAME, Config.PACKAGE_STRING);
- info.set_property (Libmsi.Property.SECURITY, 2);
- } catch (GLib.Error error) {
- critical (error.message);
- }
-
- tables = new HashTable<string, MsiTable> (str_hash, str_equal);
- table_property = new MsiTableProperty ();
- table_icon = new MsiTableIcon ();
-
- foreach (var t in new MsiTable[] {
- new MsiTableAdminExecuteSequence (),
- new MsiTableAdminUISequence (),
- new MsiTableAdvtExecuteSequence (),
- new MsiTableError (),
- new MsiTableFile (),
- new MsiTableInstallExecuteSequence (),
- new MsiTableInstallUISequence (),
- new MsiTableMedia (),
- table_property,
- table_icon,
- new MsiTable_Validation ()
- }) {
- tables.insert (t.name, t);
- }
- }
-
- public MsiDatabase () {
- // empty ctor
- }
-
- public void build (string filename) throws GLib.Error {
- string name;
- MsiTable table;
-
- var db = new Libmsi.Database (filename, (string)2);
- info.save (db);
-
- var it = HashTableIter <string, MsiTable> (tables);
- while (it.next (out name, out table))
- table.create (db);
-
- db.commit ();
- }
- }
-
-
-
- public abstract class WixElementVisitor: Object {
- public abstract void visit_product (WixProduct product) throws GLib.Error;
- public abstract void visit_icon (WixIcon icon) throws GLib.Error;
- public abstract void visit_package (WixPackage package) throws GLib.Error;
- public abstract void visit_property (WixProperty prop) throws GLib.Error;
- }
-
- public abstract class WixElement: Object {
- public static string name;
- public string Id { get; set; }
- public List<WixElement> children;
-
- static construct {
- Value.register_transform_func (typeof (WixElement), typeof (string), (ValueTransform)WixElement.value_to_string);
- }
-
- public void add_child (WixElement e) {
- children.append (e);
- }
-
- public virtual void load (Xml.Node *node) throws Wixl.Error {
- if (node->name != name)
- throw new Error.FAILED ("%s: invalid node %s".printf (name, node->name));
-
- for (var prop = node->properties; prop != null; prop = prop->next) {
- if (prop->type == Xml.ElementType.ATTRIBUTE_NODE)
- set_property (prop->name, get_attribute_content (prop));
- }
- }
-
- public string to_string () {
- var type = get_type ();
- var klass = (ObjectClass)type.class_ref ();
- var str = type.name () + " {";
-
- var i = 0;
- foreach (var p in klass.list_properties ()) {
- var value = Value (p.value_type);
- get_property (p.name, ref value);
- var valstr = value.holds (typeof (string)) ?
- (string)value : value.strdup_contents ();
- str += (i == 0 ? "" : ", ") + p.name + ": " + valstr;
- i += 1;
- }
-
- return str + "}";
- }
-
- public static void value_to_string (Value src, out Value dest) {
- WixElement e = value_get_element (src);
-
- dest = e.to_string ();
- }
-
- public static WixElement? value_get_element (Value value) {
- if (! value.holds (typeof (WixElement)))
- return null;
-
- return (WixElement)value.get_object ();
- }
-
- public virtual void accept (WixElementVisitor visitor) throws GLib.Error {
- foreach (var child in children)
- child.accept (visitor);
- }
- }
-
- public class WixProperty: WixElement {
- static construct {
- name = "Property";
- }
-
- public string Value { get; set; }
-
- public override void accept (WixElementVisitor visitor) throws GLib.Error {
- visitor.visit_property (this);
- }
- }
-
- public class WixPackage: WixElement {
- static construct {
- name = "Package";
- }
-
- public string Keywords { get; set; }
- public string InstallerDescription { get; set; }
- public string InstallerComments { get; set; }
- public string Manufacturer { get; set; }
- public string InstallerVersion { get; set; }
- public string Languages { get; set; }
- public string Compressed { get; set; }
- public string SummaryCodepage { get; set; }
- public string Comments { get; set; }
- public string Description { get; set; }
-
- public override void load (Xml.Node *node) throws Wixl.Error {
- base.load (node);
-
- for (var child = node->children; child != null; child = child->next) {
- switch (child->type) {
- case Xml.ElementType.COMMENT_NODE:
- case Xml.ElementType.TEXT_NODE:
- continue;
- case Xml.ElementType.ELEMENT_NODE:
- switch (child->name) {
- }
- break;
- }
- debug ("unhandled node %s", child->name);
- }
- }
-
- public override void accept (WixElementVisitor visitor) throws GLib.Error {
- visitor.visit_package (this);
- base.accept (visitor);
- }
- }
-
- public class WixIcon: WixElement {
- static construct {
- name = "Icon";
- }
-
- public string SourceFile { get; set; }
-
- public override void accept (WixElementVisitor visitor) throws GLib.Error {
- visitor.visit_icon (this);
- }
- }
-
- public class WixProduct: WixElement {
- static construct {
- name = "Product";
- }
-
- public string Name { get; set; }
- public string UpgradeCode { get; set; }
- public string Language { get; set; }
- public string Codepage { get; set; }
- public string Version { get; set; }
- public string Manufacturer { get; set; }
-
- public WixProduct () {
- }
-
- public override void load (Xml.Node *node) throws Wixl.Error {
- base.load (node);
-
- for (var child = node->children; child != null; child = child->next) {
- switch (child->type) {
- case Xml.ElementType.COMMENT_NODE:
- case Xml.ElementType.TEXT_NODE:
- continue;
- case Xml.ElementType.ELEMENT_NODE:
- switch (child->name) {
- case "Package":
- var package = new WixPackage ();
- package.load (child);
- add_child (package);
- continue;
- case "Icon":
- var icon = new WixIcon ();
- icon.load (child);
- add_child (icon);
- continue;
- case "Property":
- var prop = new WixProperty ();
- prop.load (child);
- add_child (prop);
- continue;
- }
- break;
- }
- debug ("unhandled node %s", child->name);
- }
- }
-
- public override void accept (WixElementVisitor visitor) throws GLib.Error {
- visitor.visit_product (this);
- base.accept (visitor);
- }
- }
-
- class WixRoot: WixElement {
- static construct {
- name = "Wix";
- }
-
- public string xmlns { get; set; }
-
- public WixRoot () {
- }
-
- public void load_xml (Xml.Doc *doc) throws Wixl.Error {
- var root = doc->children;
- load (root);
-
- if (root->ns != null)
- xmlns = root->ns->href;
-
- for (var child = root->children; child != null; child = child->next) {
- switch (child->type) {
- case Xml.ElementType.COMMENT_NODE:
- case Xml.ElementType.TEXT_NODE:
- continue;
- case Xml.ElementType.ELEMENT_NODE:
- switch (child->name) {
- case "Product":
- var product = new WixProduct ();
- product.load (child);
- add_child (product);
- continue;
- }
- break;
- }
-
- debug ("unhandled node %s", child->name);
- }
- }
- }
-
- class WixBuilder: WixElementVisitor {
- WixRoot root;
- MsiDatabase db;
-
- public WixBuilder (WixRoot root) {
- this.root = root;
- }
-
- public MsiDatabase build () throws GLib.Error {
- db = new MsiDatabase ();
- root.accept (this);
- return db;
- }
-
- public override void visit_product (WixProduct product) throws GLib.Error {
- db.info.set_codepage (int.parse (product.Codepage));
- db.info.set_author (product.Manufacturer);
-
- db.table_property.add ("Manufacturer", product.Manufacturer);
- db.table_property.add ("ProductLanguage", product.Codepage);
- db.table_property.add ("ProductCode", add_braces (product.Id));
- db.table_property.add ("ProductName", product.Name);
- db.table_property.add ("ProductVersion", product.Version);
- db.table_property.add ("UpgradeCode", add_braces (product.UpgradeCode));
- }
-
- public override void visit_package (WixPackage package) throws GLib.Error {
- db.info.set_keywords (package.Keywords);
- db.info.set_subject (package.Description);
- db.info.set_comments (package.Comments);
- }
-
- public override void visit_icon (WixIcon icon) throws GLib.Error {
- db.table_icon.add (icon.Id, icon.SourceFile);
- }
-
- public override void visit_property (WixProperty prop) throws GLib.Error {
- db.table_property.add (prop.Id, prop.Value);
- }
- }
-
int main (string[] args) {
Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");