annotate ui/tests/binverifytest.cpp @ 1390:f3e2df6b49ba

(issue181) Fix hardcoded values for RSA codesigning key size.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 19 Jan 2015 15:42:20 +0100
parents 948f03bb5254
children
rev   line source
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
1 /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
2 * Software engineering by Intevation GmbH
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
3 *
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
4 * This file is Free Software under the GNU GPL (v>=2)
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
5 * and comes with ABSOLUTELY NO WARRANTY!
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
6 * See LICENSE.txt for details.
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
7 */
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
8 #include "binverify.h"
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
9 #include "binverifytest.h"
869
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
10 #include "createinstallerdialog.h"
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
11 #include "common.h"
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
12 #include "mainwindow.h"
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
13
869
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
14 #include <QtTest>
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
15 #include <QSettings>
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
16 #include <QTemporaryFile>
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
17
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
18 #ifdef Q_OS_WIN
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
19 # define EXE_SUFFIX ".exe"
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
20 #else
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
21 # define EXE_SUFFIX ""
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
22 #endif
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
23
869
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
24 #ifdef Q_OS_WIN
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
25 Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
26 #else
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
27 Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
28 #endif
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
29
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
30 /* Some general robustness checks */
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
31 void BinVerifyTest::testMiscErrors()
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
32 {
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
33 QVERIFY (verify_binary (NULL, 10).result != VerifyValid);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
34 QVERIFY (verify_binary ("foo", 10).result != VerifyValid);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
35 QVERIFY (verify_binary ("bar", -1).result!= VerifyValid);
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
36 /* On windows the next line will check that a valid microsoft
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
37 * signed executable is not valid for us (pinning). On linux
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
38 * it will just fail with a read error which we tested above */
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
39 #ifdef Q_OS_WIN
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
40 QVERIFY (verify_binary ("c:\\Windows\\System32\\mmc.exe",
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
41 strlen("c:\\Windows\\System32\\mmc.exe")).result != VerifyInvalidCertificate);
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
42 #endif
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
43 QVERIFY (verify_binary ("/dev/null", strlen("/dev/null")).result != VerifyValid);
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
44 }
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
45
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
46 /* Check that a signature with only a different key (of the same size)
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
47 * is not validated (Invalid signature because key and cert don't match)*/
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
48 void BinVerifyTest::testOtherKey()
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
49 {
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
50 QVERIFY(VerifyInvalidSignature == verify_binary ("fakeinst-other-key" EXE_SUFFIX,
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
51 strlen("fakeinst-other-key" EXE_SUFFIX)).result);
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
52 }
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
53
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
54 /* Check that an invalid signature is not validated */
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
55 void BinVerifyTest::testInvalidSig()
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
56 {
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
57 bin_verify_result res = verify_binary ("fakeinst-invalid" EXE_SUFFIX,
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
58 strlen("fakeinst-invalid" EXE_SUFFIX));
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
59 QVERIFY(VerifyValid != res.result);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
60 QVERIFY(res.fptr == NULL);
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
61 }
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
62
774
44fa5de02b52 (issue43) Finalize and verify binary verification for linux.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 637
diff changeset
63 #ifdef Q_OS_WIN
44fa5de02b52 (issue43) Finalize and verify binary verification for linux.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 637
diff changeset
64 /* Check that a signature with a different (valid) certificate is not validated
44fa5de02b52 (issue43) Finalize and verify binary verification for linux.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 637
diff changeset
65 * on Linux only the key is checked not the certificate */
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
66 void BinVerifyTest::testOtherCert()
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
67 {
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
68 QVERIFY(VerifyInvalidCertificate == verify_binary ("fakeinst-other-cert" EXE_SUFFIX,
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
69 strlen("fakeinst-other-cert" EXE_SUFFIX)).result);
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
70 }
774
44fa5de02b52 (issue43) Finalize and verify binary verification for linux.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 637
diff changeset
71 #endif
637
be30d50bc4f0 Add remaining tests to check binverify functionality
Andre Heinecke <andre.heinecke@intevation.de>
parents: 636
diff changeset
72
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
73 /* Check that no signature is not validated */
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
74 void BinVerifyTest::testNoSignature()
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
75 {
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
76 bin_verify_result res = verify_binary ("fakeinst" EXE_SUFFIX,
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
77 strlen("fakeinst" EXE_SUFFIX));
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
78 QVERIFY(VerifyValid != res.result);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
79 QVERIFY(res.fptr == NULL);
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
80 }
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
81
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
82 /* Check that a valid signed executable is verified */
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
83 void BinVerifyTest::testValidBinary()
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
84 {
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
85 bin_verify_result res = verify_binary ("fakeinst-signed" EXE_SUFFIX,
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
86 strlen("fakeinst-signed" EXE_SUFFIX));
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
87 QVERIFY (VerifyValid == res.result);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
88 QFile thefile ("fakeinst-signed" EXE_SUFFIX);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
89 #ifdef WIN32
1369
948f03bb5254 Add signature time extraction for Linux and test for it in binverifytest
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1081
diff changeset
90 /* Verifies the deny write open mode. But on linux we dont have it. */
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
91 QVERIFY (!thefile.open(QIODevice::ReadWrite));
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
92 #endif
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
93 QVERIFY (res.fptr != NULL);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
94 fclose(res.fptr);
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
95 QVERIFY (thefile.open(QIODevice::ReadWrite));
1369
948f03bb5254 Add signature time extraction for Linux and test for it in binverifytest
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1081
diff changeset
96 QVERIFY (res.sig_time != 0 && res.sig_time != -1);
948f03bb5254 Add signature time extraction for Linux and test for it in binverifytest
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1081
diff changeset
97 QDateTime sigDt = QDateTime::fromTime_t(res.sig_time);
948f03bb5254 Add signature time extraction for Linux and test for it in binverifytest
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1081
diff changeset
98 QVERIFY (sigDt.isValid());
948f03bb5254 Add signature time extraction for Linux and test for it in binverifytest
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1081
diff changeset
99 qDebug() << "Signature time: " << sigDt;
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
100 thefile.close();
636
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
101 }
2fd4f9980a2a Add test for authenticode verificate (binverify)
Andre Heinecke <andre.heinecke@intevation.de>
parents:
diff changeset
102
869
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
103 void BinVerifyTest::testSignatureCreation()
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
104 {
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
105 QSettings testsettings;
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
106 testsettings.setValue("CodeSignCert", SOURCE_DIR"/data/codesign/codesigning-combined.pem");
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
107 testsettings.sync();
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
108 CreateInstallerDialog *theDialog = new CreateInstallerDialog(NULL);
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
109 QString garbage = getRandomDataFile(21*1024*1024);
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
110 QTemporaryFile outfile;
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
111 outfile.open();
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
112 outfile.close();
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
113 bool ret = theDialog->appendTextSignatureToFile (garbage, outfile.fileName());
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
114 QVERIFY(QFile::remove(garbage));
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
115 QVERIFY(ret == true);
1081
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
116 bin_verify_result res = verify_binary (outfile.fileName().toUtf8().constData(),
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
117 outfile.fileName().toUtf8().size());
edbf5e5e88f4 (issue118) Extend verify_binary to carry an open file
Andre Heinecke <andre.heinecke@intevation.de>
parents: 1060
diff changeset
118 QVERIFY(VerifyValid == res.result);
869
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
119 }
1060
317ee9dc4684 (issue46) Make debug output optional in cinst and mozilla and propagate its setting.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 869
diff changeset
120 bool g_debug = true;
869
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
121
b1df9621c89c Add a test for text signature creation with createinstallerdialog
Andre Heinecke <andre.heinecke@intevation.de>
parents: 774
diff changeset
122 QTEST_MAIN (BinVerifyTest);

http://wald.intevation.org/projects/trustbridge/