summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2013-01-09 16:29:37 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2013-01-09 18:04:19 +0100
commit549146755c4a510dd3fd8db87724c3b573927d89 (patch)
tree90d6a74f84fcc0083a2f48978687fb5a1f296fcf
parent06c962631abee5d0fc59cdabf186f9cd003a461b (diff)
parentb57de2196e111605812cc3aff4d6dcb53ec8965d (diff)
downloadmsitools-549146755c4a510dd3fd8db87724c3b573927d89.tar.gz
msitools-549146755c4a510dd3fd8db87724c3b573927d89.tar.xz
msitools-549146755c4a510dd3fd8db87724c3b573927d89.zip
Merge remote-tracking branch 'wixl/master'
-rw-r--r--AUTHORS3
-rw-r--r--LICENSE19
-rw-r--r--Makefile.am6
-rw-r--r--README22
-rw-r--r--atlocal.in4
-rwxr-xr-xautogen.sh10
-rw-r--r--configure.ac37
-rw-r--r--po/LINGUAS0
-rw-r--r--po/POTFILES.in3
-rw-r--r--po/POTFILES.skip3
-rw-r--r--tests/data/wixl/FoobarAppl10.exe1
-rw-r--r--tests/data/wixl/Helper.dll1
-rw-r--r--tests/data/wixl/Manual.pdf1
-rwxr-xr-xtests/data/wixl/Manual.wxs14
-rw-r--r--tests/data/wixl/SampleFirst.wxs61
-rwxr-xr-xtests/data/wixl/SampleFragment.wxs61
-rw-r--r--tests/data/wixl/test-arp.wxs45
-rw-r--r--tests/testsuite.at2
-rw-r--r--tests/wixl.at95
-rw-r--r--vapi/libxml-2.0.vapi1863
-rw-r--r--wixl/Makefile.am46
-rw-r--r--wixl/builder.vala590
-rw-r--r--wixl/config.vapi12
-rw-r--r--wixl/msi.vala642
-rw-r--r--wixl/preprocessor.vala131
-rw-r--r--wixl/util.vala139
-rw-r--r--wixl/wix.vala598
-rw-r--r--wixl/wixl.vala92
28 files changed, 4492 insertions, 9 deletions
diff --git a/AUTHORS b/AUTHORS
index 4bc5365..1aa901a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,5 @@
-msitools are maintained by Paolo Bonzini. <pbonzini@redhat.com>
+msitools are maintained by Paolo Bonzini <pbonzini@redhat.com> and
+Marc-Andre Lureau <marcandre.lureau@gmail.com>.
libmsi is mostly based on Wine's implementation of Windows Installer,
with the following copyright:
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..417fe9c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Format: http://www.debian.org/doc/copyright-format/1.0
+Upstream-Name: Wixl
+
+Files: *
+Copyright: Copyright 2013 Red Hat, Inc.
+License: LGPL-2+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+ .
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/Makefile.am b/Makefile.am
index a76d7df..623c479 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,10 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = libmsi tests .
+if WIXL
+SUBDIRS += po wixl
+endif
+
dist_include_HEADERS = \
include/libmsi.h \
include/libmsi-database.h \
@@ -33,7 +37,7 @@ DISTCLEANFILES = atconfig atlocal
CLEANFILES = testsuite.log
check-local: $(srcdir)/tests/testsuite atconfig atlocal
- $(SHELL) $(srcdir)/tests/testsuite AUTOTEST_PATH=. $(TESTSUITEFLAGS)
+ $(SHELL) $(srcdir)/tests/testsuite AUTOTEST_PATH=.:wixl $(TESTSUITEFLAGS)
installcheck-local: $(srcdir)/tests/testsuite atconfig atlocal
$(SHELL) $(srcdir)/tests/testsuite AUTOTEST_PATH=$(bindir) $(TESTSUITEFLAGS)
diff --git a/README b/README
index 4ef146b..8e1320b 100644
--- a/README
+++ b/README
@@ -6,11 +6,17 @@ implementation of the Windows Installer.
msitools plans to be a solution for packaging and deployment of
cross-compiled Windows applications.
-While in a very early stage, it is already usable. Two tools are
-provided, msiinfo and msibuild, respectively to inspect and create
-MSI files. They are very low-level, but it should already be possible
-to use these tools to take an existing .MSI file, and update it with
-new build products (for example after a cross-compilation).
+Provided tools include:
+
+- msiinfo, to inspect MSI files
+
+- msibuild, a low-level tool to create MSI files
+
+- wixl, a WiX-like tool, that builds Windows Installer (MSI) packages
+ from an XML document, and tries to share the same syntax as the WiX
+ toolset, http://wixtoolset.org/
+
+While in a very early stage, it is already usable.
msitools uses libgsf in order to read OLE Structured Storage files
(which are the underlying format of .MSI files). As of December 7th,
@@ -18,4 +24,8 @@ msitools uses libgsf in order to read OLE Structured Storage files
found in any release. Fedora packages for a fixed libgsf can be found
at http://bonzini.fedorapeople.org/.
-For more information, contact me at pbonzini@redhat.com.
+Wixl lacks many features compared to WiX. As always, contributions
+are welcome!
+
+For more information, please contact us by email. Forking and sending
+github pull requests is also welcome.
diff --git a/atlocal.in b/atlocal.in
index bc84b6d..43b055c 100644
--- a/atlocal.in
+++ b/atlocal.in
@@ -22,3 +22,7 @@ _msiinfo() {
_msibuild() {
WINEDEBUG=-all msibuild$EXEEXT "$@"
}
+
+_wixl() {
+ wixl$EXEEXT "$@"
+}
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..2463bcb
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+test -n "$srcdir" || srcdir=$(dirname "$0")
+test -n "$srcdir" || srcdir=.
+(
+ cd "$srcdir" &&
+ mkdir -p m4 &&
+ AUTOPOINT='intltoolize --automake --copy' autoreconf -fiv -Wall
+) || exit
+test -n "$NOCONFIGURE" || "$srcdir/configure" --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
index 1d5f81a..a28fc48 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,6 +15,8 @@ AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_PROG_YACC
+IT_PROG_INTLTOOL([0.35])
+
AM_PATH_GLIB_2_0([2.12.0])
PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 gio-2.0 >= 2.14])
PKG_CHECK_MODULES([GSF], [libgsf-1])
@@ -28,11 +30,32 @@ LT_INIT([win32-dll disable-fast-install])
GOBJECT_INTROSPECTION_CHECK([0.9.4])
AM_CONDITIONAL([GIR], [test "x$INTROSPECTION_MAKEFILE" != x])
-AM_PROG_VALAC([0.14])
+AM_PROG_VALAC([0.16])
AC_PATH_PROG(VAPIGEN, vapigen, no)
AC_SUBST(VAPIGEN)
AM_CONDITIONAL([VAPI], [test "x$VAPIGEN" != xno])
+PKG_CHECK_MODULES([WIXL], [gio-2.0 >= 2.26.0
+ libgcab-1.0
+ uuid >= 1.41.3
+ libxml-2.0 >= 2.9],
+ [wixl_ok=yes], [wixl_ok=no])
+
+AC_ARG_ENABLE([wixl],
+ [AS_HELP_STRING([--disable-wixl], [do not build wixl (default=yes)])],
+ [wixl=$enableval], [wixl=yes])
+
+AS_IF([test $wixl_ok = no && test $wixl != no],
+ [AC_MSG_ERROR([Wixl dependencies not found])])
+
+AM_CONDITIONAL([WIXL], [test "x$wixl" != xno])
+
+GETTEXT_PACKAGE=wixl
+AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [Gettext Package])
+AC_SUBST(GETTEXT_PACKAGE)
+AM_GNU_GETTEXT_VERSION([1.11])
+AM_GLIB_GNU_GETTEXT
+
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AM_MISSING_PROG([AUTOM4TE], [autom4te])
@@ -45,7 +68,19 @@ AC_CONFIG_FILES([tests/package.m4.tmp:tests/package.m4.in],
AC_CONFIG_FILES([
Makefile
libmsi-1.0.pc
+ po/Makefile.in
libmsi/Makefile
+ wixl/Makefile
tests/Makefile
])
AC_OUTPUT
+
+AC_MSG_NOTICE([
+ msitools $VERSION
+ ================
+
+ prefix: ${prefix}
+ c compiler: ${CC}
+ uuid: ${uuid}
+ wixl: ${wixl}
+])
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/po/LINGUAS
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..7b68332
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,3 @@
+[encoding: UTF-8]
+wixl/wixl.vala
+wixl/builder.vala
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
new file mode 100644
index 0000000..e828b78
--- /dev/null
+++ b/po/POTFILES.skip
@@ -0,0 +1,3 @@
+wixl/builder.c
+wixl/wixl.c
+libmsi/sql-parser.c
diff --git a/tests/data/wixl/FoobarAppl10.exe b/tests/data/wixl/FoobarAppl10.exe
new file mode 100644
index 0000000..c1b0730
--- /dev/null
+++ b/tests/data/wixl/FoobarAppl10.exe
@@ -0,0 +1 @@
+x \ No newline at end of file
diff --git a/tests/data/wixl/Helper.dll b/tests/data/wixl/Helper.dll
new file mode 100644
index 0000000..c1b0730
--- /dev/null
+++ b/tests/data/wixl/Helper.dll
@@ -0,0 +1 @@
+x \ No newline at end of file
diff --git a/tests/data/wixl/Manual.pdf b/tests/data/wixl/Manual.pdf
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/tests/data/wixl/Manual.pdf
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/tests/data/wixl/Manual.wxs b/tests/data/wixl/Manual.wxs
new file mode 100755
index 0000000..e767d58
--- /dev/null
+++ b/tests/data/wixl/Manual.wxs
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='windows-1252'?>
+<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
+ <Fragment Id='FragmentManual'>
+
+ <DirectoryRef Id='INSTALLDIR'>
+ <Component Id='Manual' Guid='ABCDDCBA-574D-4A9A-A266-5B5EC2C022A4'>
+ <File Id='Manual' Name='Manual.pdf' DiskId='1' Source='Manual.pdf' KeyPath='yes'>
+ <Shortcut Id="startmenuManual" Directory="ProgramMenuDir" Name="Instruction Manual" Advertise="yes" />
+ </File>
+ </Component>
+ </DirectoryRef>
+
+ </Fragment>
+</Wix>
diff --git a/tests/data/wixl/SampleFirst.wxs b/tests/data/wixl/SampleFirst.wxs
new file mode 100644
index 0000000..604eb0b
--- /dev/null
+++ b/tests/data/wixl/SampleFirst.wxs
@@ -0,0 +1,61 @@
+<?xml version='1.0' encoding='windows-1252'?>
+<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
+ <Product Name='Foobar 1.0' Id='ABCDDCBA-86C7-4D14-AEC0-86416A69ABDE' UpgradeCode='ABCDDCBA-7349-453F-94F6-BCB5110BA4FD'
+ Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>
+
+ <Package Id='*' Keywords='Installer' Description="Acme's Foobar 1.0 Installer"
+ Comments='Foobar is a registered trademark of Acme Ltd.' Manufacturer='Acme Ltd.'
+ InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
+
+ <Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
+ <Property Id='DiskPrompt' Value="Acme's Foobar 1.0 Installation [1]" />
+
+ <Directory Id='TARGETDIR' Name='SourceDir'>
+ <Directory Id='ProgramFilesFolder' Name='PFiles'>
+ <Directory Id='Acme' Name='Acme'>
+ <Directory Id='INSTALLDIR' Name='Foobar 1.0'>
+
+ <Component Id='MainExecutable' Guid='ABCDDCBA-83F1-4F22-985B-FDB3C8ABD471'>
+ <File Id='FoobarEXE' Name='FoobarAppl10.exe' DiskId='1' Source='FoobarAppl10.exe' KeyPath='yes'>
+ <Shortcut Id="startmenuFoobar10" Directory="ProgramMenuDir" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
+ <Shortcut Id="desktopFoobar10" Directory="DesktopFolder" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
+ </File>
+ </Component>
+
+ <Component Id='HelperLibrary' Guid='ABCDDCBA-6BE3-460D-A14F-75658D16550B'>
+ <File Id='HelperDLL' Name='Helper.dll' DiskId='1' Source='Helper.dll' KeyPath='yes' />
+ </Component>
+
+ <Component Id='Manual' Guid='ABCDDCBA-574D-4A9A-A266-5B5EC2C022A4'>
+ <File Id='Manual' Name='Manual.pdf' DiskId='1' Source='Manual.pdf' KeyPath='yes'>
+ <Shortcut Id="startmenuManual" Directory="ProgramMenuDir" Name="Instruction Manual" Advertise="yes" />
+ </File>
+ </Component>
+
+ </Directory>
+ </Directory>
+ </Directory>
+
+ <Directory Id="ProgramMenuFolder" Name="Programs">
+ <Directory Id="ProgramMenuDir" Name="Foobar 1.0">
+ <Component Id="ProgramMenuDir" Guid="ABCDDCBA-7E98-44CE-B049-C477CC0A2B00">
+ <RemoveFolder Id='ProgramMenuDir' On='uninstall' />
+ <RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes' />
+ </Component>
+ </Directory>
+ </Directory>
+
+ <Directory Id="DesktopFolder" Name="Desktop" />
+ </Directory>
+
+ <Feature Id='Complete' Level='1'>
+ <ComponentRef Id='MainExecutable' />
+ <ComponentRef Id='HelperLibrary' />
+ <ComponentRef Id='Manual' />
+ <ComponentRef Id='ProgramMenuDir' />
+ </Feature>
+
+ <Icon Id="Foobar10.exe" SourceFile="FoobarAppl10.exe" />
+
+ </Product>
+</Wix>
diff --git a/tests/data/wixl/SampleFragment.wxs b/tests/data/wixl/SampleFragment.wxs
new file mode 100755
index 0000000..42f1718
--- /dev/null
+++ b/tests/data/wixl/SampleFragment.wxs
@@ -0,0 +1,61 @@
+<?xml version='1.0' encoding='windows-1252'?>
+<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
+ <Product Name='Foobar 1.0' Id='ABCDDCBA-86C7-4D14-AEC0-86416A69ABDE' UpgradeCode='ABCDDCBA-7349-453F-94F6-BCB5110BA4FD'
+ Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>
+
+ <Package Id='*' Keywords='Installer' Description="Acme's Foobar 1.0 Installer"
+ Comments='Foobar is a registered trademark of Acme Ltd.' Manufacturer='Acme Ltd.'
+ InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
+
+ <Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
+ <Property Id='DiskPrompt' Value="Acme's Foobar 1.0 Installation [1]" />
+
+ <Directory Id='TARGETDIR' Name='SourceDir'>
+ <Directory Id='ProgramFilesFolder' Name='PFiles'>
+ <Directory Id='Acme' Name='Acme'>
+ <Directory Id='INSTALLDIR' Name='Foobar 1.0'>
+
+ <Component Id='MainExecutable' Guid='ABCDDCBA-83F1-4F22-985B-FDB3C8ABD471'>
+ <File Id='FoobarEXE' Name='FoobarAppl10.exe' DiskId='1' Source='FoobarAppl10.exe' KeyPath='yes'>
+ <Shortcut Id="startmenuFoobar10" Directory="ProgramMenuDir" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
+ <Shortcut Id="desktopFoobar10" Directory="DesktopFolder" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
+ </File>
+ </Component>
+
+ <Component Id='HelperLibrary' Guid='ABCDDCBA-6BE3-460D-A14F-75658D16550B'>
+ <File Id='HelperDLL' Name='Helper.dll' DiskId='1' Source='Helper.dll' KeyPath='yes' />
+ </Component>
+
+ </Directory>
+ </Directory>
+ </Directory>
+
+ <Directory Id="ProgramMenuFolder" Name="Programs">
+ <Directory Id="ProgramMenuDir" Name="Foobar 1.0">
+ <Component Id="ProgramMenuDir" Guid="ABCDDCBA-7E98-44CE-B049-C477CC0A2B00">
+ <RemoveFolder Id='ProgramMenuDir' On='uninstall' />
+ <RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes' />
+ </Component>
+ </Directory>
+ </Directory>
+
+ <Directory Id="DesktopFolder" Name="Desktop" />
+ </Directory>
+
+ <Feature Id='Complete' Title='Foobar 1.0' Description='The complete package.'
+ Display='expand' Level='1' ConfigurableDirectory='INSTALLDIR'>
+ <Feature Id='MainProgram' Title='Program' Description='The main executable.' Level='1'>
+ <ComponentRef Id='MainExecutable' />
+ <ComponentRef Id='HelperLibrary' />
+ <ComponentRef Id='ProgramMenuDir' />
+ </Feature>
+
+ <Feature Id='Documentation' Title='Description' Description='The instruction manual.' Level='1'>
+ <ComponentRef Id='Manual' />
+ </Feature>
+ </Feature>
+
+ <Icon Id="Foobar10.exe" SourceFile="FoobarAppl10.exe" />
+
+ </Product>
+</Wix>
diff --git a/tests/data/wixl/test-arp.wxs b/tests/data/wixl/test-arp.wxs
new file mode 100644
index 0000000..3e135ee
--- /dev/null
+++ b/tests/data/wixl/test-arp.wxs
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<?define Version = "0.2.0"?>
+<?define UpgradeCode = "ABCDDCBA-8392-0202-1993-199374829923"?>
+<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
+
+ <Product Id="*" Name="name" Manufacturer="manufacturer"
+ Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)"
+ Language="1033">
+
+ <Package InstallerVersion="200" Compressed="yes" Comments="comments"/>
+ <Media Id="1" Cabinet="cabinet.cab" EmbedCab="yes"/>
+
+ <Property Id="ARPHELPLINK" Value="http://www.foobar.baz"/>
+ <Property Id="ARPNOMODIFY" Value="1"/>
+ <Property Id="ARPNOREPAIR" Value="1"/>
+ <Property Id="ARPPRODUCTICON" Value="FoobarAppl10.exe"/>
+ <Property Id="ARPURLINFOABOUT" Value="http://www.foobar.baz/info"/>
+ <Upgrade Id="$(var.UpgradeCode)">
+ <UpgradeVersion Minimum="$(var.Version)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED"/>
+ <UpgradeVersion Minimum="0.0.0" Maximum="$(var.Version)" IncludeMinimum="yes" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED"/>
+ </Upgrade>
+ <Condition Message="A newer version is already installed.">NOT NEWERVERSIONDETECTED</Condition>
+
+ <Directory Id="TARGETDIR" Name="SourceDir">
+ <Directory Id="ProgramFilesFolder">
+ <Directory Id="INSTALLDIR" Name="Example">
+ <Component Id="MainExecutable" Guid="ABCDDCBA-2034-1019-3233-949940039491">
+ <File Id="FoobarAppl10.exe" Source="FoobarAppl10.exe"/>
+ </Component>
+ </Directory>
+ </Directory>
+ </Directory>
+
+ <Feature Id="Complete" Level="1">
+ <ComponentRef Id="MainExecutable"/>
+ </Feature>
+
+ <InstallExecuteSequence>
+ <RemoveExistingProducts After="InstallValidate"/>
+ </InstallExecuteSequence>
+
+ <Icon Id="FoobarAppl10.exe" SourceFile="FoobarAppl10.exe"/>
+
+ </Product>
+</Wix>
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 01ac62b..c48c5d1 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -231,3 +231,5 @@ Application: Windows Installer XML (3.7.1119.0)
Security: 2 (2)
])
AT_CLEANUP
+
+m4_include([wixl.at])
diff --git a/tests/wixl.at b/tests/wixl.at
new file mode 100644
index 0000000..0191012
--- /dev/null
+++ b/tests/wixl.at
@@ -0,0 +1,95 @@
+AT_BANNER([wixl])
+
+# AT_CHECK_... - add exeext automatically
+m4_define([AT_CHECK_WIXL], [
+AT_CHECK([_wixl ]$@)])
+
+# AT_WIXLDATA - copy data file from source tree
+m4_define([AT_WIXLDATA], [
+dir=`dirname $1`
+AS_MKDIR_P([$dir])
+AT_CHECK([cp $abs_srcdir/tests/data/wixl/$1 $1])])
+
+
+AT_SETUP([Invalid command line])
+AT_CHECK_WIXL([], [1], [ignore], [ignore])
+AT_CHECK_WIXL([out.msi foo.wxs], [1], [ignore], [ignore])
+AT_CHECK_WIXL([-o out.msi], [1], [ignore], [ignore])
+AT_CHECK_WIXL([-E], [1], [ignore], [ignore])
+AT_CHECK_WIXL([-D], [1], [ignore], [ignore])
+AT_CHECK_WIXL([-E -o out.msi], [1], [ignore], [ignore])
+AT_CHECK([test -f out.msi], [1])
+AT_CLEANUP
+
+AT_SETUP([WiX tutorial SampleFirst])
+AT_WIXLDATA([SampleFirst.wxs])
+AT_WIXLDATA([FoobarAppl10.exe])
+AT_WIXLDATA([Helper.dll])
+AT_WIXLDATA([Manual.pdf])
+AT_CHECK_WIXL([-o out.msi SampleFirst.wxs], [0], [ignore], [ignore])
+# FIXME: add tons of tests on out.msi
+AT_CHECK([test -f out.msi], [0])
+AT_CLEANUP
+
+AT_SETUP([WiX tutorial SampleFragment])
+AT_WIXLDATA([SampleFragment.wxs])
+AT_WIXLDATA([Manual.wxs])
+AT_WIXLDATA([FoobarAppl10.exe])
+AT_WIXLDATA([Helper.dll])
+AT_WIXLDATA([Manual.pdf])
+AT_CHECK_WIXL([-o out.msi SampleFragment.wxs Manual.wxs], [0], [ignore], [ignore])
+# FIXME: add tons of tests on out.msi
+AT_CHECK([test -f out.msi], [0])
+AT_CLEANUP
+
+AT_SETUP([Preprocessor variables])
+export MY_VAR="Hello!"
+AT_DATA([variables.wxs], [<?xml version="1.0"?>
+<?define Version = "0.2.0"?>
+<?define UpgradeCode = "ABCDDCBA-8392-0202-1993-199374829923"?>
+<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
+ <Property Id="Id0" Value="$(var.UpgradeCode)"/>
+ <Property Id="Id0.1" Value="$$(var.UpgradeCode)"/>
+ <Property Id="Id0.2" Value="$$$(var.UpgradeCode)"/>
+ <?define UpgradeCode = "ABCDDCBA-8392-0202-1993-199374829924"?>
+ <Property Id="Id2" Value="$(var.UpgradeCode)"/>
+ <Property Id="Id3" Value="$(var.Version)"/>
+ <?define A = "A"?><?define B = "B"?>
+ <Property Id="IdAB" Value="$(var.A)$(var.B)"/>
+ <Property Id="IdHello" Value="$(env.MY_VAR)"/>
+ <Property Id="IdSys" Value="($(sys.SOURCEFILEDIR))foo"/>
+</Wix>
+])
+AT_CHECK_WIXL([-E variables.wxs], [0], [<?xml version="1.0"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+ <Property Id="Id0" Value="ABCDDCBA-8392-0202-1993-199374829923"/>
+ <Property Id="Id0.1" Value="$ABCDDCBA-8392-0202-1993-199374829923"/>
+ <Property Id="Id0.2" Value="$$ABCDDCBA-8392-0202-1993-199374829923"/>
+ <Property Id="Id2" Value="ABCDDCBA-8392-0202-1993-199374829924"/>
+ <Property Id="Id3" Value="0.2.0"/>
+ <Property Id="IdAB" Value="AB"/>
+ <Property Id="IdHello" Value="Hello!"/>
+ <Property Id="IdSys" Value="(variables.wxs)foo"/>
+</Wix>
+], [ignore])
+AT_DATA([variables.wxs], [<?xml version="1.0"?>
+<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
+ <Property Id="Id$(var.Foo)" Value="$(var.Foo)"/>
+ <Property Id="Id$(var.Zig)" Value="$(var.Zig)"/>
+</Wix>
+])
+AT_CHECK_WIXL([-E variables.wxs -D Foo -D Zig=Zag], [0], [<?xml version="1.0"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+ <Property Id="Id1" Value="1"/>
+ <Property Id="IdZag" Value="Zag"/>
+</Wix>
+], [ignore])
+AT_CLEANUP
+
+AT_SETUP([ARP example])
+AT_WIXLDATA([test-arp.wxs])
+AT_WIXLDATA([FoobarAppl10.exe])
+AT_CHECK_WIXL([-o out.msi test-arp.wxs], [0], [ignore], [ignore])
+# FIXME: add tons of tests on out.msi
+AT_CHECK([test -f out.msi], [0])
+AT_CLEANUP
diff --git a/vapi/libxml-2.0.vapi b/vapi/libxml-2.0.vapi
new file mode 100644
index 0000000..b76cc54
--- /dev/null
+++ b/vapi/libxml-2.0.vapi
@@ -0,0 +1,1863 @@
+/* libxml2.vala
+ *
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini, Michael Lawrence
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j@bitron.ch>
+ * Raffaele Sandrini <rasa@gmx.ch>
+ * Michael Lawrence <lawremi@iastate.edu>
+ * Ondřej Jirman <megous@megous.com>
+ */
+
+[CCode (gir_namespace = "libxml2", gir_version = "2.0")]
+namespace Xml {
+ /* nanoftp - minimal FTP implementation */
+
+ [CCode (has_target = false, cname = "ftpDataCallback", cheader_filename = "libxml/nanoftp.h")]
+ public delegate void FtpDataCallback (void* userData, [CCode (array_length = false)] char[] data, int len);
+
+ [CCode (has_target = false, cname = "ftpListCallback", cheader_filename = "libxml/nanoftp.h")]
+ public delegate void FtpListCallback (void* userData, string filename, string attrib, string owner, string group, ulong size, int links, int year, string month, int day, int hour, int minute);
+
+ [Compact]
+ [CCode (cname = "void", free_function = "xmlNanoFTPFreeCtxt", cheader_filename = "libxml/nanoftp.h")]
+ public class NanoFTP {
+ [CCode (cname = "xmlNanoFTPCheckResponse")]
+ public int check_response ();
+
+ [CCode (cname = "xmlNanoFTPCleanup")]
+ public static void cleanup ();
+
+ [CCode (cname = "xmlNanoFTPClose")]
+ public int close ();
+
+ [CCode (cname = "xmlNanoFTPCloseConnection")]
+ public int close_connection ();
+
+ [CCode (cname = "xmlNanoFTPConnect")]
+ public int connect ();
+
+ [CCode (cname = "xmlNanoFTPConnectTo")]
+ public static NanoFTP* connect_to (string server, int port);
+
+ [CCode (cname = "xmlNanoFTPCwd")]
+ public int cwd (string directory);
+
+ [CCode (cname = "xmlNanoFTPDele")]
+ public int dele (string file);
+
+ [CCode (cname = "xmlNanoFTPGet")]
+ public int get (FtpDataCallback cb, void* user_data, string filename);
+
+ [CCode (cname = "xmlNanoFTPGetConnection")]
+ public int get_connection ();
+
+ [CCode (cname = "xmlNanoFTPGetResponse")]
+ public int get_response ();
+
+ [CCode (cname = "xmlNanoFTPGetSocket")]
+ public int get_socket (string filename);
+
+ [CCode (cname = "xmlNanoFTPInit")]
+ public static void init ();
+
+ [CCode (cname = "xmlNanoFTPList")]
+ public int list (FtpListCallback cb, void* user_data, string filename);
+
+ [CCode (cname = "xmlNanoFTPNewCtxt")]
+ public NanoFTP (string url);
+
+ [CCode (cname = "xmlNanoFTPOpen")]
+ public static NanoFTP* open (string url);
+
+ [CCode (cname = "xmlNanoFTPProxy")]
+ public static void proxy (string host, int port, string user, string passwd, int type);
+
+ [CCode (cname = "xmlNanoFTPQuit")]
+ public int quit ();
+
+ [CCode (cname = "xmlNanoFTPRead")]
+ public int read (void* dest, int len);
+
+ [CCode (cname = "xmlNanoFTPScanProxy")]
+ public static void scan_proxy (string url);
+
+ [CCode (cname = "xmlNanoFTPUpdateURL")]
+ public int update_url (string url);
+ }
+
+
+ /* nanohttp - minimal HTTP implementation */
+
+ [Compact]
+ [CCode (cname = "void", cheader_filename = "libxml/nanohttp.h")]
+ public class NanoHTTP {
+ [CCode (cname = "xmlNanoHTTPAuthHeader")]
+ public unowned string auth_header ();
+
+ [CCode (cname = "xmlNanoHTTPCleanup")]
+ public static void cleanup ();
+
+ [CCode (cname = "xmlNanoHTTPClose")]
+ public int close ();
+
+ [CCode (cname = "xmlNanoHTTPContentLength")]
+ public int content_length ();
+
+ [CCode (cname = "xmlNanoHTTPEncoding")]
+ public unowned string http_encoding ();
+
+ [CCode (cname = "xmlNanoHTTPFetch")]
+ public static int fetch (string url, string filename, out string content_type);
+
+ [CCode (cname = "xmlNanoHTTPInit")]
+ public static void init ();
+
+ [CCode (cname = "xmlNanoHTTPMethod")]
+ public static NanoHTTP* method (string url, string method, string input, out string content_type, string headers, int ilen);
+
+ [CCode (cname = "xmlNanoHTTPMethodRedir")]
+ public static NanoHTTP* method_redir (string url, string method, string input, out string content_type, out string redir, string headers, int ilen);
+
+ [CCode (cname = "xmlNanoHTTPMimeType")]
+ public string mime_type ();
+
+ [CCode (cname = "xmlNanoHTTPOpen")]
+ public static NanoHTTP* open (string url, out string content_type);
+
+ [CCode (cname = "xmlNanoHTTPOpenRedir")]
+ public static NanoHTTP* open_redir (string url, out string content_type, out string redir);
+
+ [CCode (cname = "xmlNanoHTTPRead")]
+ public int read (void* dest, int len);
+
+ [CCode (cname = "xmlNanoHTTPRedir")]
+ public unowned string redir ();
+
+ [CCode (cname = "xmlNanoHTTPReturnCode")]
+ public int return_code ();
+
+ [CCode (cname = "xmlNanoHTTPSave")]
+ public int save (string filename);
+
+ [CCode (cname = "xmlNanoHTTPScanProxy")]
+ public static void scan_proxy (string URL);
+ }
+
+
+ /* parser - the core parser module */
+
+ [CCode (cheader_filename = "libxml/parser.h")]
+ namespace Parser {
+ [CCode (cname = "xmlCleanupParser")]
+ public static void cleanup ();
+
+ [CCode (cname = "xmlInitParser")]
+ public static void init ();
+
+ [CCode (cname = "xmlParseDoc")]
+ public static Doc* parse_doc (string cur);
+
+ [CCode (cname = "xmlParseFile")]
+ public static Doc* parse_file (string filename);
+
+ [CCode (cname = "xmlParseMemory")]
+ public static Doc* parse_memory (string buffer, int size);
+
+ [CCode (cname = "xmlReadDoc")]
+ public static Doc* read_doc (string cur, string? url = null, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReadFd")]
+ public static Doc* read_fd (int fd, string? base_url = null, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReadFile")]
+ public static Doc* read_file (string filename, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReadMemory")]
+ public static Doc* read_memory (string text, int len, string? url = null, string? encoding = null, int options = 0);
+ }
+
+ [CCode (cname = "xmlParserOption", cprefix = "XML_PARSE_", cheader_filename = "libxml/parser.h", has_type_id = false)]
+ public enum ParserOption {
+ RECOVER,
+ NOENT,
+ DTDLOAD,
+ DTDATTR,
+ DTDVALID,
+ NOERROR,
+ NOWARNING,
+ PEDANTIC,
+ NOBLANKS,
+ SAX1,
+ XINCLUDE,
+ NONET,
+ NODICT,
+ NSCLEAN,
+ NOCDATA,
+ NOXINCNODE,
+ COMPACT,
+ }
+
+ [CCode (cname = "xmlCharEncoding", cprefix = "XML_CHAR_ENCODING_", cheader_filename = "libxml/encoding.h", has_type_id = false)]
+ public enum CharEncoding {
+ ERROR,
+ NONE,
+ UTF8,
+ UTF16LE,
+ UTF16BE,
+ UCS4LE,
+ UCS4BE,
+ EBCDIC,
+ UCS4_2143,
+ UCS4_3412,
+ UCS2,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_1")]
+ ISO_8859_1,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_2")]
+ ISO_8859_2,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_3")]
+ ISO_8859_3,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_4")]
+ ISO_8859_4,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_5")]
+ ISO_8859_5,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_6")]
+ ISO_8859_6,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_7")]
+ ISO_8859_7,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_8")]
+ ISO_8859_8,
+ [CCode (cname = "XML_CHAR_ENCODING_8859_9")]
+ ISO_8859_9,
+ ISO_2022_JP,
+ SHIFT_JIS,
+ EUC_JP,
+ ASCII,
+ }
+
+ /* tree - interfaces for tree manipulation */
+
+ [CCode (cheader_filename = "libxml/tree.h")]
+ namespace Tree {
+ [CCode (cname = "xmlGetCompressMode")]
+ public static int get_compress_mode ();
+
+ [CCode (cname = "xmlIsXHTML")]
+ public static int is_xhtml (string system_id, string public_id);
+
+ [CCode (cname = "xmlSetCompressMode")]
+ public static void set_compress_mode (int mode);
+ }
+
+ [Compact]
+ [CCode (cname = "xmlAttr", free_function = "xmlFreeProp", cheader_filename = "libxml/tree.h")]
+ public class Attr {
+ public ElementType type;
+ public weak string name;
+ public Node* children;
+ public Node* last;
+ public Node* parent;
+ public Attr* next;
+ public Attr* prev;
+ public Doc* doc;
+ public Ns* ns;
+ public AttributeType atype;
+
+ [CCode (cname = "xmlRemoveProp")]
+ public int remove();
+ }
+
+ [Compact]
+ [CCode (cname = "xmlAttribute", cheader_filename = "libxml/tree.h")]
+ public class Attribute {
+ public ElementType type;
+ public weak string name;
+ public Node* children;
+ public Node* last;
+ public Dtd* parent;
+ public Node* next;
+ public Node* prev;
+ public Doc* doc;
+ public Attribute* nexth;
+ public AttributeType atype;
+ public AttributeDefault def;
+ public weak string default_value;
+ public weak string prefix;
+ public weak string elem;
+ }
+
+ [CCode (cname = "xmlAttributeDefault", cprefix = "XML_ATTRIBUTE_", cheader_filename = "libxml/tree.h", has_type_id = false)]
+ public enum AttributeDefault {
+ NONE,
+ REQUIRED,
+ IMPLIED,
+ FIXED
+ }
+
+ [CCode (cname = "xmlAttributeType", cprefix = "XML_ATTRIBUTE_", cheader_filename = "libxml/tree.h", has_type_id = false)]
+ public enum AttributeType {
+ CDATA,
+ ID,
+ IDREF ,
+ IDREFS,
+ ENTITY,
+ ENTITIES,
+ NMTOKEN,
+ NMTOKENS,
+ ENUMERATION,
+ NOTATION
+ }
+
+ [Compact]
+ [CCode (cname = "xmlDoc", free_function = "xmlFreeDoc", cheader_filename = "libxml/tree.h,libxml/parser.h")]
+ public class Doc {
+ public ElementType type;
+ public string name;
+ public Node* children;
+ public Node* last;
+ public Node* parent;
+ public Node* next;
+ public Node* prev;
+ public Doc* doc;
+ public int compression;
+ public int standalone;
+ [CCode (cname = "intSubset")]
+ public Dtd* int_subset;
+ [CCode (cname = "extSubset")]
+ public Dtd* ext_subset;
+ [CCode (cname = "oldNs")]
+ public Ns* old_ns;
+ public weak string version;
+ public weak string encoding;
+ [CCode (cname = "URL")]
+ public weak string url;
+ public int charset;
+
+ [CCode (cname = "xmlCopyDoc")]
+ public Doc* copy (int recursive);
+
+ [CCode (cname = "xmlCreateIntSubset")]
+ public Dtd* create_int_subset (string name, string external_id, string system_id);
+
+ [CCode (cname = "xmlDocDump", instance_pos = -1)]
+ public int dump (GLib.FileStream f);
+
+ [CCode (cname = "xmlDocDumpFormatMemory")]
+ public void dump_memory_format (out string mem, out int len = null, bool format = true);
+
+ [CCode (cname = "xmlDocDumpFormatMemoryEnc")]
+ public void dump_memory_enc_format (out string mem, out int len = null, string enc = "UTF-8", bool format = true);
+
+ [CCode (cname = "xmlDocDumpMemory")]
+ public void dump_memory (out string mem, out int len = null);
+
+ [CCode (cname = "xmlDocDumpMemoryEnc")]
+ public void dump_memory_enc (out string mem, out int len = null, string enc = "UTF-8");
+
+ [CCode (cname = "xmlDocFormatDump", instance_pos = 1.1)]
+ public int dump_format (GLib.FileStream f, bool format = true);
+
+ [CCode (cname = "xmlDocGetRootElement")]
+ public Node* get_root_element();
+
+ [CCode (cname = "xmlDocSetRootElement")]
+ public Node* set_root_element(Node* root);
+
+ [CCode (cname = "xmlElemDump", instance_pos = 1.1)]
+ public void elem_dump (GLib.FileStream f, Node* cur);
+
+ [CCode (cname = "xmlGetDocCompressMode")]
+ public int get_compress_mode ();
+
+ [CCode (cname = "xmlNewCDataBlock")]
+ public Node* new_cdata_block (string content, int len);
+
+ [CCode (cname = "xmlNewCharRef")]
+ public Node* new_char_ref (string name);
+
+ [CCode (cname = "xmlNewDoc")]
+ public Doc (string? version = null);
+
+ [CCode (cname = "xmlNewDocComment")]
+ public Node* new_comment (string content);
+
+ [CCode (cname = "xmlNewDocFragment")]
+ public Node* new_fragment ();
+
+ [CCode (cname = "xmlNewDocNode")]
+ public Node* new_node (Ns* ns, string name, string? content = null);
+
+ [CCode (cname = "xmlNewDocNodeEatName")]
+ public Node* new_node_eat_name (Ns* ns, owned string name, string? content = null);
+
+ [CCode (cname = "xmlNewDocPI")]
+ public Node* new_pi (string name, string content);
+
+ [CCode (cname = "xmlNewDocProp")]
+ public Attr* new_prop (string name, string value);
+
+ [CCode (cname = "xmlNewDocRawNode")]
+ public Node* new_raw_node (Ns* ns, string name, string? content = null);
+
+ [CCode (cname = "xmlNewDocText")]
+ public Node* new_text (string content);
+
+ [CCode (cname = "xmlNewDocTextLen")]
+ public Node* new_text_len (string content, int len);
+
+ [CCode (cname = "xmlNewReference")]
+ public Node* new_reference (string name);
+
+ [CCode (cname = "xmlNodeListGetRawString")]
+ public string node_list_get_raw_string (Node* list, bool in_line);
+
+ [CCode (cname = "xmlNodeListGetString")]
+ public string node_list_get_string (Node* list, bool in_line);
+
+ [CCode (cname = "xmlSaveFile", instance_pos = -1)]
+ public int save_file (string filename);
+
+ [CCode (cname = "xmlSaveFileEnc", instance_pos = 1.1)]
+ public void save_file_enc (string filename, string enc = "UTF-8");
+
+ [CCode (cname = "xmlSaveFormatFile", instance_pos = 1.1)]
+ public int save_format_file (string filename, int format);
+
+ [CCode (cname = "xmlSaveFormatFileEnc", instance_pos = 1.1)]
+ public void save_format_file_enc (string filename, string enc = "UTf-8", bool format = true);
+
+ [CCode (cname = "xmlSetDocCompressMode")]
+ public void set_compress_mode (int mode);
+
+ [CCode (cname = "xmlStringGetNodeList")]
+ public Node* string_get_node_list (string str);
+
+ [CCode (cname = "xmlStringLenGetNodeList")]
+ public Node* string_len_get_node_list (string str, int len);
+ }
+
+ [Compact]
+ [CCode (cname = "xmlDtd", free_function="xmlFreeDtd", cheader_filename = "libxml/tree.h")]
+ public class Dtd {
+ public ElementType type;
+ public string name;
+ public Node* children;
+ public Node* last;
+ public Node* parent;
+ public Node* next;
+ public Node* prev;
+ public Doc* doc;
+
+ public weak string external_id;
+ public weak string system_id;
+
+ [CCode (cname = "xmlNewDtd")]
+ public Dtd (Doc* doc, string name, string external_id, string system_id);
+
+ [CCode (cname = "xmlCopyDtd")]
+ public Dtd* copy();
+ }
+
+ [Compact]
+ [CCode (cname = "xmlElement", cheader_filename = "libxml/tree.h")]
+ public class Element {
+ public ElementType type;
+ public weak string name;
+ public Node* children;
+ public Node* last;
+ public Dtd* parent;
+ public Node* next;
+ public Node* prev;
+ public Doc* doc;
+ public Attribute* attributes;
+ public weak string prefix;
+ }
+
+ [CCode (cname = "xmlElementType", cprefix = "XML_", cheader_filename = "libxml/tree.h", has_type_id = false)]
+ public enum ElementType {
+ ELEMENT_NODE,
+ ATTRIBUTE_NODE,
+ TEXT_NODE,
+ CDATA_SECTION_NODE,
+ ENTITY_REF_NODE,
+ ENTITY_NODE,
+ PI_NODE,
+ COMMENT_NODE,
+ DOCUMENT_NODE,
+ DOCUMENT_TYPE_NODE,
+ DOCUMENT_FRAG_NODE,
+ NOTATION_NODE,
+ HTML_DOCUMENT_NODE,
+ DTD_NODE,
+ ELEMENT_DECL,
+ ATTRIBUTE_DECL,
+ ENTITY_DECL,
+ NAMESPACE_DECL,
+ XINCLUDE_START,
+ XINCLUDE_END,
+ DOCB_DOCUMENT_NODE
+ }
+
+ [Compact]
+ [CCode (cname = "xmlElementContent", free_function = "xmlFreeElementContent", cheader_filename = "libxml/tree.h")]
+ public class ElementContent {
+ [CCode (cname = "xmlNewElementContent")]
+ ElementContent (string name, ElementContentType type);
+
+ public ElementContentType type;
+ public ElementContentOccur ocur;
+ public const string name;
+ public ElementContent c1;
+ public ElementContent c2;
+ public ElementContent parent;
+ public const string prefix;
+ }
+
+ [CCode (cname = "xmlElementContentType", cprefix = "XML_ELEMENT_CONTENT_", cheader_filename = "libxml/tree.h", has_type_id = false)]
+ public enum ElementContentType {
+ PCDATA,
+ ELEMENT,
+ SEQ,
+ OR
+ }
+
+ [CCode (cname = "xmlElementContentOccur", cprefix = "XML_ELEMENT_CONTENT_", cheader_filename = "libxml/tree.h", has_type_id = false)]
+ public enum ElementContentOccur {
+ ONCE,
+ OPT,
+ MULT,
+ PLUS
+ }
+
+ [Compact]
+ [CCode (cname = "xmlEntity", cheader_filename = "libxml/tree.h")]
+ public struct Entity {
+ public void* private;
+ public ElementType type;
+ public const string name;
+ public Node* children;
+ public Node* last;
+ public Dtd* parent;
+ public Node* next;
+ public Node* prev;
+ public Doc* doc;
+ public string orig;
+ public string content;
+ public int length;
+ public EntityType etype;
+ [CCode (cname = "ExternalID")]
+ public const string external_id;
+ [CCode (cname = "SystemID")]
+ public const string system_id;
+ public Entity* nexte;
+ [CCode (cname = "URI")]
+ public const string uri;
+ public int owner;
+ public int checked;
+ }
+
+ [CCode (cname = "xmlEntityType", cprefix = "XML_", cheader_filename = "libxml/tree.h", has_type_id = false)]
+ public enum EntityType {
+ INTERNAL_GENERAL_ENTITY,
+ EXTERNAL_GENERAL_PARSED_ENTITY,
+ EXTERNAL_GENERAL_UNPARSED_ENTITY,
+ INTERNAL_PARAMETER_ENTITY,
+ EXTERNAL_PARAMETER_ENTITY,
+ INTERNAL_PREDEFINED_ENTITY
+ }
+
+ [Compact]
+ [CCode (cname = "xmlEnumeration", cheader_filename = "libxml/tree.h")]
+ public struct Enumeration {
+ public Enumeration* next;
+ public const string name;
+ }
+
+
+ [Compact]
+ [CCode (cname = "xmlNode", free_function = "xmlFreeNode", cheader_filename = "libxml/tree.h")]
+ public class Node {
+ public ElementType type;
+ public weak string name;
+ public Node* children;
+ public Node* last;
+ public Node* parent;
+ public Node* next;
+ public Node* prev;
+ public Doc* doc;
+ public Ns* ns;
+ public string content;
+ public Attr* properties;
+ [CCode (cname = "nsDef")]
+ public Ns* ns_def;
+ public ushort line;
+ public ushort extra;
+
+ [CCode (cname = "xmlAddChild")]
+ public Node* add_child (Node* cur);
+
+ [CCode (cname = "xmlAddChildList")]
+ public Node* add_child_list (Node* cur);
+
+ [CCode (cname = "xmlAddNextSibling")]
+ public Node* add_next_sibling (Node* elem);
+
+ [CCode (cname = "xmlAddPrevSibling")]
+ public Node* add_prev_sibling (Node* elem);
+
+ [CCode (cname = "xmlAddSibling")]
+ public Node* add_sibling (Node* elem);
+
+ [CCode (cname = "xmlCopyNode")]
+ public Node* copy (int extended);
+
+ [CCode (cname = "xmlCopyNodeList")]
+ public Node copy_list();
+
+ [CCode (cname = "xmlDocCopyNode")]
+ public Node* doc_copy (Doc* doc, int extended);
+
+ [CCode (cname = "xmlDocCopyNodeList")]
+ public Node* doc_copy_list (Doc* doc);
+
+ [CCode (cname = "xmlFreeNodeList")]
+ public void free_list ();
+
+ [CCode (cname = "xmlGetLastChild")]
+ public Node* get_last_child ();
+
+ [CCode (cname = "xmlGetLineNo")]
+ public long get_line_no ();
+
+ [CCode (cname = "xmlGetNoNsProp")]
+ public string? get_no_ns_prop (string name);
+
+ [CCode (cname = "xmlGetNodePath")]
+ public string get_path ();
+
+ [CCode (cname = "xmlGetNsProp")]
+ public string? get_ns_prop (string name, string ns);
+
+ [CCode (cname = "xmlGetProp")]
+ public string? get_prop (string name);
+
+ [CCode (cname = "xmlHasNsProp")]
+ public Attr* has_ns_prop (string name, string name_space);
+
+ [CCode (cname = "xmlHasProp")]
+ public Attr* has_prop (string name);
+
+ [CCode (cname = "xmlIsBlankNode")]
+ public int is_blank ();
+
+ [CCode (cname = "xmlNewChild")]
+ public Node* new_child (Ns* ns, string name, string? content = null);
+
+ [CCode (cname = "xmlNewNs")]
+ public Ns* new_ns (string href, string prefix);
+
+ [CCode (cname = "xmlNewNsProp")]
+ public Attr* new_ns_prop (Ns* ns, string name, string value);
+
+ [CCode (cname = "xmlNewProp")]
+ public Attr* new_prop (string name, string value);
+
+ [CCode (cname = "xmlNewTextChild")]
+ public Node* new_text_child (Ns* ns, string name, string content);
+
+ [CCode (cname = "xmlNodeAddContent")]
+ public void add_content (string content);
+
+ [CCode (cname = "xmlNodeAddContentLen")]
+ public void add_content_len (string content, int len);
+
+ [CCode (cname = "xmlNodeGetContent")]
+ public string get_content();
+
+ [CCode (cname = "xmlNodeGetLang")]
+ public string get_lang();
+
+ [CCode (cname = "xmlNodeGetSpacePreserve")]
+ public int get_space_preserve();
+
+ [CCode (cname = "xmlNodeIsText")]
+ public int is_text();
+
+ [CCode (cname = "xmlNodeSetContent")]
+ public void set_content (string content);
+
+ [CCode (cname = "xmlNodeSetContentLen")]
+ public void set_content_len (string content, int len);
+
+ [CCode (cname = "xmlNodeSetLang")]
+ public void set_lang (string val);
+
+ [CCode (cname = "xmlNodeSetName")]
+ public void set_name (string name);
+
+ [CCode (cname = "xmlNodeSetSpacePreserve")]
+ public void set_space_preserve (int val);
+
+ [CCode (cname = "xmlReplaceNode")]
+ public Node* replace (Node* cur);
+
+ [CCode (cname = "xmlNewComment")]
+ public Node.comment (string content);
+
+ [CCode (cname = "xmlNewNode")]
+ public Node (Ns* ns, string name);
+
+ [CCode (cname = "xmlNewNodeEatName")]
+ public Node.eat_name (Ns* ns, owned string name);
+
+ [CCode (cname = "xmlNewText")]
+ public Node.text (string content);
+
+ [CCode (cname = "xmlNewTextLen")]
+ public Node.text_len (string content, int len);
+
+ [CCode (cname = "xmlNewPI")]
+ public Node.pi (string name, string content);
+
+ [CCode (cname = "xmlSetListDoc")]
+ public void set_list_doc (Doc* doc);
+
+ [CCode (cname = "xmlSetNsProp")]
+ public Attr* set_ns_prop (Ns* ns, string name, string value);
+
+ [CCode (cname = "xmlSetProp")]
+ public Attr* set_prop (string name, string value);
+
+ [CCode (cname = "xmlSetTreeDoc")]
+ public void set_tree_doc (Doc* doc);
+
+ [CCode (cname = "xmlTextConcat")]
+ public int text_concat (string content, int len);
+
+ [CCode (cname = "xmlTextMerge")]
+ public Node* text_merge (Node* second);
+
+ [CCode (cname = "xmlUnlinkNode")]
+ public void unlink ();
+
+ [CCode (cname = "xmlUnsetNsProp")]
+ public int unset_ns_prop (Ns* ns, string name);
+
+ [CCode (cname = "xmlUnsetProp")]
+ public int unset_prop (string name);
+
+ [CCode (cname = "xmlNextElementSibling")]
+ public Node* next_element_sibling ();
+
+ [CCode (cname = "xmlFirstElementChild")]
+ public Node* first_element_child ();
+
+ [CCode (cname = "xmlChildElementCount")]
+ public ulong child_element_count ();
+ }
+
+ [Compact]
+ [CCode (cname = "xmlNs", free_function= "xmlFreeNs", cheader_filename = "libxml/tree.h")]
+ public class Ns {
+ [CCode (cname = "xmlNewNs")]
+ public Ns (Xml.Node* node, string href, string prefix);
+ public Ns* next;
+ public ElementType type;
+ public string href;
+ public string prefix;
+ public Doc* context;
+ }
+
+ [Compact]
+ [CCode (cname = "xmlParserCtxt", free_function = "xmlFreeParserCtxt", cheader_filename = "libxml/parser.h")]
+ public class ParserCtxt {
+ public SAXHandler* sax;
+ [CCode (cname = "userData")]
+ public void* user_data;
+
+ [CCode (cname = "xmlNewParserCtxt")]
+ public ParserCtxt ();
+
+ [CCode (cname = "xmlCreatePushParserCtxt")]
+ public ParserCtxt.create_push (Xml.SAXHandler* sax, void* user_data, [CCode (array_length = false)] char[] data, int len, string? filename = null);
+
+ [CCode (cname = "xmlCreateIOParserCtxt")]
+ public ParserCtxt.create_io (Xml.SAXHandler* sax, void* user_data, Xml.InputReadCallback ioread, Xml.InputCloseCallback ioclose, void* ioctx, string? encoding = null);
+
+ [CCode (cname = "xmlCreateDocParserCtxt")]
+ public ParserCtxt.create_doc (string cur);
+
+ [CCode (cname = "xmlParseChunk")]
+ public int parse_chunk ([CCode (array_length = false)] char[] data, int size, bool terminate);
+
+ [CCode (cname = "xmlParseDocument")]
+ public int parse_document ();
+
+ [CCode (cname = "xmlCtxtResetPush")]
+ public void reset_push ([CCode (array_length = false)] char[] data, int len, string? filename = null, string? encoding = null);
+
+ [CCode (cname = "xmlCtxtReset")]
+ public void reset ();
+
+ [CCode (cname = "xmlCtxtInit")]
+ public void init ();
+
+ [CCode (cname = "xmlCtxtClear")]
+ public void clear ();
+
+ [CCode (cname = "xmlCtxtUseOptions")]
+ public int use_options (int options);
+
+ [CCode (cname = "xmlCtxtReadDoc")]
+ public Doc* read_doc (string cur, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlCtxtReadFile")]
+ public Doc* read_file (string filename, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlCtxtReadMemory")]
+ public Doc* read_memory ([CCode (array_length = false)] char[] buffer, int size, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlCtxtReadFd")]
+ public Doc* read_fd (int fd, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlCtxtReadIO")]
+ public Doc* read_io (Xml.InputReadCallback ioread, Xml.InputCloseCallback ioclose, void* ioctx, string url, string? encoding = null, int options = 0);
+ }
+
+
+ /* uri - library of generic URI related routines */
+
+ [Compact]
+ [CCode (cname = "xmlURI", free_function = "xmlFreeURI", cheader_filename = "libxml/uri.h")]
+ public class URI {
+ [CCode (cname = "xmlBuildRelativeURI")]
+ public static string build_relative (string uri, string @base);
+
+ [CCode (cname = "xmlBuildURI")]
+ public static string build (string URI, string @base);
+
+ [CCode (cname = "xmlCanonicPath")]
+ public static string canonic_path (string path);
+
+ [CCode (cname = "xmlCreateURI")]
+ public URI ();
+
+ [CCode (cname = "xmlNormalizeURIPath")]
+ public static int normalize_uri_path (string path);
+
+ [CCode (cname = "xmlParseURI")]
+ public static URI? parse (string str);
+
+ [CCode (cname = "xmlParseURIRaw")]
+ public static URI? parse_raw (string str, bool raw);
+
+ [CCode (cname = "xmlParseURIReference")]
+ public int parse_reference (string str);
+
+ [CCode (cname = "xmlPathToURI")]
+ public static string path_to_uri (string path);
+
+ [CCode (cname = "xmlPrintURI", instance_pos = -1)]
+ public void print (GLib.FileStream stream);
+
+ [CCode (cname = "xmlSaveUri")]
+ public string save ();
+
+ [CCode (cname = "xmlURIEscape")]
+ public static string escape (string str);
+
+ [CCode (cname = "xmlURIEscapeStr")]
+ public static string escape_str (string str, string list);
+
+ [CCode (cname = "xmlURIUnescapeString")]
+ public static string unescape_string (string str, int len, string? target);
+
+ public string scheme;
+ public string opaque;
+ public string authority;
+ public string server;
+ public string user;
+ public int port;
+ public string path;
+ public string query;
+ public string fragment;
+ public int cleanup;
+ public string query_raw;
+ }
+
+
+ /* xmlIO - interface for the I/O interfaces used by the parser */
+
+ [CCode (has_target = false, cname = "xmlInputCloseCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate int InputCloseCallback (void* context);
+
+ [CCode (has_target = false, cname = "xmlInputReadCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate int InputReadCallback (void* context, [CCode (array_length = false)] char[] buffer, int len);
+
+ [CCode (has_target = false, cname = "xmlInputMatchCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate int InputMatchCallback (string filename);
+
+ [CCode (has_target = false, cname = "xmlInputOpenCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate void* InputOpenCallback (string filename);
+
+ [CCode (has_target = false, cname = "xmlOutputMatchCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate int OutputMatchCallback (string filename);
+
+ [CCode (has_target = false, cname = "xmlOutputOpenCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate void* OutputOpenCallback (string filename);
+
+ [CCode (has_target = false, cname = "xmlOutputWriteCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate int OutputWriteCallback ([CCode (array_length = false)] char[] buffer, int len);
+
+ [CCode (has_target = false, cname = "xmlOutputCloseCallback", cheader_filename = "libxml/xmlIO.h")]
+ public delegate int OutputCloseCallback (void * context);
+
+ [CCode (cname = "xmlRegisterInputCallbacks", cheader_filename = "libxml/xmlIO.h")]
+ public int registerInputCallbacks (InputMatchCallback matchFunc, InputOpenCallback openFunc, InputReadCallback readFunc, InputCloseCallback closeFunc);
+
+ [CCode (cname = "xmlRegisterOutputCallbacks", cheader_filename = "libxml/xmlIO.h")]
+ public int registerOutputCallbacks(OutputMatchCallback matchFunc, OutputOpenCallback openFunc, OutputWriteCallback writeFunc, OutputCloseCallback closeFunc);
+
+ /* xmlschemas - incomplete XML Schemas structure implementation */
+
+ [Compact]
+ [CCode (cname = "xmlSchemaValidCtxt", cheader_filename = "libxml/xmlreader.h")]
+ public class SchemaValidCtxt {
+ }
+
+ /* xmlsave */
+
+ [Compact]
+ [CCode (cname = "xmlSaveCtxt", free_function = "xmlSaveClose", cheader_filename = "libxml/xmlsave.h")]
+ public class SaveCtxt {
+ [CCode (cname = "xmlSaveToIO")]
+ public SaveCtxt.to_io (OutputWriteCallback iowrite, OutputCloseCallback ioclose, void * ioctx = null, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlSaveClose")]
+ public int close ();
+ [CCode (cname = "xmlSaveFlush")]
+ public int flush ();
+ [CCode (cname = "xmlSaveDoc")]
+ public int save_doc (Xml.Doc *doc);
+ [CCode (cname = "xmlSaveTree")]
+ public int save_tree (Xml.Node *node);
+ }
+
+ /* xmlwriter - the XMLWriter implementation */
+
+ [Compact]
+ [CCode (cname = "xmlTextWriter", free_function = "xmlFreeTextWriter", cheader_filename = "libxml/xmlwriter.h")]
+ public class TextWriter {
+ [CCode (cname = "xmlNewTextWriterFilename")]
+ public TextWriter.filename (string uri, bool compression = false);
+
+ [CCode (cname = "xmlNewTextWriterDoc")]
+ public TextWriter.doc (out Doc doc, bool compression = false);
+
+ [CCode (cname = "xmlTextWriterFlush")]
+ public int flush ();
+
+ [CCode (cname = "xmlTextWriterSetIndent")]
+ public int set_indent (bool indent);
+
+ [CCode (cname = "xmlTextWriterSetIndentString")]
+ public int set_indent_string (string str);
+
+ /* End */
+ [CCode (cname = "xmlTextWriterEndCDATA")]
+ public int end_cdata ();
+
+ [CCode (cname = "xmlTextWriterEndComment")]
+ public int end_comment ();
+
+ [CCode (cname = "xmlTextWriterEndDocument")]
+ public int end_document ();
+
+ [CCode (cname = "xmlTextWriterEndElement")]
+ public int end_element ();
+
+ [CCode (cname = "xmlTextWriterEndAttribute")]
+ public int end_attribute ();
+
+ /* Start */
+
+ [CCode (cname = "xmlTextWriterStartCDATA")]
+ public int start_cdata ();
+
+ [CCode (cname = "xmlTextWriterStartComment")]
+ public int start_comment ();
+
+ [CCode (cname = "xmlTextWriterStartDocument")]
+ public int start_document (string? version = null, string? encoding = null, string? standalone = null);
+
+ [CCode (cname = "xmlTextWriterStartElement")]
+ public int start_element (string name);
+
+ [CCode (cname = "xmlTextWriterStartElementNS")]
+ public int start_element_ns (string prefix, string name, string namespaceURI);
+
+ [CCode (cname = "xmlTextWriterStartAttribute")]
+ public int start_attribute (string name);
+
+ [CCode (cname = "xmlTextWriterStartAttributeNS")]
+ public int start_attribute_ns (string prefix, string name, string namespaceURI);
+
+ /* write */
+
+ [CCode (cname = "xmlTextWriterWriteAttribute")]
+ public int write_attribute (string name, string content);
+
+ [CCode (cname = "xmlTextWriterWriteAttributeNS")]
+ public int write_attribute_ns (string prefix, string name, string namespaceURI, string content);
+
+ [CCode (cname = "xmlTextWriterWriteElement")]
+ public int write_element (string name, string content);
+
+ [CCode (cname = "xmlTextWriterWriteElementNS")]
+ public int write_element_ns (string prefix, string name, string namespaceURI, string content);
+
+ [CCode (cname = "xmlTextWriterWriteBase64")]
+ public int write_base64 (void* data, int start, int length);
+
+ [CCode (cname = "xmlTextWriterWriteComment")]
+ public int write_comment (string content);
+
+ [CCode (cname = "xmlTextWriterWriteString")]
+ public int write_string (string content);
+
+ [CCode (cname = "xmlTextWriterWriteCDATA")]
+ public int write_cdata (string content);
+
+ /* formatted */
+
+ [CCode (cname = "xmlTextWriterWriteFormatAttribute")]
+ public int format_attribute (string name, string format, ...);
+
+ [CCode (cname = "xmlTextWriterWriteFormatAttributeNS")]
+ public int format_attribute_ns (string prefix, string name, string namespaceURI, string format, ...);
+
+ [CCode (cname = "xmlTextWriterWriteFormatCDATA")]
+ public int format_cdata (string format, ...);
+
+ [CCode (cname = "xmlTextWriterWriteFormatComment")]
+ public int format_comment (string format, ...);
+
+ [CCode (cname = "xmlTextWriterWriteFormatElement")]
+ public int format_element (string name, string format, ...);
+
+ [CCode (cname = "xmlTextWriterWriteFormatElementNS")]
+ public int format_element_ns (string prefix, string name, string namespaceURI, string format, ...);
+
+ [CCode (cname = "xmlTextWriterWriteFormatString")]
+ public int format_string (string format, ...);
+ }
+
+ /* xmlreader - the XMLReader implementation */
+
+ [CCode (cname = "xmlParserProperties", cprefix = "XML_PARSER_", cheader_filename = "libxml/xmlreader.h", has_type_id = false)]
+ public enum ParserProperties {
+ LOADDTD,
+ DEFAULTATTRS,
+ VALIDATE,
+ SUBST_ENTITIES
+ }
+
+ [CCode (cname = "xmlParserSeverities", cprefix = "XML_PARSER_SEVERITY_", cheader_filename = "libxml/xmlreader.h", has_type_id = false)]
+ public enum ParserSeverities {
+ VALIDITY_WARNING,
+ VALIDITY_ERROR,
+ WARNING,
+ ERROR
+ }
+
+ [CCode (cname = "xmlReaderTypes", cheader_filename = "libxml/xmlreader.h", has_type_id = false)]
+ public enum ReaderType {
+ NONE,
+ ELEMENT,
+ ATTRIBUTE,
+ TEXT,
+ CDATA,
+ ENTITY_REFERENCE,
+ ENTITY,
+ PROCESSING_INSTRUCTION,
+ COMMENT,
+ DOCUMENT,
+ DOCUMENT_TYPE,
+ DOCUMENT_FRAGMENT,
+ NOTATION,
+ WHITESPACE,
+ SIGNIFICANT_WHITESPACE,
+ END_ELEMENT,
+ END_ENTITY,
+ XML_DECLARATION
+ }
+
+ [Compact]
+ [CCode (cname = "xmlTextReader", free_function = "xmlFreeTextReader", cheader_filename = "libxml/xmlreader.h")]
+ public class TextReader {
+ [CCode (cname = "xmlNewTextReaderFilename")]
+ public TextReader.filename (string uri);
+
+ [CCode (cname = "xmlReaderForDoc")]
+ public TextReader.for_doc (string cur, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderForFd")]
+ public TextReader.for_fd (int fd, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderForFile")]
+ public TextReader.for_file (string filename, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderForIO")]
+ public TextReader.for_io (InputReadCallback ioread, InputCloseCallback ioclose, void* ioctx, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderForMemory")]
+ public TextReader.for_memory ([CCode (array_length = false)] char[] buffer, int size, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderNewDoc")]
+ public int new_doc (string cur, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderNewFd")]
+ public int new_fd (int fd, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderNewFile")]
+ public int new_file (string filename, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderNewIO")]
+ public int new_io (InputReadCallback ioread, InputCloseCallback ioclose, void* ioctx, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderNewMemory")]
+ public int new_memory ([CCode (array_length = false)] char[] buffer, int size, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "xmlReaderNewWalker")]
+ public int new_walker (Doc* doc);
+
+ [CCode (cname = "xmlReaderWalker")]
+ public TextReader.walker (Doc* doc);
+
+ [CCode (cname = "xmlTextReaderAttributeCount")]
+ public int attribute_count ();
+
+ [CCode (cname = "xmlTextReaderBaseUri")]
+ public string base_uri ();
+
+ [CCode (cname = "xmlTextReaderByteConsumed")]
+ public long byte_consumed ();
+
+ [CCode (cname = "xmlTextReaderClose")]
+ public int close ();
+
+ [CCode (cname = "xmlTextReaderConstBaseUri")]
+ public unowned string const_base_uri ();
+
+ [CCode (cname = "xmlTextReaderConstEncoding")]
+ public unowned string const_encoding ();
+
+ [CCode (cname = "xmlTextReaderConstLocalName")]
+ public unowned string const_local_name ();
+
+ [CCode (cname = "xmlTextReaderConstName")]
+ public unowned string const_name ();
+
+ [CCode (cname = "xmlTextReaderConstNamespaceUri")]
+ public unowned string const_namespace_uri ();
+
+ [CCode (cname = "xmlTextReaderConstPrefix")]
+ public unowned string const_prefix ();
+
+ [CCode (cname = "xmlTextReaderConstString")]
+ public unowned string const_string (string str);
+
+ [CCode (cname = "xmlTextReaderConstValue")]
+ public unowned string const_value ();
+
+ [CCode (cname = "xmlTextReaderConstXmlLang")]
+ public unowned string const_xml_lang ();
+
+ [CCode (cname = "xmlTextReaderConstXmlVersion")]
+ public unowned string const_xml_version ();
+
+ [CCode (cname = "xmlTextReaderCurrentDoc")]
+ public Doc* current_doc ();
+
+ [CCode (cname = "xmlTextReaderCurrentNode")]
+ public Node* current_node ();
+
+ [CCode (cname = "xmlTextReaderDepth")]
+ public int depth ();
+
+ [CCode (cname = "xmlTextReaderExpand")]
+ public Node* expand ();
+
+ [CCode (cname = "xmlTextReaderGetAttribute")]
+ public string get_attribute (string name);
+
+ [CCode (cname = "xmlTextReaderGetAttributeNo")]
+ public string get_attribute_no (int no);
+
+ [CCode (cname = "xmlTextReaderGetAttributeNs")]
+ public string get_attribute_ns (string local_name, string namespace_uri);
+
+ [CCode (cname = "xmlTextReaderGetErrorHandler")]
+ public void get_error_handler (out TextReaderErrorFunc f, void** arg);
+
+ [CCode (cname = "xmlTextReaderGetParserColumnNumber")]
+ public int get_parser_column_number ();
+
+ [CCode (cname = "xmlTextReaderGetParserLineNumber")]
+ public int get_parser_line_number ();
+
+ [CCode (cname = "xmlTextReaderGetParserProp")]
+ public int get_parser_prop (int prop);
+
+ [CCode (cname = "xmlTextReaderHasAttributes")]
+ public int has_attributes ();
+
+ [CCode (cname = "xmlTextReaderHasValue")]
+ public int has_value ();
+
+ [CCode (cname = "xmlTextReaderIsDefault")]
+ public int is_default ();
+
+ [CCode (cname = "xmlTextReaderIsEmptyElement")]
+ public int is_empty_element ();
+
+ [CCode (cname = "xmlTextReaderIsNamespaceDecl")]
+ public int is_namespace_decl ();
+
+ [CCode (cname = "xmlTextReaderIsValid")]
+ public int is_valid ();
+
+ [CCode (cname = "xmlTextReaderLocalName")]
+ public string local_name ();
+
+ [CCode (cname = "xmlTextReaderLookupNamespace")]
+ public string lookup_namespace (string prefix);
+
+ [CCode (cname = "xmlTextReaderMoveToAttribute")]
+ public int move_to_attribute (string name);
+
+ [CCode (cname = "xmlTextReaderMoveToAttributeNo")]
+ public int move_to_attribute_no (int no);
+
+ [CCode (cname = "xmlTextReaderMoveToAttributeNs")]
+ public int move_to_attribute_ns (string local_name, string namespace_uri);
+
+ [CCode (cname = "xmlTextReaderMoveToElement")]
+ public int move_to_element ();
+
+ [CCode (cname = "xmlTextReaderMoveToFirstAttribute")]
+ public int move_to_first_attribute ();
+
+ [CCode (cname = "xmlTextReaderMoveToNextAttribute")]
+ public int move_to_next_attribute ();
+
+ [CCode (cname = "xmlTextReaderName")]
+ public string name ();
+
+ [CCode (cname = "xmlTextReaderNamespaceUri")]
+ public string namespace_uri ();
+
+ [CCode (cname = "xmlTextReaderNext")]
+ public int next ();
+
+ [CCode (cname = "xmlTextReaderNextSibling")]
+ public int next_sibling ();
+
+ [CCode (cname = "xmlTextReaderNodeType")]
+ public int node_type ();
+
+ [CCode (cname = "xmlTextReaderNormalization")]
+ public int normalization ();
+
+ [CCode (cname = "xmlTextReaderPrefix")]
+ public string prefix ();
+
+ [CCode (cname = "xmlTextReaderPreserve")]
+ public Node* preserve ();
+
+ [CCode (cname = "xmlTextReaderPreservePattern")]
+ public int preserve_pattern (string pattern, [CCode (array_length = false)] string[] namespaces);
+
+ [CCode (cname = "xmlTextReaderQuoteChar")]
+ public int quote_char ();
+
+ [CCode (cname = "xmlTextReaderRead")]
+ public int read ();
+
+ [CCode (cname = "xmlTextReaderReadAttributeValue")]
+ public int read_attribute_value ();
+
+ [CCode (cname = "xmlTextReaderReadInnerXml")]
+ public string read_inner_xml ();
+
+ [CCode (cname = "xmlTextReaderReadOuterXml")]
+ public string read_outer_xml ();
+
+ [CCode (cname = "xmlTextReaderReadState")]
+ public int read_state ();
+
+ [CCode (cname = "xmlTextReaderReadString")]
+ public string read_string ();
+
+ [CCode (cname = "xmlTextReaderSchemaValidate")]
+ public int schema_validate (string xsd);
+
+ [CCode (cname = "xmlTextReaderSchemaValidateCtxt")]
+ public int schema_validate_ctxt (SchemaValidCtxt* ctxt, int options);
+
+ [CCode (cname = "xmlTextReaderSetErrorHandler")]
+ public void set_error_handler (TextReaderErrorFunc f, void* arg);
+
+ [CCode (cname = "xmlTextReaderSetParserProp")]
+ public int set_parser_prop (SchemaValidCtxt* ctxt, int options);
+
+ [CCode (cname = "xmlTextReaderStandalone")]
+ public int standalone ();
+
+ [CCode (cname = "xmlTextReaderValue")]
+ public string value ();
+
+ [CCode (cname = "xmlTextReaderXmlLang")]
+ public string xml_lang ();
+ }
+
+ [Compact]
+ [CCode (cname = "void", cheader_filename = "libxml/xmlreader.h")]
+ public class TextReaderLocator {
+ }
+
+ [CCode (cname = "xmlTextReaderMode", cprefix = "XML_TEXTREADER_MODE_", cheader_filename = "libxml/xmlreader.h", has_type_id = false)]
+ public enum TextReaderMode {
+ INITIAL,
+ INTERACTIVE,
+ ERROR,
+ EOF,
+ CLOSED,
+ READING
+ }
+
+ [CCode (has_target = false)]
+ public delegate void TextReaderErrorFunc (void* arg, string msg, ParserSeverities severity, TextReaderLocator* locator);
+
+
+ /* xpath - XML Path Language implementation */
+
+ [CCode (cheader_filename = "libxml/xpath.h")]
+ namespace XPath {
+ [CCode (cname = "xmlXPathOrderDocElems")]
+ public static long order_doc_elements (Doc* doc);
+
+ [Compact]
+ [CCode (cname = "xmlNodeSet", free_function="xmlXPathFreeNodeSet", cheader_filename = "libxml/xpath.h")]
+ public class NodeSet {
+ [CCode (cname = "xmlXPathNodeSetGetLength")]
+ public int length ();
+
+ [CCode (cname = "xmlXPathNodeSetIsEmpty")]
+ public bool is_empty ();
+
+ [CCode (cname = "xmlXPathNodeSetItem")]
+ public Node* item (int index);
+ }
+
+ [Compact]
+ [CCode (cname = "xmlXPathContext", free_function = "xmlXPathFreeContext", cheader_filename = "libxml/xpath.h")]
+ public class Context {
+ public Doc* doc;
+ public Node* node;
+
+ [CCode (cname = "xmlXPathContextSetCache")]
+ public int set_cache (int active, int value, int options);
+
+ [CCode (cname = "xmlXPathEval", instance_pos = -1)]
+ public Object* eval (string str);
+
+ [CCode (cname = "xmlXPathEvalExpression", instance_pos = -1)]
+ public Object* eval_expression (string str);
+
+ [CCode (cname = "xmlXPathRegisterNs")]
+ public int register_ns (string prefix, string ns_uri);
+
+ [CCode (cname = "xmlXPathNewContext")]
+ public Context (Doc* doc);
+ }
+
+ [CCode (cname = "xmlXPathError", cprefix = "XPATH_", cheader_filename = "libxml/xpath.h", has_type_id = false)]
+ public enum Error {
+ EXPRESSION_OK,
+ NUMBER_ERROR,
+ UNFINISHED_LITERAL_ERROR,
+ START_LITERAL_ERROR,
+ VARIABLE_REF_ERROR,
+ UNDEF_VARIABLE_ERROR,
+ INVALID_PREDICATE_ERROR,
+ EXPR_ERROR,
+ UNCLOSED_ERROR,
+ UNKNOWN_FUNC_ERROR,
+ INVALID_OPERAND,
+ INVALID_TYPE,
+ INVALID_ARITY,
+ INVALID_CTXT_SIZE,
+ INVALID_CTXT_POSITION,
+ MEMORY_ERROR,
+ [CCode (cname = "XPTR_SYNTAX_ERROR")]
+ XPTR_SYNTAX_ERROR,
+ [CCode (cname = "XPTR_RESOURCE_ERROR")]
+ XPTR_RESOURCE_ERROR,
+ [CCode (cname = "XPTR_SUB_RESOURCE_ERROR")]
+ XPTR_SUB_RESOURCE_ERROR,
+ UNDEF_PREFIX_ERROR,
+ ENCODING_ERROR,
+ INVALID_CHAR_ERROR,
+ INVALID_CTXT
+ }
+
+ [Compact]
+ [CCode (cname = "xmlXPathObject", free_function="xmlXPathFreeObject", cheader_filename = "libxml/xpath.h")]
+ public class Object {
+ public ObjectType type;
+ public NodeSet* nodesetval;
+ public int boolval;
+ public double floatval;
+ public string stringval;
+ public void* user;
+ public int index;
+ public void* user2;
+ public int index2;
+ }
+
+ [CCode (cname = "xmlXPathObjectType", cprefix = "XPATH_", cheader_filename = "libxml/xpath.h", has_type_id = false)]
+ public enum ObjectType {
+ UNDEFINED,
+ NODESET,
+ BOOLEAN,
+ NUMBER,
+ STRING,
+ POINT,
+ RANGE,
+ LOCATIONSET,
+ USERS,
+ XSLT_TREE
+ }
+ }
+
+ /* SAX CALLBACKS */
+
+ [CCode (cname = "attributeDeclSAXFunc", has_target = false)]
+ public delegate void attributeDeclSAXFunc (void* ctx, string elem, string fullname, int type, int def, string defaultValue, Enumeration* tree);
+
+ [CCode (cname = "attributeSAXFunc", has_target = false)]
+ public delegate void attributeSAXFunc (void* ctx, string name, string value);
+
+ [CCode (cname = "cdataBlockSAXFunc", has_target = false)]
+ public delegate void cdataBlockSAXFunc (void* ctx, string value, int len);
+
+ [CCode (cname = "charactersSAXFunc", has_target = false)]
+ public delegate void charactersSAXFunc (void* ctx, string ch, int len);
+
+ [CCode (cname = "commentsSAXFunc", has_target = false)]
+ public delegate void commentSAXFunc (void* ctx, string value);
+
+ [CCode (cname = "elementDeclSAXFunc", has_target = false)]
+ public delegate void elementDeclSAXFunc (void* ctx, string name, int type, ElementContent content);
+
+ [CCode (cname = "endDocumentSAXFunc", has_target = false)]
+ public delegate void endDocumentSAXFunc (void* ctx);
+
+ [CCode (cname = "endElementNsSAX2Func", has_target = false)]
+ public delegate void endElementNsSAX2Func (void* ctx, string localname, string prefix, string URI);
+
+ [CCode (cname = "endElementSAXFunc", has_target = false)]
+ public delegate void endElementSAXFunc (void* ctx, string name);
+
+ [CCode (cname = "entityDeclSAXFunc", has_target = false)]
+ public delegate void entityDeclSAXFunc (void* ctx, string name, int type, string publicId, string systemId, string content);
+
+ [CCode (cname = "errorSAXFunc", has_target = false)]
+ public delegate void errorSAXFunc (void* ctx, string msg, ...);
+
+ [CCode (cname = "externalSubsetSAXFunc", has_target = false)]
+ public delegate void externalSubsetSAXFunc (void* ctx, string name, string ExternalID, string SystemID);
+
+ [CCode (cname = "fatalErrorSAXFunc", has_target = false)]
+ public delegate void fatalErrorSAXFunc (void* ctx, string msg, ...);
+
+ [CCode (cname = "getEntitySAXFunc", has_target = false)]
+ public delegate Entity* getEntitySAXFunc (void* ctx, string name);
+
+ [CCode (cname = "getParameterEntitySAXFunc", has_target = false)]
+ public delegate Entity* getParameterEntitySAXFunc (void* ctx, string name);
+
+ [CCode (cname = "hasExternalSubsetSAXFunc", has_target = false)]
+ public delegate int hasExternalSubsetSAXFunc (void* ctx);
+
+ [CCode (cname = "hasInternalSubsetSAXFunc", has_target = false)]
+ public delegate int hasInternalSubsetSAXFunc (void* ctx);
+
+ [CCode (cname = "ignorableWhitespaceSAXFunc", has_target = false)]
+ public delegate void ignorableWhitespaceSAXFunc (void* ctx, string ch, int len);
+
+ [CCode (cname = "internalSubsetSAXFunc", has_target = false)]
+ public delegate void internalSubsetSAXFunc (void* ctx, string name, string ExternalID, string SystemID);
+
+ [CCode (cname = "isStandaloneSAXFunc", has_target = false)]
+ public delegate int isStandaloneSAXFunc (void* ctx);
+
+ [CCode (cname = "notationDeclSAXFunc", has_target = false)]
+ public delegate void notationDeclSAXFunc (void* ctx, string name, string publicId, string systemId);
+
+ [CCode (cname = "processingInstructionSAXFunc", has_target = false)]
+ public delegate void processingInstructionSAXFunc (void* ctx, string target, string data);
+
+ [CCode (cname = "referenceSAXFunc", has_target = false)]
+ public delegate void referenceSAXFunc (void* ctx, string name);
+
+ // [CCode (cname = "resolveEntitySAXFunc", has_target = false)]
+ // public delegate ParserInput resolveEntitySAXFunc (void* ctx, string publicId, string systemId);
+
+ // [CCode (cname = "setDocumentLocatorSAXFunc", has_target = false)]
+ // public delegate void setDocumentLocatorSAXFunc (void* ctx, SAXLocator loc);
+
+ [CCode (cname = "startDocumentSAXFunc", has_target = false)]
+ public delegate void startDocumentSAXFunc (void* ctx);
+
+ [CCode (cname = "startElementNsSAX2Func", has_target = false)]
+ public delegate void startElementNsSAX2Func (void* ctx, string localname, string prefix, string URI, int nb_namespaces, [CCode (array_length = false, array_null_terminated = true)] string[] namespaces, int nb_attributes, int nb_defaulted, [CCode (array_length = false)] string[] attributes);
+
+ [CCode (cname = "startElementSAXFunc", has_target = false)]
+ public delegate void startElementSAXFunc (void* ctx, string name, [CCode (array_length = false, array_null_terminated = true)] string[] atts);
+
+ [CCode (cname = "unparsedEntityDeclSAXFunc", has_target = false)]
+ public delegate void unparsedEntityDeclSAXFunc (void* ctx, string name, string publicId, string systemId, string notationName);
+
+ [CCode (cname = "warningSAXFunc", has_target = false)]
+ public delegate void warningSAXFunc (void* ctx, string msg, ...);
+
+ [CCode (cname ="xmlStructuredErrorFunc", has_target = false)]
+ public delegate void xmlStructuredErrorFunc (void* ctx, Error* error);
+
+ [Compact]
+ [CCode (cname = "xmlSAXHandler", cheader_filename = "libxml/parser.h")]
+ public struct SAXHandler {
+ [CCode (cname = "internalSubset")]
+ public internalSubsetSAXFunc internalSubset;
+ [CCode (cname = "isStandalone")]
+ public isStandaloneSAXFunc is_standalone;
+ [CCode (cname = "hasInternalSubset")]
+ public hasInternalSubsetSAXFunc hasInternalSubset;
+ [CCode (cname = "hasExternalSubset")]
+ public hasExternalSubsetSAXFunc hasExternalSubset;
+ // public resolveEntitySAXFunc resolveEntity;
+ [CCode (cname = "getEntity")]
+ public getEntitySAXFunc getEntity;
+ [CCode (cname = "entityDecl")]
+ public entityDeclSAXFunc entityDecl;
+ [CCode (cname = "notationDecl")]
+ public notationDeclSAXFunc notationDecl;
+ [CCode (cname = "attributeDecl")]
+ public attributeDeclSAXFunc attributeDecl;
+ [CCode (cname = "elementDecl")]
+ public elementDeclSAXFunc elementDecl;
+ [CCode (cname = "unparsedEntityDecl")]
+ public unparsedEntityDeclSAXFunc unparsedEntityDecl;
+ // public setDocumentLocatorSAXFunc setDocumentLocator;
+ [CCode (cname = "startDocument")]
+ public startDocumentSAXFunc startDocument;
+ [CCode (cname = "endDocument")]
+ public endDocumentSAXFunc endDocument;
+ [CCode (cname = "startElement")]
+ public startElementSAXFunc startElement;
+ [CCode (cname = "endElement")]
+ public endElementSAXFunc endElement;
+ public referenceSAXFunc reference;
+ public charactersSAXFunc characters;
+ [CCode (cname = "ignorableWhitespace")]
+ public ignorableWhitespaceSAXFunc ignorableWhitespace;
+ [CCode (cname = "processingInstruction")]
+ public processingInstructionSAXFunc processingInstruction;
+ public commentSAXFunc comment;
+ public warningSAXFunc warning;
+ public errorSAXFunc error;
+ [CCode (cname = "fatalError")]
+ public fatalErrorSAXFunc fatalError;
+ [CCode (cname = "getParameterEntity")]
+ public getParameterEntitySAXFunc getParameterEntity;
+ [CCode (cname = "cdataBlock")]
+ public cdataBlockSAXFunc cdataBlock;
+ [CCode (cname = "externalSubset")]
+ public externalSubsetSAXFunc externalSubset;
+ public uint initialized;
+ [CCode (cname = "startElementNs")]
+ public startElementNsSAX2Func startElementNs;
+ [CCode (cname = "endElementNs")]
+ public endElementNsSAX2Func endElementNs;
+ public xmlStructuredErrorFunc serror;
+
+ [CCode (cname = "xmlSAXUserParseMemory")]
+ public int user_parse_memory (void* user_data, string buffer, int size);
+ [CCode (cname = "xmlSAXUserParseFile")]
+ public int user_parse_file (void* user_data, string filename);
+ }
+
+
+ /* xmlerror - error handling */
+
+ [Compact]
+ [CCode (cname = "xmlError", cheader_filename = "libxml/xmlerror.h")]
+ public struct Error {
+ public int domain;
+ public int code;
+ public string message;
+ public ErrorLevel level;
+ public string file;
+ public int line;
+ public string str1;
+ public string str2;
+ public string str3;
+ public int int1;
+ public int int2;
+ public void* ctx;
+ public void* node;
+ }
+
+ [CCode (cname = "xmlErrorLevel", cprefix = "XML_ERR_", cheader_filename = "libxml/xmlerror.h", has_type_id = false)]
+ public enum ErrorLevel {
+ NONE = 0,
+ WARNING = 1,
+ ERROR = 2,
+ FATAL = 3
+ }
+
+}
+
+namespace Html {
+ [CCode (cname = "htmlIsBooleanAttr", cheader_filename = "libxml/HTMLtree.h")]
+ public static int is_boolean_attr (string name);
+
+ [CCode (cname = "UTF8ToHtml", cheader_filename = "libxml/HTMLparser.h")]
+ public static int utf8_to_html ([CCode (array_length = false)] char[] outdata, out int outlen, [CCode (array_length = false)] char[] indata, out int inlen);
+
+ [CCode (cname = "htmlEncodeEntities", cheader_filename = "libxml/HTMLparser.h")]
+ public static int encode_entities ([CCode (array_length = false)] char[] outdata, out int outlen, [CCode (array_length = false)] char[] indata, out int inlen, char quote_char = '\0');
+
+ [CCode (cname = "htmlIsScriptAttribute", cheader_filename = "libxml/HTMLparser.h")]
+ public static bool is_script_attribute (string name);
+
+ [CCode (cname = "htmlHandleOmittedElem", cheader_filename = "libxml/HTMLparser.h")]
+ public static bool handle_omitted_elem (bool val);
+
+ [CCode (cname = "htmlParserOption", cprefix = "HTML_PARSE_", cheader_filename = "libxml/HTMLparser.h", has_type_id = false)]
+ public enum ParserOption {
+ RECOVER,
+ NOERROR,
+ NOWARNING,
+ PEDANTIC,
+ NOBLANKS,
+ NONET,
+ COMPACT,
+ }
+
+ [CCode (cname = "htmlStatus", cprefix = "HTML_", cheader_filename = "libxml/HTMLparser.h", has_type_id = false)]
+ public enum Status {
+ NA,
+ INVALID,
+ DEPRECATED,
+ VALID,
+ REQUIRED,
+ }
+
+ [Compact]
+ [CCode (cname = "xmlNode", cheader_filename = "libxml/HTMLparser.h")]
+ public class Node : Xml.Node {
+ [CCode (cname = "htmlNodeStatus")]
+ public Status status (bool legacy);
+ }
+
+ [Compact]
+ [CCode (cname = "xmlDoc", cheader_filename = "libxml/HTMLtree.h,libxml/HTMLparser.h")]
+ public class Doc : Xml.Doc {
+ [CCode (cname = "htmlNewDoc")]
+ public Doc (string? uri = null, string? external_id = null);
+
+ [CCode (cname = "htmlNewNoDtD")]
+ public Doc.new_no_dtd (string? uri = null, string? external_id = null);
+
+ [CCode (cname = "htmlSAXParseDoc")]
+ public static Doc* sax_parse_doc (string cur, string? encoding, Xml.SAXHandler* sax, void* user_data = null);
+
+ [CCode (cname = "htmlSAXParseFile")]
+ public static Doc* sax_parse_file (string filename, string? encoding, Xml.SAXHandler* sax, void* user_data = null);
+
+ [CCode (cname = "htmlParseFile")]
+ public static Doc* parse_file (string filename, string? encoding);
+
+ [CCode (cname = "htmlReadDoc")]
+ public static Doc* read_doc (string cur, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlReadMemory")]
+ public static Doc* read_memory ([CCode (array_length = false)] char[] buffer, int size, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlReadFd")]
+ public static Doc* read_fd (int fd, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlReadIO")]
+ public static Doc* read_io (Xml.InputReadCallback ioread, Xml.InputCloseCallback ioclose, void* ioctx, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlGetMetaEncoding")]
+ public string get_meta_encoding ();
+
+ [CCode (cname = "htmlSetMetaEncoding")]
+ public int set_meta_encoding (string encoding);
+
+ [CCode (cname = "htmlDocDumpMemory")]
+ public void dump_memory (out string mem, out int len = null);
+
+ [CCode (cname = "htmlDocDumpMemoryFormat")]
+ public void dump_memory_format (out string mem, out int len = null, bool format = true);
+
+ [CCode (cname = "htmlDocDump", instance_pos = -1)]
+ public int dump (GLib.FileStream f);
+
+ [CCode (cname = "htmlSaveFile", instance_pos = -1)]
+ public int save_file (string filename);
+
+ [CCode (cname = "htmlNodeDumpFile", instance_pos = 1.1)]
+ public int node_dump_file (GLib.FileStream file, Xml.Node* node);
+
+ [CCode (cname = "htmlNodeDumpFileFormat", instance_pos = 1.1)]
+ public int node_dump_file_format (GLib.FileStream file, string enc = "UTF-8", bool format = true);
+
+ [CCode (cname = "htmlSaveFileEnc", instance_pos = 1.1)]
+ public int save_file_enc (string filename, string enc = "UTF-8");
+
+ [CCode (cname = "htmlSaveFileFormat", instance_pos = 1.1)]
+ public int save_file_format (string filename, string enc = "UTF-8", bool format = true);
+
+ [CCode (cname = "htmlIsAutoClosed")]
+ public bool is_auto_closed (Node* elem);
+
+ [CCode (cname = "htmlAutoCloseTag")]
+ public bool auto_close_tag (string name, Node* elem);
+ }
+
+ [Compact]
+ [CCode (cname = "htmlElemDesc", cheader_filename = "libxml/HTMLparser.h")]
+ public class ElemDesc {
+ public weak string name;
+ [CCode (cname = "startTag")]
+ public bool start_tag;
+ [CCode (cname = "endTag")]
+ public bool end_tag;
+ [CCode (cname = "saveEndTag")]
+ public bool save_end_tag;
+ public bool empty;
+ public bool depr;
+ public char dtd;
+ public bool isinline;
+ public weak string desc;
+ public weak string[] subelts;
+ public weak string defaultsubelt;
+ public weak string[] attrs_opt;
+ public weak string[] attrs_depr;
+ public weak string[] attrs_req;
+
+ [CCode (cname = "htmlTagLookup")]
+ public static ElemDesc* tag_lookup (string tag);
+
+ [CCode (cname = "htmlAttrAllowed")]
+ public Status attr_allowed (string attr, bool legacy);
+
+ [CCode (cname = "htmlElementAllowedHere")]
+ public bool allowed_here (string elt);
+
+ [CCode (cname = "htmlElementAllowedHereDesc")]
+ public bool allowed_here_desc (ElemDesc* child);
+
+ [CCode (cname = "htmlElementStatusHere")]
+ public Status status_here (ElemDesc* child);
+
+ [Ccode (cname = "htmlDefaultSubelement")]
+ public unowned string default_subelement ();
+
+ [Ccode (cname = "htmlRequiredAttrs")]
+ public unowned string[] required_attrs ();
+ }
+
+ [Compact]
+ [CCode (cname = "htmlEntityDesc", cheader_filename = "libxml/HTMLParser.h")]
+ public class EntityDesc
+ {
+ public uint value;
+ public weak string name;
+ public weak string desc;
+
+ [CCode (cname = "htmlEntityDesc")]
+ public static EntityDesc* lookup (string name);
+
+ [CCode (cname = "htmlEntityValueDesc")]
+ public static EntityDesc* value_lookup (uint value);
+ }
+
+ [Compact]
+ [CCode (cname = "htmlParserCtxt", free_function = "htmlFreeParserCtxt", cheader_filename = "libxml/HTMLparser.h")]
+ public class ParserCtxt : Xml.ParserCtxt {
+ [CCode (cname = "htmlNewParserCtxt")]
+ public ParserCtxt ();
+
+ [CCode (cname = "htmlCreateMemoryParserCtxt")]
+ public ParserCtxt.create_memory ([CCode (array_length = false)] char[] buffer, int size);
+
+ [CCode (cname = "htmlCreatePushParserCtxt")]
+ public ParserCtxt.create_push (Xml.SAXHandler* sax, void* user_data, [CCode (array_length = false)] char[] data, int len, string? filename = null, Xml.CharEncoding enc = Xml.CharEncoding.NONE);
+
+ [CCode (cname = "htmlParseChunk")]
+ public int parse_chunk ([CCode (array_length = false)] char[] data, int size, bool terminate);
+
+ [CCode (cname = "htmlParseEntityRef")]
+ public EntityDesc* parse_entity_ref (out string entity_name);
+
+ [CCode (cname = "htmlParseCharRef")]
+ public int parse_char_ref ();
+
+ [CCode (cname = "htmlParseElement")]
+ public void parse_element ();
+
+ [CCode (cname = "htmlParseDocument")]
+ public int parse_document ();
+
+ [CCode (cname = "htmlCtxtReset")]
+ public void reset ();
+
+ [CCode (cname = "htmlCtxtUseOptions")]
+ public int use_options (int options);
+
+ [CCode (cname = "htmlCtxtReadDoc")]
+ public Doc* read_doc (string cur, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlCtxtReadFile")]
+ public Doc* read_file (string filename, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlCtxtReadMemory")]
+ public Doc* read_memory ([CCode (array_length = false)] char[] buffer, int size, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlCtxtReadFd")]
+ public Doc* read_fd (int fd, string url, string? encoding = null, int options = 0);
+
+ [CCode (cname = "htmlCtxtReadIO")]
+ public Doc* read_io (Xml.InputReadCallback ioread, Xml.InputCloseCallback ioclose, void* ioctx, string url, string? encoding = null, int options = 0);
+ }
+}
diff --git a/wixl/Makefile.am b/wixl/Makefile.am
new file mode 100644
index 0000000..8e1bfa7
--- /dev/null
+++ b/wixl/Makefile.am
@@ -0,0 +1,46 @@
+NULL =
+bin_PROGRAMS = wixl
+
+AM_CFLAGS = -w
+
+# --vapidir paths are relative to the source directory!
+
+AM_VALAFLAGS = \
+ -H wixl.h --use-header \
+ --vapidir=. \
+ --vapidir=../vapi \
+ --vapidir=$(abs_top_builddir)/libmsi \
+ --pkg config \
+ --enable-experimental \
+ --pkg gio-2.0 \
+ --pkg libmsi-1.0 \
+ --pkg libgcab-1.0 \
+ --pkg libxml-2.0 \
+ --pkg posix \
+ $(NULL)
+
+wixl_SOURCES = \
+ builder.vala \
+ msi.vala \
+ preprocessor.vala \
+ util.vala \
+ wix.vala \
+ wixl.vala \
+ $(NULL)
+
+AM_CPPFLAGS = \
+ -include config.h \
+ -I $(top_srcdir)/include \
+ $(WIXL_CFLAGS) \
+ -DG_LOG_DOMAIN=\""wixl"\" \
+ -DLOCALEDIR=\""$(localedir)"\" \
+ -DPKGDATADIR=\""$(pkgdatadir)"\" \
+ -DPKGLIBDIR=\""$(pkglibdir)"\" \
+ $(NULL)
+
+wixl_LDADD = \
+ $(WIXL_LIBS) \
+ ../libmsi/libmsi.la \
+ $(NULL)
+
+wixl_DEPENDENCIES = ../libmsi/libmsi.la
diff --git a/wixl/builder.vala b/wixl/builder.vala
new file mode 100644
index 0000000..80c2ff6
--- /dev/null
+++ b/wixl/builder.vala
@@ -0,0 +1,590 @@
+namespace Wixl {
+
+ class WixBuilder: WixNodeVisitor {
+
+ public WixBuilder () {
+ add_path (".");
+ }
+
+ WixRoot root;
+ MsiDatabase db;
+ HashTable<string, string> variables;
+
+ construct {
+ variables = new HashTable<string, string> (str_hash, str_equal);
+ }
+
+ public void define_variable (string name, string value) {
+ variables.insert (name, value);
+ }
+
+ List<File> path;
+ public void add_path (string p) {
+ var file = File.new_for_path (p);
+ path.append (file);
+ }
+
+ List<WixRoot> roots;
+ public void load_doc (Xml.Doc doc) throws GLib.Error {
+ for (var child = doc.children; child != null; child = child->next) {
+ switch (child->type) {
+ case Xml.ElementType.ELEMENT_NODE:
+ if (child->name != "Wix")
+ warning ("unhandled node %s", child->name);
+ var root = new WixRoot ();
+ root.load (child);
+ roots.append (root);
+ break;
+ }
+ }
+ }
+
+ public void load_file (File file, bool preproc_only = false) throws GLib.Error {
+ string data;
+ FileUtils.get_contents (file.get_path (), out data);
+
+ var p = new Preprocessor (variables);
+ var doc = p.preprocess (data, file);
+ if (preproc_only) {
+ doc.dump_format (FileStream.fdopen (1, "w"));
+ return;
+ }
+
+ load_doc (doc);
+ }
+
+ public G? find_element<G> (string Id) {
+ foreach (var r in roots) {
+ var e = r.find_element<G> (Id);
+ if (e != null)
+ return e;
+ }
+
+ return null;
+ }
+
+ public G[] get_elements<G> () {
+ G[] elems = {};
+ foreach (var r in roots)
+ elems = r.add_elements<G> (elems);
+
+ return elems;
+ }
+
+ delegate void AddSequence (string action, int sequence) throws GLib.Error;
+
+ private void sequence_actions () throws GLib.Error {
+ MsiTableSequence? table = null;
+ AddSequence add = (action, sequence) => {
+ var seq = table.get_action (action);
+ seq.sequence = sequence;
+ };
+
+ // AdminExecuteSequence
+ table = db.table_admin_execute_sequence;
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("InstallValidate", 1400);
+ add ("InstallInitialize", 1500);
+ add ("InstallAdminPackage", 3900);
+ add ("InstallFiles", 4000);
+ add ("InstallFinalize", 6600);
+ table.add_sorted_actions ();
+
+ // AdminUISequence
+ table = db.table_admin_ui_sequence;
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("ExecuteAction", 1300);
+ table.add_sorted_actions ();
+
+ table = db.table_advt_execute_sequence;
+ add ("CostInitialize", 800);
+ add ("CostFinalize", 1000);
+ add ("InstallValidate", 1400);
+ add ("InstallInitialize", 1500);
+ if (db.table_shortcut.records.length () > 0)
+ add ("CreateShortcuts", 4500);
+ add ("PublishFeatures", 6300);
+ add ("PublishProduct", 6400);
+ add ("InstallFinalize", 6600);
+ table.add_sorted_actions ();
+
+ // InstallExecuteSequence
+ table = db.table_install_execute_sequence;
+ if (db.table_upgrade.records.length () > 0)
+ add ("FindRelatedProducts", 25);
+ if (db.table_launch_condition.records.length () > 0)
+ add ("LaunchConditions", 100);
+ add ("ValidateProductID", 700);
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("InstallValidate", 1400);
+ add ("InstallInitialize", 1500);
+ add ("ProcessComponents", 1600);
+ add ("UnpublishFeatures", 1800);
+ if (db.table_registry.records.length () > 0)
+ add ("RemoveRegistryValues", 2600);
+ if (db.table_shortcut.records.length () > 0)
+ add ("RemoveShortcuts", 3200);
+ if (db.table_file.records.length () > 0 ||
+ db.table_remove_file.records.length () > 0)
+ add ("RemoveFiles", 3500);
+ if (db.table_file.records.length () > 0)
+ add ("InstallFiles", 4000);
+ if (db.table_shortcut.records.length () > 0)
+ add ("CreateShortcuts", 4500);
+ if (db.table_registry.records.length () > 0)
+ add ("WriteRegistryValues", 5000);
+ add ("RegisterUser", 6000);
+ add ("RegisterProduct", 6100);
+ add ("PublishFeatures", 6300);
+ add ("PublishProduct", 6400);
+ add ("InstallFinalize", 6600);
+ table.add_sorted_actions ();
+
+ table = db.table_install_ui_sequence;
+ if (db.table_upgrade.records.length () > 0)
+ add ("FindRelatedProducts", 25);
+ if (db.table_launch_condition.records.length () > 0)
+ add ("LaunchConditions", 100);
+ add ("ValidateProductID", 700);
+ add ("CostInitialize", 800);
+ add ("FileCost", 900);
+ add ("CostFinalize", 1000);
+ add ("ExecuteAction", 1300);
+ table.add_sorted_actions ();
+ }
+
+ private void build_cabinet () throws GLib.Error {
+ var sequence = 0;
+ var medias = get_elements<WixMedia> ();
+ var files = get_elements<WixFile> ();
+
+ foreach (var m in medias) {
+ var folder = new GCab.Folder (GCab.Compression.MSZIP);
+
+ foreach (var f in files) {
+ if (f.DiskId != m.Id)
+ continue;
+
+ folder.add_file (new GCab.File.with_file (f.Id, f.file), false);
+ var rec = f.record;
+ sequence += 1;
+ MsiTableFile.set_sequence (rec, sequence);
+ }
+
+ var cab = new GCab.Cabinet ();
+ cab.add_folder (folder);
+ var output = new MemoryOutputStream (null, realloc, free);
+ cab.write (output, null, null, null);
+ var input = new MemoryInputStream.from_data (output.get_data ()[0:output.data_size], null);
+ if (parse_yesno (m.EmbedCab))
+ db.table_streams.add (m.Cabinet, input, output.data_size);
+
+ db.table_media.set_last_sequence (m.record, sequence);
+ }
+ }
+
+ private void shortcut_target () throws GLib.Error {
+ var shortcuts = get_elements<WixShortcut> ();
+
+ foreach (var sc in shortcuts) {
+ var component = sc.get_component ();
+ var feature = component.in_feature.first ().data;
+ MsiTableShortcut.set_target (sc.record, feature.Id);
+ }
+ }
+
+ string[] secureProperties;
+
+ public void property_update () throws GLib.Error {
+ if (secureProperties.length != 0) {
+ var prop = string.joinv (";", secureProperties);
+ db.table_property.add ("SecureCustomProperties", prop);
+ }
+ }
+
+ public MsiDatabase build () throws GLib.Error {
+ db = new MsiDatabase ();
+
+ foreach (var r in roots) {
+ root = r;
+ root.accept (this);
+ }
+ root = null;
+
+ property_update ();
+ shortcut_target ();
+ sequence_actions ();
+ build_cabinet ();
+
+ return db;
+ }
+
+ public override void visit_product (WixProduct product) throws GLib.Error {
+ if (product.Codepage != null)
+ db.info.set_codepage (int.parse (product.Codepage));
+
+ if (product.Name != null)
+ db.info.set_subject (product.Name);
+
+ db.info.set_author (product.Manufacturer);
+
+ db.table_property.add ("Manufacturer", product.Manufacturer);
+ db.table_property.add ("ProductLanguage", product.Language);
+ db.table_property.add ("ProductCode", get_uuid (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_comments (package.Comments);
+
+ if (package.Description != null)
+ db.info.set_subject (package.Description);
+
+ if (package.Keywords != null)
+ db.info.set_keywords (package.Keywords);
+
+ if (package.InstallerVersion != null)
+ db.info.set_property (Libmsi.Property.VERSION, int.parse (package.InstallerVersion));
+
+ }
+
+ public override void visit_icon (WixIcon icon) throws GLib.Error {
+ FileInfo info;
+
+ icon.file = find_file (icon.SourceFile, out info);
+ db.table_icon.add (icon.Id, icon.file.get_path ());
+ }
+
+ public override void visit_property (WixProperty prop) throws GLib.Error {
+ db.table_property.add (prop.Id, prop.Value);
+ }
+
+ public override void visit_media (WixMedia media) throws GLib.Error {
+ var cabinet = media.Cabinet;
+
+ if (parse_yesno (media.EmbedCab))
+ cabinet = "#" + cabinet;
+
+ var rec = db.table_media.add (media.Id, media.DiskPrompt, cabinet);
+ media.record = rec;
+ }
+
+ public override void visit_directory (WixDirectory dir) throws GLib.Error {
+ var defaultdir = dir.Name ?? ".";
+
+ if (dir.parent.get_type () == typeof (WixProduct)) {
+ if (dir.Id != "TARGETDIR")
+ throw new Wixl.Error.FAILED ("Invalid root directory");
+ db.table_directory.add (dir.Id, null, defaultdir);
+ } else if (dir.parent.get_type () == typeof (WixDirectory)) {
+ var parent = dir.parent as WixDirectory;
+ db.table_directory.add (dir.Id, parent.Id, defaultdir);
+ } else
+ warning ("unhandled parent type %s", dir.parent.name);
+ }
+
+ [Flags]
+ enum ComponentAttribute {
+ LOCAL_ONLY = 0,
+ SOURCE_ONLY,
+ OPTIONAL,
+ REGISTRY_KEY_PATH,
+ SHARED_DLL_REF_COUNT,
+ PERMANENT,
+ ODBC_DATA_SOURCE,
+ TRANSITIVE,
+ NEVER_OVERWRITE,
+ 64BIT,
+ REGISTRY_REFLECTION,
+ UNINSTALL_ON_SUPERSEDENCE,
+ SHARED,
+ }
+
+ G? resolve<G> (WixElement element) throws GLib.Error {
+ if (element.get_type () == typeof (G))
+ return element;
+ else if (element is WixElementRef) {
+ var ref = element as WixElementRef<G>;
+ if (ref.ref_type != typeof (G))
+ return null;
+ if (ref.resolved != null)
+ return ref.resolved;
+ ref.resolved = find_element<G> (element.Id);
+ return ref.resolved;
+ }
+
+ throw new Wixl.Error.FAILED ("couldn't resolve %s", element.Id);
+ }
+
+ public override void visit_component (WixComponent comp) throws GLib.Error {
+ var attr = 0;
+
+ if (comp.key is WixRegistryValue)
+ attr |= ComponentAttribute.REGISTRY_KEY_PATH;
+
+ var parent = resolve<WixDirectory> (comp.parent);
+ db.table_component.add (comp.Id, add_braces (comp.Guid), parent.Id, attr,
+ comp.key != null ? comp.key.Id : null);
+
+ }
+
+ enum FeatureDisplay {
+ HIDDEN = 0,
+ EXPAND,
+ COLLAPSE
+ }
+ WixFeature? feature_root;
+ int feature_display;
+
+ public override void visit_feature (WixFeature feature, VisitState state) throws GLib.Error {
+ if (state == VisitState.ENTER && feature_root == null) {
+ feature_display = 0;
+ feature_root = feature;
+ } else if (state == VisitState.LEAVE && feature_root == feature) {
+ feature_root = null;
+ }
+
+ if (state != VisitState.ENTER)
+ return;
+
+ int display = FeatureDisplay.COLLAPSE;
+ if (feature.Display != null) {
+ try {
+ display = enum_from_string (typeof (FeatureDisplay), feature.Display);
+ } catch (GLib.Error error) {
+ display = int.parse (feature.Display);
+ if (display != 0)
+ feature_display = display;
+ }
+ }
+
+ switch (display) {
+ case FeatureDisplay.COLLAPSE:
+ display = feature_display = (feature_display | 1) + 1;
+ break;
+ case FeatureDisplay.EXPAND:
+ display = feature_display = (feature_display + 1) | 1;
+ break;
+ }
+
+ string? parent = (feature.parent is WixFeature) ? feature.parent.Id : null;
+
+ db.table_feature.add (feature.Id, display, int.parse (feature.Level), 0, parent, feature.Title, feature.Description, feature.ConfigurableDirectory);
+
+ }
+
+ public override void visit_component_ref (WixComponentRef ref) throws GLib.Error {
+ if (ref.parent is WixFeature) {
+ var feature = ref.parent as WixFeature;
+
+ var component = resolve<WixComponent> (@ref);
+ component.in_feature.append (feature);
+ db.table_feature_components.add (feature.Id, @ref.Id);
+ } else
+ warning ("unhandled parent type %s", @ref.parent.name);
+ }
+
+ enum RemoveFileInstallMode {
+ INSTALL = 1,
+ UNINSTALL,
+ BOTH
+ }
+
+ public override void visit_remove_folder (WixRemoveFolder rm) throws GLib.Error {
+ var on = enum_from_string (typeof (RemoveFileInstallMode), rm.On);
+ var comp = rm.parent as WixComponent;
+ var dir = comp.parent as WixDirectory;
+
+ db.table_remove_file.add (rm.Id, comp.Id, dir.Id, on);
+ }
+
+ void visit_key_element (WixKeyElement key) throws GLib.Error {
+ var component = key.parent as WixComponent;
+
+ if (component.key == null || parse_yesno (key.KeyPath))
+ component.key = key;
+ }
+
+ enum RegistryValueType {
+ STRING,
+ INTEGER,
+ BINARY,
+ EXPANDABLE,
+ MULTI_STRING
+ }
+
+ enum RegistryRoot {
+ HKCR,
+ HKCU,
+ HKLM,
+ HKU,
+ HKMU
+ }
+
+ public override void visit_registry_value (WixRegistryValue reg) throws GLib.Error {
+ var comp = reg.parent as WixComponent;
+ var value = reg.Value;
+ var t = enum_from_string (typeof (RegistryValueType), reg.Type);
+ var r = enum_from_string (typeof (RegistryRoot), reg.Root.down ());
+ if (reg.Id == null) {
+ reg.Id = generate_id ("reg", 4,
+ comp.Id,
+ reg.Root,
+ reg.Key != null ? reg.Key.down () : null,
+ reg.Name != null ? reg.Name.down () : null);
+ }
+
+ switch (t) {
+ case RegistryValueType.STRING:
+ value = value[0] == '#' ? "#" + value : value;
+ break;
+ }
+
+ db.table_registry.add (reg.Id, r, reg.Key, comp.Id);
+
+ visit_key_element (reg);
+ }
+
+ [Flags]
+ enum FileAttribute {
+ READ_ONLY = 1 << 0,
+ HIDDEN = 1 << 1,
+ SYSTEM = 1 << 2,
+ VITAL = 1 << 9,
+ CHECKSUM = 1 << 10,
+ PATCH_ADDED = 1 << 11,
+ NON_COMPRESSED = 1 << 12,
+ COMPRESSED = 1 << 13
+ }
+
+ File? find_file (string name, out FileInfo info) throws GLib.Error {
+ info = null;
+
+ foreach (var p in path) {
+ var file = p.get_child (name);
+ try {
+ info = file.query_info ("standard::*", 0, null);
+ if (info != null)
+ return file;
+ } catch (IOError error) {
+ if (error is IOError.NOT_FOUND)
+ continue;
+ throw error;
+ }
+ }
+
+ throw new Wixl.Error.FAILED ("Couldn't find file %s", name);
+ }
+
+ public override void visit_file (WixFile file) throws GLib.Error {
+ file.DiskId = file.DiskId ?? "1";
+ return_if_fail (file.DiskId == "1");
+
+ var name = file.Id;
+ if (file.Name != null)
+ name = file.Name;
+ else if (file.Source != null)
+ name = Path.get_basename (file.Source);
+
+ var comp = file.parent as WixComponent;
+ FileInfo info;
+ file.file = find_file (name, out info);
+ var attr = FileAttribute.VITAL;
+
+ var rec = db.table_file.add (file.Id, comp.Id, name, (int)info.get_size (), attr);
+ file.record = rec;
+
+ visit_key_element (file);
+ }
+
+ public override void visit_shortcut (WixShortcut shortcut) throws GLib.Error {
+ if (!parse_yesno (shortcut.Advertise))
+ throw new Wixl.Error.FIXME ("unimplemented");
+
+ var component = shortcut.get_component ();
+ var rec = db.table_shortcut.add (shortcut.Id, shortcut.Directory, shortcut.Name, component.Id);
+ shortcut.record = rec;
+
+ if (shortcut.Icon != null)
+ MsiTableShortcut.set_icon (rec, shortcut.Icon, int.parse (shortcut.IconIndex));
+ if (shortcut.WorkingDirectory != null)
+ MsiTableShortcut.set_working_dir (rec, shortcut.WorkingDirectory);
+ }
+
+ public override void visit_sequence (WixSequence sequence) throws GLib.Error {
+ }
+
+ public override void visit_condition (WixCondition condition) throws GLib.Error {
+ return_if_fail (condition.children.length () == 1);
+ var text = condition.children.first ().data as WixText;
+
+ db.table_launch_condition.add (text.Text, condition.Message);
+ }
+
+ [Flags]
+ enum UpgradeAttribute {
+ MIGRATE_FEATURES = 1 << 0,
+ ONLY_DETECT = 1 << 1,
+ IGNORE_REMOVE_FAILURE = 1 << 2,
+ VERSION_MIN_INCLUSIVE = 1 << 8,
+ VERSION_MAX_INCLUSIVE = 1 << 9,
+ LANGUAGES_EXCLUSIVE = 1 << 10
+ }
+
+ public override void visit_upgrade (WixUpgrade upgrade) throws GLib.Error {
+ }
+
+ public override void visit_upgrade_version (WixUpgradeVersion version) throws GLib.Error {
+ var upgrade = version.parent as WixUpgrade;
+ UpgradeAttribute attributes = 0;
+
+ if (parse_yesno (version.OnlyDetect))
+ attributes |= UpgradeAttribute.ONLY_DETECT;
+
+ if (parse_yesno (version.IncludeMinimum, true))
+ attributes |= UpgradeAttribute.VERSION_MIN_INCLUSIVE;
+
+ db.table_upgrade.add (get_uuid (upgrade.Id), version.Minimum, version.Maximum, attributes, version.Property);
+
+ secureProperties += version.Property;
+ }
+
+ public override void visit_action (WixAction action) throws GLib.Error {
+ var parent = action.parent as WixSequence;
+ var table = db.tables.lookup (parent.name) as MsiTableSequence;
+
+ var node = table.get_action (action.name);
+ warn_if_fail (node.action == null);
+ node.action = action;
+
+ if (action.After != null)
+ node.add_dep (table.get_action (action.After));
+
+ if (action.Before != null) {
+ var before = table.get_action (action.Before);
+ before.add_dep (node);
+ }
+ }
+
+ public override void visit_create_folder (WixCreateFolder folder) throws GLib.Error {
+ }
+
+ public override void visit_fragment (WixFragment fragment) throws GLib.Error {
+ }
+
+ public override void visit_directory_ref (WixDirectoryRef ref) throws GLib.Error {
+ }
+
+ public override void visit_text (WixText text) throws GLib.Error {
+ }
+ }
+
+} // Wixl
diff --git a/wixl/config.vapi b/wixl/config.vapi
new file mode 100644
index 0000000..96bf752
--- /dev/null
+++ b/wixl/config.vapi
@@ -0,0 +1,12 @@
+[CCode (prefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
+namespace Config
+{
+ public const string PACKAGE_NAME;
+ public const string PACKAGE_STRING;
+ public const string PACKAGE_VERSION;
+ public const string GETTEXT_PACKAGE;
+
+ public const string LOCALEDIR;
+ public const string PKGDATADIR;
+ public const string PKGLIBDIR;
+}
diff --git a/wixl/msi.vala b/wixl/msi.vala
new file mode 100644
index 0000000..b8700b0
--- /dev/null
+++ b/wixl/msi.vala
@@ -0,0 +1,642 @@
+namespace Wixl {
+
+ abstract class MsiTable: Object {
+ public class string name;
+ public List<Libmsi.Record> records;
+
+ public class string sql_create;
+ public class string sql_insert;
+
+ public virtual void create (Libmsi.Database db) throws GLib.Error {
+ var query = new Libmsi.Query (db, sql_create);
+ query.execute (null);
+
+ if (sql_insert == null)
+ return;
+
+ query = new Libmsi.Query (db, sql_insert);
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ class MsiTableIcon: MsiTable {
+ static construct {
+ name = "Icon";
+ sql_create = "CREATE TABLE `Icon` (`Name` CHAR(72) NOT NULL, `Data` OBJECT NOT NULL PRIMARY KEY `Name`)";
+ sql_insert = "INSERT INTO `Icon` (`Name`, `Data`) VALUES (?, ?)";
+ }
+
+ 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);
+ }
+ }
+
+ abstract class MsiTableSequence: MsiTable {
+ private 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);
+ }
+
+ protected class void set_sequence_table_name (string table) {
+ name = table;
+ sql_create = "CREATE TABLE `%s` (`Action` CHAR(72) NOT NULL, `Condition` CHAR(255), `Sequence` INT PRIMARY KEY `Action`)".printf (table);
+ sql_insert = "INSERT INTO `%s` (`Action`, `Sequence`) VALUES (?, ?)".printf (table);
+ }
+
+ public class Action {
+ public string name;
+ public int sequence = -1;
+ public WixAction? action;
+
+ public bool visited = false;
+ public bool incoming_deps = false;
+
+ // Use it as a set, so value is not refcounted please vala
+ public HashTable<Action, Action*> depends_on = new HashTable<Action, Action*> (direct_hash, direct_equal);
+
+ public void add_dep (Action a) {
+ depends_on.add (a);
+ a.incoming_deps = true;
+ }
+ }
+
+ HashTable<string, Action> actions = new HashTable<string, Action> (str_hash, str_equal);
+
+
+ void sort_topological_visit (Action action, ref List<Action> sorted) {
+ if (action.visited)
+ return;
+
+ action.visited = true;
+
+ Action dep;
+ var it = HashTableIter <Action, Action*> (action.depends_on);
+ while (it.next (null, out dep))
+ sort_topological_visit (dep, ref sorted);
+
+ sorted.append (action);
+ }
+
+ List<Action> sort_topological () {
+ List<Action> sorted = null;
+
+ Action action;
+ var it = HashTableIter <string, Action> (actions);
+ while (it.next (null, out action)) {
+ if (action.incoming_deps)
+ continue;
+ sort_topological_visit (action, ref sorted);
+ }
+
+ return sorted;
+ }
+
+ void add_implicit_deps () {
+ CompareFunc<Action> cmp = (a, b) => {
+ return a.sequence - b.sequence;
+ };
+ var list = actions.get_values ();
+ list.sort (cmp);
+
+ Action? prev = null;
+ foreach (var a in list) {
+ if (a.sequence == -1)
+ continue;
+ if (prev != null)
+ a.add_dep (prev);
+ prev = a;
+ }
+ }
+
+ public void add_sorted_actions () throws GLib.Error {
+ add_implicit_deps ();
+ var sorted = sort_topological ();
+
+ int sequence = 0;
+ foreach (var action in sorted) {
+ if (action.sequence == -1)
+ action.sequence = ++sequence;
+
+ sequence = action.sequence;
+ add (action.name, action.sequence);
+ }
+ }
+
+ public Action get_action (string name) {
+ var action = actions.lookup (name);
+ if (action != null)
+ return action;
+
+ action = new Action ();
+ actions.insert (name, action);
+ action.name = name;
+
+ return action;
+ }
+ }
+
+ class MsiTableAdminExecuteSequence: MsiTableSequence {
+ static construct {
+ set_sequence_table_name ("AdminExecuteSequence");
+ }
+ }
+
+ class MsiTableAdminUISequence: MsiTableSequence {
+ static construct {
+ set_sequence_table_name ("AdminUISequence");
+ }
+ }
+
+ class MsiTableAdvtExecuteSequence: MsiTableSequence {
+ static construct {
+ set_sequence_table_name ("AdvtExecuteSequence");
+ }
+ }
+
+ class MsiTableInstallExecuteSequence: MsiTableSequence {
+ static construct {
+ set_sequence_table_name ("InstallExecuteSequence");
+ }
+ }
+
+ class MsiTableInstallUISequence: MsiTableSequence {
+ static construct {
+ set_sequence_table_name ("InstallUISequence");
+ }
+ }
+
+ class MsiTableError: MsiTable {
+ static construct {
+ name = "Error";
+ sql_create = "CREATE TABLE `Error` (`Error` INT NOT NULL, `Message` CHAR(0) LOCALIZABLE PRIMARY KEY `Error`)";
+ }
+ }
+
+ class MsiTableFile: MsiTable {
+ static construct {
+ name = "File";
+ sql_create = "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`)";
+ sql_insert = "INSERT INTO `File` (`File`, `Component_`, `FileName`, `FileSize`, `Attributes`, `Sequence`) VALUES (?, ?, ?, ?, ?, ?)";
+ }
+
+ public Libmsi.Record add (string File, string Component, string FileName, int FileSize, int Attributes, int Sequence = 0) throws GLib.Error {
+ var rec = new Libmsi.Record (6);
+
+ if (!rec.set_string (1, File) ||
+ !rec.set_string (2, Component) ||
+ !rec.set_string (3, FileName) ||
+ !rec.set_int (4, FileSize) ||
+ !rec.set_int (5, Attributes) ||
+ !rec.set_int (6, Sequence))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+
+ return rec;
+ }
+
+ public static bool set_sequence (Libmsi.Record rec, int Sequence) {
+ return rec.set_int (6, Sequence);
+ }
+ }
+
+ class MsiTableMedia: MsiTable {
+ static construct {
+ name = "Media";
+ sql_create = "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`)";
+ sql_insert = "INSERT INTO `Media` (`DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`) VALUES (?, ?, ?, ?)";
+ }
+
+ public bool set_last_sequence (Libmsi.Record rec, int last_sequence) {
+ return rec.set_int (2, last_sequence);
+ }
+
+ public Libmsi.Record add (string DiskId, string? DiskPrompt, string Cabinet) throws GLib.Error {
+ var rec = new Libmsi.Record (4);
+
+ if (!rec.set_int (1, int.parse (DiskId)) ||
+ !rec.set_int (2, 0) ||
+ (DiskPrompt != null && !rec.set_string (3, DiskPrompt)) ||
+ !rec.set_string (4, Cabinet))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ return rec;
+ }
+ }
+
+ class MsiTableUpgrade: MsiTable {
+ static construct {
+ name = "Upgrade";
+ sql_create = "CREATE TABLE `Upgrade` (`UpgradeCode` CHAR(38) NOT NULL, `VersionMin` CHAR(20), `VersionMax` CHAR(20), `Language` CHAR(255), `Attributes` LONG NOT NULL, `Remove` CHAR(255), `ActionProperty` CHAR(72) NOT NULL PRIMARY KEY `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes`)";
+ sql_insert = "INSERT INTO `Upgrade` (`UpgradeCode`, `VersionMin`, `VersionMax`, `Attributes`, `ActionProperty`) VALUES (?, ?, ?, ?, ?)";
+ }
+
+ public void add (string UpgradeCode, string VersionMin, string? VersionMax, int Attributes, string ActionProperty) throws GLib.Error {
+ var rec = new Libmsi.Record (5);
+
+ if (!rec.set_string (1, UpgradeCode) ||
+ !rec.set_string (2, VersionMin) ||
+ (VersionMax != null && !rec.set_string (3, VersionMax)) ||
+ !rec.set_int (4, Attributes) ||
+ !rec.set_string (5, ActionProperty))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableLaunchCondition: MsiTable {
+ static construct {
+ name = "LaunchCondition";
+ sql_create = "CREATE TABLE `LaunchCondition` (`Condition` CHAR(255) NOT NULL, `Description` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `Condition`)";
+ sql_insert = "INSERT INTO `LaunchCondition` (`Condition`, `Description`) VALUES (?, ?)";
+ }
+
+ public void add (string condition, string description) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+
+ if (!rec.set_string (1, condition) ||
+ !rec.set_string (2, description))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableProperty: MsiTable {
+ static construct {
+ name = "Property";
+ sql_create = "CREATE TABLE `Property` (`Property` CHAR(72) NOT NULL, `Value` CHAR(0) NOT NULL LOCALIZABLE PRIMARY KEY `Property`)";
+ sql_insert = "INSERT INTO `Property` (`Property`, `Value`) VALUES (?, ?)";
+ }
+
+ 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);
+ }
+ }
+
+ class MsiTableDirectory: MsiTable {
+ static construct {
+ name = "Directory";
+ sql_create = "CREATE TABLE `Directory` (`Directory` CHAR(72) NOT NULL, `Directory_Parent` CHAR(72), `DefaultDir` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `Directory`)";
+ sql_insert = "INSERT INTO `Directory` (`Directory`, `Directory_Parent`, `DefaultDir`) VALUES (?, ?, ?)";
+ }
+
+ public void add (string Directory, string? Parent, string DefaultDir) throws GLib.Error {
+ var rec = new Libmsi.Record (3);
+ if (!rec.set_string (1, Directory) ||
+ !rec.set_string (2, Parent) ||
+ !rec.set_string (3, DefaultDir))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableComponent: MsiTable {
+ static construct {
+ name = "Component";
+ sql_create = "CREATE TABLE `Component` (`Component` CHAR(72) NOT NULL, `ComponentId` CHAR(38), `Directory_` CHAR(72) NOT NULL, `Attributes` INT NOT NULL, `Condition` CHAR(255), `KeyPath` CHAR(72) PRIMARY KEY `Component`)";
+ sql_insert = "INSERT INTO `Component` (`Component`, `ComponentId`, `Directory_`, `Attributes`, `KeyPath`) VALUES (?, ?, ?, ?, ?)";
+ }
+
+ public void add (string Component, string ComponentId, string Directory, int Attributes, string? KeyPath = null) throws GLib.Error {
+ var rec = new Libmsi.Record (5);
+ if (!rec.set_string (1, Component) ||
+ !rec.set_string (2, ComponentId) ||
+ !rec.set_string (3, Directory) ||
+ !rec.set_int (4, Attributes) ||
+ !rec.set_string (5, KeyPath))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableFeatureComponents: MsiTable {
+ static construct {
+ name = "FeatureComponents";
+ sql_create = "CREATE TABLE `FeatureComponents` (`Feature_` CHAR(38) NOT NULL, `Component_` CHAR(72) NOT NULL PRIMARY KEY `Feature_`, `Component_`)";
+ sql_insert = "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES (?, ?)";
+ }
+
+ public void add (string Feature, string Component) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+ if (!rec.set_string (1, Feature) ||
+ !rec.set_string (2, Component))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableRegistry: MsiTable {
+ static construct {
+ name = "Registry";
+ sql_create = "CREATE TABLE `Registry` (`Registry` CHAR(72) NOT NULL, `Root` INT NOT NULL, `Key` CHAR(255) NOT NULL LOCALIZABLE, `Name` CHAR(255) LOCALIZABLE, `Value` CHAR(0) LOCALIZABLE, `Component_` CHAR(72) NOT NULL PRIMARY KEY `Registry`)";
+ sql_insert = "INSERT INTO `Registry` (`Registry`, `Root`, `Key`, `Component_`) VALUES (?, ?, ?, ?)";
+ }
+
+ public void add (string Registry, int Root, string Key, string Component) throws GLib.Error {
+ var rec = new Libmsi.Record (4);
+ if (!rec.set_string (1, Registry) ||
+ !rec.set_int (2, Root) ||
+ !rec.set_string (3, Key) ||
+ !rec.set_string (4, Component))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableShortcut: MsiTable {
+ static construct {
+ name = "Shortcut";
+ sql_create = "CREATE TABLE `Shortcut` (`Shortcut` CHAR(72) NOT NULL, `Directory_` CHAR(72) NOT NULL, `Name` CHAR(128) NOT NULL LOCALIZABLE, `Component_` CHAR(72) NOT NULL, `Target` CHAR(72) NOT NULL, `Arguments` CHAR(255), `Description` CHAR(255) LOCALIZABLE, `Hotkey` INT, `Icon_` CHAR(72), `IconIndex` INT, `ShowCmd` INT, `WkDir` CHAR(72), `DisplayResourceDLL` CHAR(255), `DisplayResourceId` INT, `DescriptionResourceDLL` CHAR(255), `DescriptionResourceId` INT PRIMARY KEY `Shortcut`)";
+ sql_insert = "INSERT INTO `Shortcut` (`Shortcut`, `Directory_`, `Name`, `Component_`, `Target`, `Icon_`, `IconIndex`, `WkDir`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
+ }
+
+ public Libmsi.Record add (string Shortcut, string Directory, string Name, string Component) throws GLib.Error {
+ var rec = new Libmsi.Record (8);
+
+ if (!rec.set_string (1, Shortcut) ||
+ !rec.set_string (2, Directory) ||
+ !rec.set_string (3, Name) ||
+ !rec.set_string (4, Component))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+
+ return rec;
+ }
+
+ public static void set_target (Libmsi.Record rec, string Target) throws GLib.Error {
+ if (!rec.set_string (5, Target))
+ throw new Wixl.Error.FAILED ("failed to set record");
+ }
+
+ public static void set_icon (Libmsi.Record rec, string Icon, int IconIndex) throws GLib.Error {
+ if (!rec.set_string (6, Icon) ||
+ !rec.set_int (7, IconIndex))
+ throw new Wixl.Error.FAILED ("failed to set record");
+ }
+
+ public static void set_working_dir (Libmsi.Record rec, string WkDir) throws GLib.Error {
+ if (!rec.set_string (8, WkDir))
+ throw new Wixl.Error.FAILED ("failed to set record");
+ }
+ }
+
+ class MsiTableRemoveFile: MsiTable {
+ static construct {
+ name = "RemoveFile";
+ sql_create = "CREATE TABLE `RemoveFile` (`FileKey` CHAR(72) NOT NULL, `Component_` CHAR(72) NOT NULL, `FileName` CHAR(255) LOCALIZABLE, `DirProperty` CHAR(72) NOT NULL, `InstallMode` INT NOT NULL PRIMARY KEY `FileKey`)";
+ sql_insert = "INSERT INTO `RemoveFile` (`FileKey`, `Component_`, `DirProperty`, `InstallMode`) VALUES (?, ?, ?, ?)";
+ }
+
+ public void add (string FileKey, string Component, string DirProperty, int InstallMode) throws GLib.Error {
+ var rec = new Libmsi.Record (4);
+ if (!rec.set_string (1, FileKey) ||
+ !rec.set_string (2, Component) ||
+ !rec.set_string (3, DirProperty) ||
+ !rec.set_int (4, InstallMode))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableFeature: MsiTable {
+ static construct {
+ name = "Feature";
+ sql_create = "CREATE TABLE `Feature` (`Feature` CHAR(38) NOT NULL, `Feature_Parent` CHAR(38), `Title` CHAR(64) LOCALIZABLE, `Description` CHAR(255) LOCALIZABLE, `Display` INT, `Level` INT NOT NULL, `Directory_` CHAR(72), `Attributes` INT NOT NULL PRIMARY KEY `Feature`)";
+ sql_insert = "INSERT INTO `Feature` (`Feature`, `Display`, `Level`, `Attributes`, `Feature_Parent`, `Title`, `Description`, `Directory_`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
+ }
+
+ public void add (string Feature, int Display, int Level, int Attributes, string? Parent = null, string? Title = null, string? Description = null, string? ConfigurableDirectory = null) throws GLib.Error {
+ var rec = new Libmsi.Record (8);
+ if (!rec.set_string (1, Feature) ||
+ !rec.set_int (2, Display) ||
+ !rec.set_int (3, Level) ||
+ !rec.set_int (4, Attributes) ||
+ (Parent != null && !rec.set_string (5, Parent)) ||
+ (Title != null && !rec.set_string (6, Title)) ||
+ (Description != null && !rec.set_string (7, Description)) ||
+ (ConfigurableDirectory != null && !rec.set_string (8, ConfigurableDirectory)))
+ throw new Wixl.Error.FAILED ("failed to add record");
+
+ records.append (rec);
+ }
+ }
+
+ class MsiTableValidation: MsiTable {
+ static construct {
+ name = "_Validation";
+ }
+
+ public override void create (Libmsi.Database db) throws GLib.Error {
+ }
+ }
+
+ class MsiTableStreams: MsiTable {
+ static construct {
+ name = "_Streams";
+ }
+
+ public void add (string name, GLib.InputStream input, size_t count) throws GLib.Error {
+ var rec = new Libmsi.Record (2);
+ if (!rec.set_string (1, name) ||
+ !rec.set_stream (2, input, count))
+ 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, "INSERT INTO `_Streams` (`Name`, `Data`) VALUES (?, ?)");
+ foreach (var r in records)
+ query.execute (r);
+ }
+ }
+
+ 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;
+ public MsiTableMedia table_media;
+ public MsiTableDirectory table_directory;
+ public MsiTableComponent table_component;
+ public MsiTableFeature table_feature;
+ public MsiTableFeatureComponents table_feature_components;
+ public MsiTableRemoveFile table_remove_file;
+ public MsiTableRegistry table_registry;
+ public MsiTableFile table_file;
+ public MsiTableAdminExecuteSequence table_admin_execute_sequence;
+ public MsiTableAdminUISequence table_admin_ui_sequence;
+ public MsiTableAdvtExecuteSequence table_advt_execute_sequence;
+ public MsiTableInstallExecuteSequence table_install_execute_sequence;
+ public MsiTableInstallUISequence table_install_ui_sequence;
+ public MsiTableStreams table_streams;
+ public MsiTableShortcut table_shortcut;
+ public MsiTableUpgrade table_upgrade;
+ public MsiTableLaunchCondition table_launch_condition;
+
+ public 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.KEYWORDS, "Installer");
+ info.set_property (Libmsi.Property.CODEPAGE, 1252);
+ info.set_property (Libmsi.Property.UUID, get_uuid ("*"));
+ 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 ();
+ table_media = new MsiTableMedia ();
+ table_directory = new MsiTableDirectory ();
+ table_component = new MsiTableComponent ();
+ table_feature = new MsiTableFeature ();
+ table_feature_components = new MsiTableFeatureComponents ();
+ table_remove_file = new MsiTableRemoveFile ();
+ table_registry = new MsiTableRegistry ();
+ table_file = new MsiTableFile ();
+ table_admin_execute_sequence = new MsiTableAdminExecuteSequence ();
+ table_admin_ui_sequence = new MsiTableAdminUISequence ();
+ table_advt_execute_sequence = new MsiTableAdvtExecuteSequence ();
+ table_install_execute_sequence = new MsiTableInstallExecuteSequence ();
+ table_install_ui_sequence = new MsiTableInstallUISequence ();
+ table_streams = new MsiTableStreams ();
+ table_shortcut = new MsiTableShortcut ();
+ table_upgrade = new MsiTableUpgrade ();
+ table_launch_condition = new MsiTableLaunchCondition ();
+
+ foreach (var t in new MsiTable[] {
+ table_admin_execute_sequence,
+ table_admin_ui_sequence,
+ table_advt_execute_sequence,
+ table_install_execute_sequence,
+ table_install_ui_sequence,
+ table_directory,
+ table_media,
+ table_property,
+ table_icon,
+ table_component,
+ table_feature,
+ table_feature_components,
+ table_remove_file,
+ table_registry,
+ table_file,
+ table_streams,
+ table_shortcut,
+ table_upgrade,
+ table_launch_condition,
+ new MsiTableError (),
+ new MsiTableValidation ()
+ }) {
+ 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/wixl/preprocessor.vala b/wixl/preprocessor.vala
new file mode 100644
index 0000000..feafb3b
--- /dev/null
+++ b/wixl/preprocessor.vala
@@ -0,0 +1,131 @@
+namespace Wixl {
+
+ class Preprocessor: Object {
+
+ HashTable<string, string> globals;
+ HashTable<string, string> variables;
+ construct {
+ variables = new HashTable<string, string> (str_hash, str_equal);
+ }
+
+ public Preprocessor (HashTable<string, string> globals) {
+ this.globals = globals;
+ }
+
+ public void define_variable (string name, string value) {
+ variables.insert (name, value);
+ }
+
+ public string? lookup_variable (string name) {
+ return variables.lookup (name) ?? globals.lookup (name);
+ }
+
+ public string eval_variable (string str, File? file) throws GLib.Error {
+ var var = str.split (".", 2);
+ if (var.length != 2)
+ throw new Wixl.Error.FAILED ("invalid variable %s", str);
+
+ switch (var[0]) {
+ case "var":
+ var val = lookup_variable (var[1]);
+ if (val == null)
+ throw new Wixl.Error.FAILED ("Undefined variable %s", var[1]);
+ return val;
+ case "env":
+ return Environment.get_variable (var[1]);
+ case "sys":
+ switch (var[1]) {
+ case "CURRENTDIR":
+ return Environment.get_current_dir ();
+ case "SOURCEFILEDIR":
+ return file.get_basename ();
+ case "SOURCEFILEPATH":
+ return file.get_path ();
+ }
+ break;
+ }
+
+ throw new Wixl.Error.FIXME ("unhandled variable type %s", str);
+ }
+
+ public string eval (string str, File? file) throws GLib.Error {
+ var result = "";
+ int end = 0;
+ int pos = 0;
+
+ while ((pos = str.index_of ("$", end)) != -1) {
+ if (end < pos)
+ result += str[end:pos];
+ end = pos + 1;
+ var remainder = str[end:str.length];
+ if (remainder.has_prefix ("$"))
+ result += "$";
+ else if (remainder.has_prefix ("(")) {
+ var closing = find_closing_paren (remainder);
+ if (closing == -1)
+ throw new Wixl.Error.FAILED ("no matching closing parenthesis");
+ var substring = remainder[1:closing];
+ if (substring.index_of ("(") != -1)
+ throw new Wixl.Error.FIXME ("unsupported function");
+ result += eval_variable (substring, file);
+ end += closing + 1;
+ }
+ }
+
+ return result + str[end:str.length];
+ }
+
+ public Xml.Doc preprocess (string data, File? file) throws GLib.Error {
+ Xml.Doc doc;
+ var writer = new Xml.TextWriter.doc (out doc);
+ var reader = new Xml.TextReader.for_doc (data, "");
+
+ writer.start_document ();
+ while (reader.read () > 0) {
+ switch (reader.node_type ()) {
+ case Xml.ReaderType.PROCESSING_INSTRUCTION:
+ switch (reader.const_local_name ()) {
+ case "define":
+ MatchInfo info;
+ var r = /^\s*(?P<name>.+?)\s*=\s*(?P<value>.+?)\s*$/;
+ if (r.match (reader.const_value (), 0, out info)) {
+ var name = remove_prefix ("var.", info.fetch_named ("name"));
+ var value = unquote (info.fetch_named ("value"));
+ define_variable (name, value);
+ } else
+ throw new Wixl.Error.FAILED ("invalid define");
+ break;
+ default:
+ warning ("unhandled preprocessor instruction %s", reader.const_local_name ());
+ break;
+ }
+ break;
+ case Xml.ReaderType.ELEMENT:
+ var empty = reader.is_empty_element () > 0;
+
+ writer.start_element (reader.const_name ());
+ while (reader.move_to_next_attribute () > 0) {
+ var value = eval (reader.const_value (), file);
+ writer.write_attribute (reader.const_name (), value);
+ }
+
+ if (empty)
+ writer.end_element ();
+ break;
+ case Xml.ReaderType.END_ELEMENT:
+ writer.end_element ();
+ break;
+ case Xml.ReaderType.TEXT:
+ writer.write_string (eval (reader.const_value(), file));
+ break;
+ case Xml.ReaderType.CDATA:
+ writer.write_cdata (eval (reader.const_value(), file));
+ break;
+ }
+ }
+ writer.end_document ();
+
+ return doc;
+ }
+ }
+} \ No newline at end of file
diff --git a/wixl/util.vala b/wixl/util.vala
new file mode 100644
index 0000000..11f1588
--- /dev/null
+++ b/wixl/util.vala
@@ -0,0 +1,139 @@
+namespace Wixl {
+
+ public errordomain Error {
+ FAILED,
+ FIXME,
+ }
+
+ namespace UUID {
+ [CCode (cname = "uuid_generate", cheader_filename = "uuid/uuid.h")]
+ internal extern static void generate ([CCode (array_length = false)] uchar[] uuid);
+ [CCode (cname = "uuid_unparse", cheader_filename = "uuid/uuid.h")]
+ internal extern static void unparse ([CCode (array_length = false)] uchar[] uuid,
+ [CCode (array_length = false)] uchar[] output);
+ }
+
+ string uuid_generate () {
+ var udn = new uchar[50];
+ var id = new uchar[16];
+
+ UUID.generate (id);
+ UUID.unparse (id, udn);
+
+ return (string) udn;
+ }
+
+ int enum_from_string (Type t, string str) throws GLib.Error {
+ var k = (EnumClass)t.class_ref ();
+ var v = k.get_value_by_nick (str);
+
+ if (v == null)
+ throw new Wixl.Error.FAILED ("Can't convert string to enum");
+ return v.value;
+ }
+
+ string add_braces (string str) {
+ if (str[0] == '{')
+ return str;
+
+ return "{" + str + "}";
+ }
+
+ string get_uuid (owned string uuid) throws GLib.Error {
+ if (uuid == "*")
+ uuid = uuid_generate ();
+ uuid = add_braces (uuid);
+ uuid = uuid.up ();
+ // FIXME: validate
+ return uuid;
+ }
+
+ long now () {
+ var tv = TimeVal ();
+ tv.get_current_time ();
+ return tv.tv_sec;
+ }
+
+ uint64 time_to_filetime (long t) {
+ return (t + 134774ULL * 86400ULL) * 10000000ULL;
+ }
+
+ string get_attribute_content (Xml.Attr *attr) {
+ if (attr->children == null)
+ return "";
+
+ return attr->children->content;
+ }
+
+ public string indent (string space, string text) {
+ var indented = "";
+
+ foreach (var l in text.split ("\n")) {
+ if (indented.length != 0)
+ indented += "\n";
+
+ if (l.length != 0)
+ indented += space + l;
+ }
+
+ return indented;
+ }
+
+ public string generate_id (string prefix, uint n, ...) {
+ var l = va_list ();
+ var args = new string[n];
+
+ for (var i = 0; n > 0; n--) {
+ string? val = l.arg ();
+ if (val == null)
+ continue;
+ args[i] = val; // FIXME: misc vala bug when +=
+ i += 1;
+ }
+ var data = string.joinv ("|", args);
+ var hash = Checksum.compute_for_string (ChecksumType.MD5, data);
+ var str = prefix + hash[0:32].up ();
+
+ return str;
+ }
+
+ bool parse_yesno (string? str, bool default = false) {
+ if (str == null)
+ return default;
+
+ return (str[0] == 'Y' || str[0] == 'y');
+ }
+
+ string unquote (string str) {
+ if ((str[0] == '\'' && str[str.length-1] == '\'') ||
+ (str[0] == '"' && str[str.length-1] == '"'))
+ return str[1:-1];
+
+ return str;
+ }
+
+ string remove_prefix (string prefix, string str) {
+ if (str.has_prefix (prefix))
+ return str[prefix.length:str.length];
+
+ return str;
+ }
+
+ int find_closing_paren (string str) {
+ return_val_if_fail (str[0] == '(', -1);
+
+ var open_count = 1;
+ var close_count = 0;
+ for (var pos = 1; pos < str.length; pos++) {
+ if (str[pos] == '(')
+ open_count++;
+ else if (str[pos] == ')') {
+ close_count++;
+ if (open_count == close_count)
+ return pos;
+ }
+ }
+
+ return -1;
+ }
+} // Wixl
diff --git a/wixl/wix.vala b/wixl/wix.vala
new file mode 100644
index 0000000..d3468c5
--- /dev/null
+++ b/wixl/wix.vala
@@ -0,0 +1,598 @@
+namespace Wixl {
+
+ public enum VisitState {
+ ENTER,
+ INFIX,
+ LEAVE
+ }
+
+ public abstract class WixNodeVisitor: 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 void visit_media (WixMedia media) throws GLib.Error;
+ public abstract void visit_directory (WixDirectory dir) throws GLib.Error;
+ public abstract void visit_component (WixComponent comp) throws GLib.Error;
+ public abstract void visit_feature (WixFeature feature, VisitState state) throws GLib.Error;
+ public abstract void visit_component_ref (WixComponentRef ref) throws GLib.Error;
+ public abstract void visit_remove_folder (WixRemoveFolder rm) throws GLib.Error;
+ public abstract void visit_registry_value (WixRegistryValue reg) throws GLib.Error;
+ public abstract void visit_file (WixFile reg) throws GLib.Error;
+ public abstract void visit_shortcut (WixShortcut shortcut) throws GLib.Error;
+ public abstract void visit_create_folder (WixCreateFolder folder) throws GLib.Error;
+ public abstract void visit_fragment (WixFragment fragment) throws GLib.Error;
+ public abstract void visit_directory_ref (WixDirectoryRef ref) throws GLib.Error;
+ public abstract void visit_sequence (WixSequence sequence) throws GLib.Error;
+ public abstract void visit_condition (WixCondition condition) throws GLib.Error;
+ public abstract void visit_upgrade (WixUpgrade upgrade) throws GLib.Error;
+ public abstract void visit_upgrade_version (WixUpgradeVersion version) throws GLib.Error;
+ public abstract void visit_action (WixAction action) throws GLib.Error;
+ public abstract void visit_text (WixText text) throws GLib.Error;
+ }
+
+ public abstract class WixNode: Object {
+ public WixElement? parent;
+
+ static construct {
+ Value.register_transform_func (typeof (WixNode), typeof (string), (ValueTransform)WixNode.value_to_string);
+ }
+
+ public abstract string to_string ();
+
+ public static void value_to_string (Value src, out Value dest) {
+ WixNode e = value_get_node (src);
+
+ dest = e.to_string ();
+ }
+
+ public static WixNode? value_get_node (Value value) {
+ if (! value.holds (typeof (WixNode)))
+ return null;
+
+ return (WixNode)value.get_object ();
+ }
+
+ public abstract void accept (WixNodeVisitor visitor) throws GLib.Error;
+ }
+
+ public class WixText: WixNode {
+ public string Text;
+
+ public WixText (string str) {
+ Text = str;
+ }
+
+ public override string to_string () {
+ return Text;
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_text (this);
+ }
+ }
+
+ public abstract class WixElement: WixNode {
+ public class string name;
+
+ public string Id { get; set; }
+ public List<WixNode> children;
+
+ // FIXME: would be nice if vala always initialize class member to null
+ // GObject copy class init so other class hashtable will be unrefed...??
+ protected class HashTable<string, Type> *child_types = null;
+ class construct {
+ child_types = new HashTable<string, Type> (str_hash, str_equal);
+ }
+
+ public class void add_child_types (HashTable<string, Type> table, Type[] child_types) {
+ foreach (var t in child_types) {
+ var n = ((WixElement) Object.new (t)).name;
+ table.insert (n, t);
+ }
+ }
+
+ public void add_child (WixNode e) {
+ e.parent = this;
+ children.append (e);
+ }
+
+ public G[] add_elements<G> (owned G[] a) {
+ // jeez, vala, took me a while to workaround generics & array issues..
+ var array = a;
+ var type = typeof (G);
+
+ if (this.get_type ().is_a (type))
+ array += this;
+
+ foreach (var c in children) {
+ if (c is WixElement)
+ array = (c as WixElement).add_elements<G> (array);
+ else if (c.get_type ().is_a (type))
+ array += c;
+ }
+
+ return array;
+ }
+
+ public G[] get_elements<G> () {
+ return add_elements<G> ({});
+ }
+
+ public G? find_element<G> (string Id) {
+ var type = typeof (G);
+ if (this.Id == Id && this.get_type () == type)
+ return this;
+
+ foreach (var c in children) {
+ if (c is WixElement) {
+ var e = (c as WixElement).find_element<G> (Id);
+ if (e != null)
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ 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));
+ }
+
+ for (var child = node->children; child != null; child = child->next) {
+ switch (child->type) {
+ case Xml.ElementType.COMMENT_NODE:
+ continue;
+ case Xml.ElementType.TEXT_NODE:
+ add_child (new WixText (child->content));
+ continue;
+ case Xml.ElementType.ELEMENT_NODE:
+ var t = child_types->lookup (child->name);
+ if (t != 0) {
+ var elem = Object.new (t) as WixElement;
+ elem.load (child);
+ add_child (elem);
+ continue;
+ }
+ break;
+ }
+ debug ("unhandled child %s node %s", name, child->name);
+ }
+ }
+
+ public override string to_string () {
+ var type = get_type ();
+ var klass = (ObjectClass)type.class_ref ();
+ var str = "<" + name;
+
+ var i = 0;
+ foreach (var p in klass.list_properties ()) {
+ if (!(ParamFlags.READABLE in p.flags))
+ continue;
+ var value = Value (p.value_type);
+ get_property (p.name, ref value);
+ var valstr = value.holds (typeof (string)) ?
+ (string)value : value.strdup_contents ();
+ if (valstr != null)
+ str += " " + p.name + "=\"" + valstr + "\"";
+ i += 1;
+ }
+
+ if (children.length () != 0) {
+ str += ">\n";
+
+ foreach (var child in children) {
+ str += child.to_string () + "\n";
+ }
+
+ return str + "</" + name + ">";
+ } else
+ return str + "/>";
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ foreach (var child in children)
+ child.accept (visitor);
+ }
+ }
+
+ public class WixFragment: WixElement {
+ static construct {
+ name = "Fragment";
+
+ add_child_types (child_types, {
+ typeof (WixDirectory),
+ typeof (WixDirectoryRef),
+ });
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_fragment (this);
+ }
+ }
+
+ public class WixProperty: WixElement {
+ static construct {
+ name = "Property";
+ }
+
+ public string Value { get; set; }
+
+ public override void accept (WixNodeVisitor 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 accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_package (this);
+ }
+ }
+
+ public class WixCreateFolder: WixElement {
+ static construct {
+ name = "CreateFolder";
+ }
+
+ public string Directory { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_create_folder (this);
+ }
+ }
+
+ public class WixIcon: WixElement {
+ static construct {
+ name = "Icon";
+ }
+
+ public string SourceFile { get; set; }
+
+ public File file;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_icon (this);
+ }
+ }
+
+ public class WixShortcut: WixElement {
+ static construct {
+ name = "Shortcut";
+ }
+
+ public string Directory { get; set; }
+ public string Name { get; set; }
+ public string IconIndex { get; set; }
+ public string WorkingDirectory { get; set; }
+ public string Icon { get; set; }
+ public string Advertise { get; set; }
+
+ public Libmsi.Record record;
+
+ public WixComponent? get_component () {
+ if (parent is WixFile || parent is WixCreateFolder)
+ return parent.parent as WixComponent;
+ else
+ return parent as WixComponent;
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_shortcut (this);
+ }
+ }
+
+ public abstract class WixKeyElement: WixElement {
+ public string KeyPath { get; set; }
+ }
+
+ public class WixFile: WixKeyElement {
+ static construct {
+ name = "File";
+
+ add_child_types (child_types, { typeof (WixShortcut) });
+ }
+
+ public string DiskId { get; set; }
+ public string Source { get; set; }
+ public string Name { get; set; }
+
+ public Libmsi.Record record;
+ public File file;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_file (this);
+ }
+ }
+
+ public class WixRegistryValue: WixKeyElement {
+ static construct {
+ name = "RegistryValue";
+ }
+
+ public string Root { get; set; }
+ public string Key { get; set; }
+ public string Type { get; set; }
+ public string Value { get; set; }
+ public string Name { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_registry_value (this);
+ }
+ }
+
+ public class WixRemoveFolder: WixElement {
+ static construct {
+ name = "RemoveFolder";
+ }
+
+ public string On { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_remove_folder (this);
+ }
+ }
+
+ public class WixFeature: WixElement {
+ static construct {
+ name = "Feature";
+
+ add_child_types (child_types, {
+ typeof (WixComponentRef),
+ typeof (WixFeature),
+ });
+ }
+
+ public string Level { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public string Display { get; set; }
+ public string ConfigurableDirectory { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_feature (this, VisitState.ENTER);
+ base.accept (visitor);
+ visitor.visit_feature (this, VisitState.LEAVE);
+ }
+ }
+
+ public class WixComponentRef: WixElementRef<WixComponent> {
+ static construct {
+ name = "ComponentRef";
+ ref_type = typeof (WixComponent);
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_component_ref (this);
+ }
+ }
+
+ public class WixCondition: WixElement {
+ static construct {
+ name = "Condition";
+ }
+
+ public string Message { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_condition (this);
+ }
+ }
+
+ public abstract class WixAction: WixElement {
+ public string After { get; set; }
+ public string Before { get; set; }
+ public string Overridable { get; set; }
+ public string Sequence { get; set; }
+ public string Suppress { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_action (this);
+ }
+ }
+
+ public class WixRemoveExistingProducts: WixAction {
+ static construct {
+ name = "RemoveExistingProducts";
+ }
+ }
+
+ public class WixSequence: WixElement {
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_sequence (this);
+ }
+ }
+
+ public class WixInstallExecuteSequence: WixSequence {
+ static construct {
+ name = "InstallExecuteSequence";
+
+ add_child_types (child_types, {
+ typeof (WixRemoveExistingProducts),
+ });
+ }
+ }
+
+ public class WixUpgrade: WixElement {
+ static construct {
+ name = "Upgrade";
+
+ add_child_types (child_types, {
+ typeof (WixUpgradeVersion),
+ });
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_upgrade (this);
+ }
+ }
+
+ public class WixUpgradeVersion: WixElement {
+ static construct {
+ name = "UpgradeVersion";
+ }
+
+ public string Minimum { get; set; }
+ public string Maximum { get; set; }
+ public string IncludeMinimum { get; set; }
+ public string IncludeMaximum { get; set; }
+ public string OnlyDetect { get; set; }
+ public string Property { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_upgrade_version (this);
+ }
+ }
+
+ public class WixProduct: WixElement {
+ static construct {
+ name = "Product";
+
+ add_child_types (child_types, {
+ typeof (WixCondition),
+ typeof (WixDirectory),
+ typeof (WixFeature),
+ typeof (WixIcon),
+ typeof (WixInstallExecuteSequence),
+ typeof (WixMedia),
+ typeof (WixPackage),
+ typeof (WixProperty),
+ typeof (WixUpgrade),
+ });
+ }
+
+ 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 accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_product (this);
+ }
+ }
+
+ public class WixMedia: WixElement {
+ static construct {
+ name = "Media";
+ }
+
+ public string Cabinet { get; set; }
+ public string EmbedCab { get; set; }
+ public string DiskPrompt { get; set; }
+
+ public Libmsi.Record record;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_media (this);
+ }
+ }
+
+ public class WixComponent: WixElement {
+ static construct {
+ name = "Component";
+
+ add_child_types (child_types, {
+ typeof (WixRemoveFolder),
+ typeof (WixRegistryValue),
+ typeof (WixFile)
+ });
+ }
+
+ public string Guid { get; set; }
+ public WixKeyElement? key;
+
+ public List<WixFeature> in_feature;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_component (this);
+ }
+ }
+
+ public class WixDirectory: WixElement {
+ static construct {
+ name = "Directory";
+
+ add_child_types (child_types, {
+ typeof (WixDirectory),
+ typeof (WixComponent),
+ });
+ }
+
+ public string Name { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_directory (this);
+ }
+ }
+
+ public class WixElementRef<G>: WixElement {
+ public class Type ref_type;
+ public G? resolved;
+
+ // protected WixElementRef () {
+ // // FIXME vala: class init/construct fails, construct fails...
+ // ref_type = typeof (G);
+ // }
+ }
+
+ public class WixDirectoryRef: WixElementRef<WixDirectory> {
+ static construct {
+ name = "DirectoryRef";
+ ref_type = typeof (WixDirectory);
+
+ add_child_types (child_types, {
+ typeof (WixDirectory),
+ typeof (WixComponent),
+ });
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_directory_ref (this);
+ }
+ }
+
+ class WixRoot: WixElement {
+ static construct {
+ name = "Wix";
+
+ add_child_types (child_types, {
+ typeof (WixProduct),
+ typeof (WixFragment),
+ });
+ }
+ }
+
+} // Wixl
diff --git a/wixl/wixl.vala b/wixl/wixl.vala
new file mode 100644
index 0000000..057749d
--- /dev/null
+++ b/wixl/wixl.vala
@@ -0,0 +1,92 @@
+using Posix;
+
+namespace Wixl {
+
+ static bool version;
+ static bool verbose;
+ static bool preproc;
+ static string output;
+ [CCode (array_length = false, array_null_terminated = true)]
+ static string[] files;
+ [CCode (array_length = false, array_null_terminated = true)]
+ static string[] defines;
+
+ private const OptionEntry[] options = {
+ { "version", 0, 0, OptionArg.NONE, ref version, N_("Display version number"), null },
+ { "verbose", 'v', 0, OptionArg.NONE, ref verbose, N_("Verbose output"), null },
+ { "output", 'o', 0, OptionArg.FILENAME, ref output, N_("Output file"), null },
+ { "define", 'D', 0, OptionArg.STRING_ARRAY, ref defines, N_("Define variable"), null },
+ { "only-preproc", 'E', 0, OptionArg.NONE, ref preproc, N_("Stop after the preprocessing stage"), null },
+ { "", 0, 0, OptionArg.FILENAME_ARRAY, ref files, null, N_("INPUT_FILE...") },
+ { null }
+ };
+
+ 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 (Config.PACKAGE_NAME);
+
+ var parameter_string = _("- a msi building 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));
+ exit (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);
+ }
+
+ if (output == null && !preproc) {
+ GLib.stderr.printf (_("Please specify the output file.\n"));
+ exit (1);
+ }
+
+ try {
+ var builder = new WixBuilder ();
+
+ foreach (var d in defines) {
+ var def = d.split ("=", 2);
+ var name = def[0];
+ var value = def.length == 2 ? def[1] : "1";
+ builder.define_variable (name, value);
+ }
+
+ foreach (var arg in files) {
+ if (verbose)
+ print ("Loading %s...\n", arg);
+ var file = File.new_for_commandline_arg (arg);
+ builder.load_file (file, preproc);
+ builder.add_path (file.get_parent ().get_path ());
+ }
+
+ if (preproc)
+ return 0;
+
+ if (verbose)
+ print ("Building %s...\n", output);
+ var msi = builder.build ();
+ msi.build (output);
+ } catch (GLib.Error error) {
+ printerr (error.message + "\n");
+ return 1;
+ }
+
+ return 0;
+ }
+
+} // Wixl