annotate ui/main.cpp @ 633:6c090638b2b4

Use static buffer for module file name. According to the msdn examle the return value of getmodulefilename should be used to indicate success and not the size. And according to comments on that function on Windows 8.1 it does not return the needed size. So better be more robust and just use max_path as a limit.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 23 Jun 2014 15:29:48 +0200
parents edf269b6e499
children 80d1a80b3e8d
rev   line source
404
17e1c8f37d72 Add License
Andre Heinecke <aheinecke@intevation.de>
parents: 365
diff changeset
1 /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
17e1c8f37d72 Add License
Andre Heinecke <aheinecke@intevation.de>
parents: 365
diff changeset
2 * Software engineering by Intevation GmbH
17e1c8f37d72 Add License
Andre Heinecke <aheinecke@intevation.de>
parents: 365
diff changeset
3 *
17e1c8f37d72 Add License
Andre Heinecke <aheinecke@intevation.de>
parents: 365
diff changeset
4 * This file is Free Software under the GNU GPL (v>=2)
17e1c8f37d72 Add License
Andre Heinecke <aheinecke@intevation.de>
parents: 365
diff changeset
5 * and comes with ABSOLUTELY NO WARRANTY!
17e1c8f37d72 Add License
Andre Heinecke <aheinecke@intevation.de>
parents: 365
diff changeset
6 * See LICENSE.txt for details.
17e1c8f37d72 Add License
Andre Heinecke <aheinecke@intevation.de>
parents: 365
diff changeset
7 */
0
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
8 #include "mainwindow.h"
612
2ea11a95aa4a Bail if the user is already running the application.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 499
diff changeset
9 #include "processhelp.h"
631
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
10 #include "binverify.h"
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
11 #include "logging.h"
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
12 #include "strhelp.h"
0
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
13
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
14 #include <QApplication>
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
15 #include <QSystemTrayIcon>
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
16 #include <QtPlugin>
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
17 #include <QMessageBox>
17
c12825a651ed Read out content-length and use this to skip existing files
Andre Heinecke <aheinecke@intevation.de>
parents: 16
diff changeset
18 #include <QSettings>
423
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
19 #include <QDebug>
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
20 #include <QTranslator>
0
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
21
16
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
22 #ifndef VERSION
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
23 #define VERSION "0.0.1"
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
24 #endif
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
25
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
26 #ifndef APPNAME
407
af53c40e74b1 Rename m13ui to TrustBridge
Andre Heinecke <aheinecke@intevation.de>
parents: 404
diff changeset
27 #define APPNAME "TrustBridge"
16
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
28 #endif
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
29
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
30 #ifndef ORGANIZATION
409
09bb19e5e369 Remove m13 mentions and change test certificate to intevation.de
Andre Heinecke <aheinecke@intevation.de>
parents: 407
diff changeset
31 #define ORGANIZATION "BSI"
16
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
32 #endif
0
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
33
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
34 #ifdef Q_OS_WIN
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
35 Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
36 #else
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
37 Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
38 #endif
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
39
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
40 int main(int argc, char **argv)
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
41 {
631
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
42 /* First verify integrity even before calling QApplication*/
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
43 #ifdef Q_OS_WIN
633
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
44 {
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
45 wchar_t wPath[MAX_PATH];
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
46 char *utf8path = NULL;
631
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
47
633
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
48 if (!GetModuleFileNameW (NULL, wPath, MAX_PATH - 1)) {
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
49 PRINTLASTERROR ("Failed to obtain module file name. Path too long?");
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
50 syslog_error_printf ("Integrity check failed.");
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
51 return -1;
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
52 }
631
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
53
633
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
54 /* wPath might not be 0 terminated */
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
55 wPath[MAX_PATH - 1] = '\0';
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
56
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
57 utf8path = wchar_to_utf8 (wPath, wcsnlen(wPath, MAX_PATH));
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
58
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
59 if (utf8path == NULL) {
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
60 ERRORPRINTF ("Failed to convert module path to utf-8");
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
61 syslog_error_printf ("Integrity check failed.");
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
62 return -1;
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
63 }
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
64
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
65 if (!verify_binary (utf8path, strlen(utf8path)) != VerifyValid)
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
66 {
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
67 ERRORPRINTF ("Verification of the binary failed");
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
68 syslog_error_printf ("Integrity check failed.");
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
69 xfree(utf8path);
631
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
70 #ifdef RELEASE_BUILD
633
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
71 return -1;
631
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
72 #endif
633
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
73 }
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
74
6c090638b2b4 Use static buffer for module file name.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 631
diff changeset
75 xfree(utf8path);
631
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
76 }
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
77 #else
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
78 if (!verify_binary ("/proc/self/exe", 14) != VerifyValid)
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
79 {
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
80 syslog_error_printf ("Integrity check failed.");
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
81 #ifdef RELEASE_BUILD
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
82 return -1;
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
83 #endif
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
84 }
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
85 #endif
edf269b6e499 Add self test as first opertation on start
Andre Heinecke <andre.heinecke@intevation.de>
parents: 612
diff changeset
86
0
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
87 QApplication app (argc, argv);
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
88
482
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
89 QApplication::setQuitOnLastWindowClosed(false);
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
90 QApplication::setOrganizationName(QString::fromLatin1(ORGANIZATION));
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
91 QApplication::setApplicationName(QString::fromLatin1(APPNAME));
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
92 QApplication::setApplicationVersion(QString::fromLatin1(VERSION));
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
93 QSettings::setDefaultFormat(QSettings::IniFormat);
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
94
154
3349c9596043 Added commandline arguemnt '--tray' to hide or show the mainwindow.
Raimund Renkert <rrenkert@intevation.de>
parents: 73
diff changeset
95 QStringList arguments = QApplication::arguments();
3349c9596043 Added commandline arguemnt '--tray' to hide or show the mainwindow.
Raimund Renkert <rrenkert@intevation.de>
parents: 73
diff changeset
96 bool trayMode = arguments.contains("--tray");
3349c9596043 Added commandline arguemnt '--tray' to hide or show the mainwindow.
Raimund Renkert <rrenkert@intevation.de>
parents: 73
diff changeset
97
482
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
98 QSettings settings;
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
99 settings.beginGroup("settings");
499
077b4342d69b Default autostart to true and change setting to bool
Andre Heinecke <aheinecke@intevation.de>
parents: 487
diff changeset
100 bool autoStart = settings.value("autostart", true).toBool();
482
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
101 settings.endGroup();
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
102
499
077b4342d69b Default autostart to true and change setting to bool
Andre Heinecke <aheinecke@intevation.de>
parents: 487
diff changeset
103 if (trayMode && !autoStart) {
482
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
104 return 0;
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
105 }
0f4331ed4e83 Close the application if started in tray mode and autstart is not set.
Raimund Renkert <rrenkert@intevation.de>
parents: 423
diff changeset
106
612
2ea11a95aa4a Bail if the user is already running the application.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 499
diff changeset
107 if (ProcessHelp::otherProcessesExist(APPNAME)) {
2ea11a95aa4a Bail if the user is already running the application.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 499
diff changeset
108 qDebug() << "Another " << APPNAME << " process is already running. Exiting.";
2ea11a95aa4a Bail if the user is already running the application.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 499
diff changeset
109 ProcessHelp::activateWindowForProcess(APPNAME);
2ea11a95aa4a Bail if the user is already running the application.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 499
diff changeset
110 return 0;
2ea11a95aa4a Bail if the user is already running the application.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 499
diff changeset
111 }
2ea11a95aa4a Bail if the user is already running the application.
Andre Heinecke <andre.heinecke@intevation.de>
parents: 499
diff changeset
112
423
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
113 QTranslator translator;
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
114 if (QLocale::system().name() == "C") {
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
115 /* Useful for testing / development as the primary target is german */
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
116 translator.load(":/l10n/trustbridge_de_DE");
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
117 } else {
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
118 translator.load(":/l10n/trustbridge_" + QLocale::system().name());
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
119 qDebug() << "Loading translations for: " << "trustbridge_" +
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
120 QLocale::system().name();
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
121 }
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
122 app.installTranslator(&translator);
3d1e9df24803 Add translation loading
Andre Heinecke <aheinecke@intevation.de>
parents: 409
diff changeset
123
73
5c616934cbe4 Also check that the system tray supports messages
Andre Heinecke <aheinecke@intevation.de>
parents: 71
diff changeset
124 if (!QSystemTrayIcon::isSystemTrayAvailable() ||
5c616934cbe4 Also check that the system tray supports messages
Andre Heinecke <aheinecke@intevation.de>
parents: 71
diff changeset
125 !QSystemTrayIcon::supportsMessages()) {
16
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
126 QMessageBox::critical(0, QString::fromLatin1(APPNAME),
0
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
127 QObject::tr("Couldn't detect any system tray "
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
128 "on this system. This software can only "
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
129 "be used in a desktop environment."));
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
130 return 1;
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
131 }
16
225a5ec20dad Use QSettings and manage downloader from mainwindow.
Andre Heinecke <aheinecke@intevation.de>
parents: 0
diff changeset
132
365
75f7288ad67b Switch from listupdatedialog to installwrapper. Minor UI improvements
Andre Heinecke <aheinecke@intevation.de>
parents: 154
diff changeset
133 MainWindow mainWin(trayMode);
0
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
134
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
135 return app.exec();
cb0cde2c5eb9 Initial commit. Basically a Hello World with a Tray Icon.
Andre Heinecke <aheinecke@intevation.de>
parents:
diff changeset
136 }

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