~ubuntu-branches/ubuntu/saucy/vdr-plugin-live/saucy-proposed

« back to all changes in this revision

Viewing changes to tntconfig.cpp

  • Committer: Package Import Robot
  • Author(s): Tobias Grimm
  • Date: 2012-01-15 10:22:53 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20120115102253-hixwx4gbcpyhtt2m
Tags: 0.2.0+git20120114-1
* New Upstream Snapshot (commit d2a85a6) (Closes: #654879)
* Dropped 02_timers_colon patch - fixed upstream
* Dropped 04_tntnet-2.0.patch - fixed upstream
* Dropped 01_ipv6.patch - fixed upstream
* Dropped 03_live-0.2.0-fix-INCLUDES.patch - fixed upstream
* Build-depend on libpcre3-dev
* Updated debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
#include <fstream>
4
4
#include <sstream>
5
5
#include <stdexcept>
 
6
#include <cxxtools/loginit.h>
 
7
#include <tnt/sessionscope.h>
 
8
#include <tnt/httpreply.h>
6
9
#include <vdr/config.h>
7
10
#include <vdr/plugin.h>
 
11
#include <vdr/videodir.h>
8
12
#include "i18n.h"
9
13
#include "live.h"
10
14
#include "setup.h"
12
16
 
13
17
namespace vdrlive {
14
18
 
15
 
using namespace std;
16
 
 
17
 
TntConfig::TntConfig()
18
 
{
19
 
        WriteConfig();
20
 
}
21
 
 
22
 
void TntConfig::WriteConfig()
23
 
{
24
 
        WriteProperties();
25
 
 
26
 
        string const configDir(Plugin::GetConfigDirectory());
27
 
 
28
 
        ostringstream builder;
29
 
        builder << configDir << "/httpd.config";
30
 
        m_configPath = builder.str();
31
 
 
32
 
        ofstream file( m_configPath.c_str(), ios::out | ios::trunc );
33
 
        if ( !file ) {
 
19
        using namespace std;
 
20
 
 
21
        TntConfig::TntConfig()
 
22
        {
 
23
#if ! TNT_CONFIG_INTERNAL
 
24
                WriteConfig();
 
25
#endif
 
26
        }
 
27
 
 
28
#if ! TNT_CONFIG_INTERNAL
 
29
        void TntConfig::WriteConfig()
 
30
        {
 
31
                WriteProperties();
 
32
 
 
33
                string const configDir(Plugin::GetConfigDirectory());
 
34
 
34
35
                ostringstream builder;
35
 
                builder << "Can't open " << m_configPath << " for writing: " << strerror( errno );
36
 
                throw runtime_error( builder.str() );
37
 
        }
38
 
 
39
 
        // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
40
 
        // ------------------------------------------------------------------------
41
 
        // These MapUrl statements are very security sensitive!
42
 
        // A wrong mapping to content@ may allow retrieval of arbitrary files
43
 
        // from your VDR system via live.
44
 
        // Two meassures are taken against this in our implementation:
45
 
        // 1. The MapUrls need to be checked regulary against possible exploits
46
 
        //    One tool to do this can be found here:
47
 
        //      http://www.lumadis.be/regex/test_regex.php
48
 
        //    Newly inserted MapUrls should be marked with author and confirmed
49
 
        //    by a second party. (use source code comments for this)
50
 
        // 2. content.ecpp checks the given path to be
51
 
        //    a.  an absolute path starting at /
52
 
        //    b.  not containing ../ paths components
53
 
    //    In order to do so, the MapUrl statements must create absolute
54
 
        //    path arguments to content@
55
 
        // ------------------------------------------------------------------------
56
 
        // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
57
 
 
58
 
 
59
 
        file << "MapUrl ^/$ login@" << endl;
60
 
 
61
 
        // the following redirects vdr_request URL to the component
62
 
        // specified by the action parameter.
63
 
        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
64
 
        file << "MapUrl ^/vdr_request/([^.]+) $1@" << endl;
65
 
 
66
 
        // the following selects the theme specific 'theme.css' file
67
 
        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
68
 
        file << "MapUrl ^/themes/([^/]*)/css.*/(.+\\.css) content@ " << configDir << "/themes/$1/css/$2 text/css" << endl;
69
 
 
70
 
        // the following rules provide a search scheme for images. The first
71
 
        // rule where a image is found, terminates the search.
72
 
        // 1. /themes/<theme>/img/<imgname>.<ext>
73
 
        // 2. /img/<imgname>.<ext>
74
 
        // deprecated: 3. <imgname>.<ext> (builtin images)
75
 
        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
76
 
        file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/themes/$1/img/$2.$3 image/$3" << endl;
77
 
        file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/img/$2.$3 image/$3" << endl;
78
 
        // deprecated: file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) $2@" << endl;
79
 
 
80
 
        // Epg images
81
 
        string const epgImgPath(LiveSetup().GetEpgImageDir());
82
 
        if (!epgImgPath.empty()) {
83
 
                // inserted by 'winni' -- EXPLOITABLE! (checked by tadi)
84
 
                // file << "MapUrl ^/epgimages/(.*)\\.(.+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
85
 
 
86
 
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
87
 
                file << "MapUrl ^/epgimages/([^/]*)\\.([^./]+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
88
 
        }
89
 
 
90
 
        // select additional (not build in) javascript.
91
 
        // WARNING: no path components with '.' in the name are allowed. Only
92
 
        // the basename may contain dots and must end with '.js'
93
 
        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
94
 
        file << "MapUrl ^/js(/[^.]*)([^/]*\\.js) content@ " << configDir << "/js$1$2 text/javascript" << endl;
95
 
 
96
 
        // map to 'css/basename(uri)'
97
 
        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
98
 
        file << "MapUrl ^/css.*/(.+) content@ " << configDir << "/css/$1 text/css" << endl;
99
 
 
100
 
        // map to 'img/basename(uri)'
101
 
        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
102
 
        file << "MapUrl ^/img.*/(.+)\\.([^.]+) content@ " << configDir << "/img/$1.$2 image/$2" << endl;
103
 
 
104
 
        // Map favicon.ico into img directory
105
 
        file << "MapUrl ^/favicon.ico$ content@ " << configDir << "/img/favicon.ico image/x-icon" << endl;
106
 
 
107
 
        // insecure by default: DO NOT UNKOMMENT!!!
108
 
        // file << "MapUrl /([^/]+/.+) content@ $1" << endl;
109
 
 
110
 
        // takes first path components without 'extension' when it does not
111
 
        // contain '.'
112
 
        // modified by 'tadi' -- verified with above, but not counterchecked yet!
113
 
        file << "MapUrl ^/([^./]+)(.*)? $1@" << endl;
114
 
 
115
 
        file << "PropertyFile " << m_propertiesPath << endl;
116
 
        file << "SessionTimeout 86400" << endl;
117
 
        file << "DefaultContentType \"text/html; charset=" << LiveI18n().CharacterEncoding() << "\"" << endl;
118
 
 
119
 
        Setup::IpList const& ips = LiveSetup().GetServerIps();
120
 
        int port = LiveSetup().GetServerPort();
121
 
        for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
122
 
                file << "Listen " << *ip << " " << port << endl;
123
 
        }
124
 
 
125
 
#ifdef TNTVERS7
126
 
        int s_port = LiveSetup().GetServerSslPort();
127
 
        string s_cert = LiveSetup().GetServerSslCert();
128
 
 
129
 
        if (s_cert.empty()) {
130
 
                s_cert = configDir + "/live.pem";
131
 
        }
132
 
 
133
 
        if ( ifstream( s_cert.c_str() ) ) {
 
36
                builder << configDir << "/httpd.config";
 
37
                m_configPath = builder.str();
 
38
 
 
39
                ofstream file( m_configPath.c_str(), ios::out | ios::trunc );
 
40
                if ( !file ) {
 
41
                        ostringstream builder;
 
42
                        builder << "Can't open " << m_configPath << " for writing: " << strerror( errno );
 
43
                        throw runtime_error( builder.str() );
 
44
                }
 
45
 
 
46
                // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
 
47
                // ------------------------------------------------------------------------
 
48
                // These MapUrl statements are very security sensitive!
 
49
                // A wrong mapping to content@ may allow retrieval of arbitrary files
 
50
                // from your VDR system via live.
 
51
                // Two meassures are taken against this in our implementation:
 
52
                // 1. The MapUrls need to be checked regulary against possible exploits
 
53
                //    One tool to do this can be found here:
 
54
                //      http://www.lumadis.be/regex/test_regex.php
 
55
                //    Newly inserted MapUrls should be marked with author and confirmed
 
56
                //    by a second party. (use source code comments for this)
 
57
                // 2. content.ecpp checks the given path to be
 
58
                //    a.  an absolute path starting at /
 
59
                //    b.  not containing ../ paths components
 
60
                //    In order to do so, the MapUrl statements must create absolute
 
61
                //    path arguments to content@
 
62
                // ------------------------------------------------------------------------
 
63
                // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
 
64
 
 
65
 
 
66
                file << "MapUrl ^/$ login@" << endl;
 
67
 
 
68
                // the following redirects vdr_request URL to the component
 
69
                // specified by the action parameter.
 
70
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
71
                file << "MapUrl ^/vdr_request/([^.]+) $1@" << endl;
 
72
 
 
73
                // the following selects the theme specific 'theme.css' file
 
74
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
75
                file << "MapUrl ^/themes/([^/]*)/css.*/(.+\\.css) content@ " << configDir << "/themes/$1/css/$2 text/css" << endl;
 
76
 
 
77
                // the following rules provide a search scheme for images. The first
 
78
                // rule where a image is found, terminates the search.
 
79
                // 1. /themes/<theme>/img/<imgname>.<ext>
 
80
                // 2. /img/<imgname>.<ext>
 
81
                // deprecated: 3. <imgname>.<ext> (builtin images)
 
82
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
83
                file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/themes/$1/img/$2.$3 image/$3" << endl;
 
84
                file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/img/$2.$3 image/$3" << endl;
 
85
                // deprecated: file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) $2@" << endl;
 
86
 
 
87
                // Epg images
 
88
                string const epgImgPath(LiveSetup().GetEpgImageDir());
 
89
                if (!epgImgPath.empty()) {
 
90
                        // inserted by 'winni' -- EXPLOITABLE! (checked by tadi)
 
91
                        // file << "MapUrl ^/epgimages/(.*)\\.(.+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
 
92
 
 
93
                        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
94
                        file << "MapUrl ^/epgimages/([^/]*)\\.([^./]+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
 
95
                }
 
96
 
 
97
                // select additional (not build in) javascript.
 
98
                // WARNING: no path components with '.' in the name are allowed. Only
 
99
                // the basename may contain dots and must end with '.js'
 
100
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
101
                file << "MapUrl ^/js(/[^.]*)([^/]*\\.js) content@ " << configDir << "/js$1$2 text/javascript" << endl;
 
102
 
 
103
                // map to 'css/basename(uri)'
 
104
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
105
                file << "MapUrl ^/css.*/(.+) content@ " << configDir << "/css/$1 text/css" << endl;
 
106
 
 
107
                // map to 'img/basename(uri)'
 
108
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
109
                file << "MapUrl ^/img.*/(.+)\\.([^.]+) content@ " << configDir << "/img/$1.$2 image/$2" << endl;
 
110
 
 
111
                // Map favicon.ico into img directory
 
112
                file << "MapUrl ^/favicon.ico$ content@ " << configDir << "/img/favicon.ico image/x-icon" << endl;
 
113
 
 
114
                // insecure by default: DO NOT UNKOMMENT!!!
 
115
                // file << "MapUrl /([^/]+/.+) content@ $1" << endl;
 
116
 
 
117
                // takes first path components without 'extension' when it does not
 
118
                // contain '.'
 
119
                // modified by 'tadi' -- verified with above, but not counterchecked yet!
 
120
                file << "MapUrl ^/([^./]+)(.*)? $1@" << endl;
 
121
 
 
122
                file << "PropertyFile " << m_propertiesPath << endl;
 
123
                file << "SessionTimeout 86400" << endl;
 
124
                file << "DefaultContentType \"text/html; charset=" << LiveI18n().CharacterEncoding() << "\"" << endl;
 
125
 
 
126
                Setup::IpList const& ips = LiveSetup().GetServerIps();
 
127
                int port = LiveSetup().GetServerPort();
134
128
                for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
135
 
                        file << "SslListen " << *ip << " " << s_port << " " << s_cert << endl;
 
129
                        file << "Listen " << *ip << " " << port << endl;
136
130
                }
137
131
        }
138
 
        else {
139
 
                esyslog( "ERROR: %s: %s", s_cert.c_str(), strerror( errno ) );
140
 
        }
141
132
#endif
142
 
}
143
 
 
144
 
void TntConfig::WriteProperties()
145
 
{
146
 
        ostringstream builder;
147
 
        builder << Plugin::GetConfigDirectory() << "/httpd.properties";
148
 
        m_propertiesPath = builder.str();
149
 
 
150
 
        ofstream file( m_propertiesPath.c_str(), ios::out | ios::trunc );
151
 
        if ( !file ) {
 
133
 
 
134
#if ! TNT_CONFIG_INTERNAL
 
135
        void TntConfig::WriteProperties()
 
136
        {
152
137
                ostringstream builder;
153
 
                builder << "Can't open " << m_propertiesPath << " for writing: " << strerror( errno );
154
 
                throw runtime_error( builder.str() );
155
 
        }
156
 
 
157
 
        // XXX modularize
158
 
        file << "rootLogger=" << LiveSetup().GetTntnetLogLevel() << endl;
159
 
        file << "logger.tntnet=" << LiveSetup().GetTntnetLogLevel() << endl;
160
 
}
161
 
 
162
 
TntConfig const& TntConfig::Get()
163
 
{
164
 
        static TntConfig instance;
165
 
        return instance;
166
 
}
167
 
 
 
138
                builder << Plugin::GetConfigDirectory() << "/httpd.properties";
 
139
                m_propertiesPath = builder.str();
 
140
 
 
141
                ofstream file( m_propertiesPath.c_str(), ios::out | ios::trunc );
 
142
                if ( !file ) {
 
143
                        ostringstream builder;
 
144
                        builder << "Can't open " << m_propertiesPath << " for writing: " << strerror( errno );
 
145
                        throw runtime_error( builder.str() );
 
146
                }
 
147
 
 
148
                // XXX modularize
 
149
                file << "rootLogger=" << LiveSetup().GetTntnetLogLevel() << endl;
 
150
                file << "logger.tntnet=" << LiveSetup().GetTntnetLogLevel() << endl;
 
151
                file << "logger.cxxtools=" << LiveSetup().GetTntnetLogLevel() << endl;
 
152
        }
 
153
#endif
 
154
 
 
155
#if TNT_CONFIG_INTERNAL
 
156
        void TntConfig::Configure(tnt::Tntnet& app) const
 
157
        {
 
158
                string const configDir(Plugin::GetConfigDirectory());
 
159
 
 
160
                std::istringstream logConf(
 
161
                        "rootLogger=" + LiveSetup().GetTntnetLogLevel() + "\n"
 
162
                        "logger.tntnet=" + LiveSetup().GetTntnetLogLevel() + "\n"
 
163
                        "logger.cxxtools=" + LiveSetup().GetTntnetLogLevel() + "\n"
 
164
                        );
 
165
                log_init(logConf);
 
166
 
 
167
                // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
 
168
                // ------------------------------------------------------------------------
 
169
                // These mapUrl statements are very security sensitive!
 
170
                // A wrong mapping to content may allow retrieval of arbitrary files
 
171
                // from your VDR system via live.
 
172
                // Two meassures are taken against this in our implementation:
 
173
                // 1. The MapUrls need to be checked regulary against possible exploits
 
174
                //    One tool to do this can be found here:
 
175
                //      http://www.lumadis.be/regex/test_regex.php
 
176
                //    Newly inserted MapUrls should be marked with author and confirmed
 
177
                //    by a second party. (use source code comments for this)
 
178
                // 2. content.ecpp checks the given path to be
 
179
                //    a.  an absolute path starting at /
 
180
                //    b.  not containing ../ paths components
 
181
                //    In order to do so, the MapUrl statements must create absolute
 
182
                //    path arguments to content@
 
183
                // ------------------------------------------------------------------------
 
184
                // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
 
185
 
 
186
                app.mapUrl("^/$", "login");
 
187
 
 
188
                // the following redirects vdr_request URL to the component
 
189
                // specified by the action parameter.
 
190
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
191
                app.mapUrl("^/vdr_request/([^.]+)", "$1");
 
192
 
 
193
                // the following redirects play_video URL to the content component.
 
194
                // inserted by 'tadi' -- not verified, not counterchecked yet!
 
195
                //app.mapUrl("^/vlc/(.+)", "static@tntnet")
 
196
                //      .setPathInfo("/$1")
 
197
                //      .pushArg(string("DocumentRoot=") + VideoDirectory);
 
198
 
 
199
                // the following selects the theme specific 'theme.css' file
 
200
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
201
                app.mapUrl("^/themes/([^/]*)/css.*/(.+\\.css)", "content")
 
202
                        .setPathInfo(configDir + "/themes/$1/css/$2")
 
203
                        .pushArg("text/css");
 
204
 
 
205
                // the following rules provide a search scheme for images. The first
 
206
                // rule where a image is found, terminates the search.
 
207
                // 1. /themes/<theme>/img/<imgname>.<ext>
 
208
                // 2. /img/<imgname>.<ext>
 
209
                // deprecated: 3. <imgname>.<ext> (builtin images)
 
210
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
211
                app.mapUrl("^/themes/([^/]*)/img.*/(.+)\\.(.+)", "content")
 
212
                        .setPathInfo(configDir + "/themes/$1/img/$2.$3")
 
213
                        .pushArg("image/$3");
 
214
                app.mapUrl("^/themes/([^/]*)/img.*/(.+)\\.(.+)", "content")
 
215
                        .setPathInfo(configDir + "/img/$2.$3")
 
216
                        .pushArg("image/$3");
 
217
                // deprecated: file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) $2@" << endl;
 
218
 
 
219
                // Epg images
 
220
                string const epgImgPath(LiveSetup().GetEpgImageDir());
 
221
                if (!epgImgPath.empty()) {
 
222
                        // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
223
                        app.mapUrl("^/epgimages/([^/]*)\\.([^./]+)", "content")
 
224
                                .setPathInfo(epgImgPath + "/$1.$2")
 
225
                                .pushArg("image/$2");
 
226
                }
 
227
 
 
228
                // select additional (not build in) javascript.
 
229
                // WARNING: no path components with '.' in the name are allowed. Only
 
230
                // the basename may contain dots and must end with '.js'
 
231
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
232
                app.mapUrl("^/js(/[^.]*)([^/]*\\.js)", "content")
 
233
                        .setPathInfo(configDir + "/js$1$2")
 
234
                        .pushArg("text/javascript");
 
235
 
 
236
                // map to 'css/basename(uri)'
 
237
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
238
                app.mapUrl("^/css.*/(.+)", "content")
 
239
                        .setPathInfo(configDir + "/css/$1")
 
240
                        .pushArg("text/css");
 
241
 
 
242
                // map to 'img/basename(uri)'
 
243
                // inserted by 'tadi' -- verified with above, but not counterchecked yet!
 
244
                app.mapUrl("^/img.*/(.+)\\.([^.]+)", "content")
 
245
                        .setPathInfo(configDir + "/img/$1.$2")
 
246
                        .pushArg("image/$2");
 
247
 
 
248
                // Map favicon.ico into img directory
 
249
                app.mapUrl("^/favicon.ico$", "content")
 
250
                        .setPathInfo(configDir + "/img/favicon.ico")
 
251
                        .pushArg("image/x-icon");
 
252
 
 
253
                // takes first path components without 'extension' when it does not
 
254
                // contain '.'
 
255
                // modified by 'tadi' -- verified with above, but not counterchecked yet!
 
256
                app.mapUrl("^/([^./]+)(.*)?", "$1");
 
257
 
 
258
                tnt::Sessionscope::setDefaultTimeout(86400);
 
259
                tnt::HttpReply::setDefaultContentType(string("text/html; charset=") + LiveI18n().CharacterEncoding());
 
260
 
 
261
                Setup::IpList const& ips = LiveSetup().GetServerIps();
 
262
                int port = LiveSetup().GetServerPort();
 
263
                size_t listenFailures = 0;
 
264
                for (Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip) {
 
265
                        try {
 
266
                                esyslog("[live] INFO: attempt to listen on ip = '%s'", ip->c_str());
 
267
                                app.listen(*ip, port);
 
268
                        }
 
269
                        catch (exception const & ex) {
 
270
                                esyslog("[live] ERROR: ip = %s is invalid: exception = %s", ip->c_str(), ex.what());
 
271
                                if (++listenFailures == ips.size()) {
 
272
                                        // if no listener was initialized we throw at
 
273
                                        // least the last exception to the next layer.
 
274
                                        throw;
 
275
                                }
 
276
                        }
 
277
                }
 
278
 
 
279
#if TNT_SSL_SUPPORT
 
280
                int s_port = LiveSetup().GetServerSslPort();
 
281
                string s_cert = LiveSetup().GetServerSslCert();
 
282
                string s_key = LiveSetup().GetServerSslKey();
 
283
 
 
284
                if (s_cert.empty()) {
 
285
                        s_cert = configDir + "/live.pem";
 
286
                }
 
287
 
 
288
                if (s_key.empty()) {
 
289
                        s_key = configDir + "/live-key.pem";
 
290
                }
 
291
 
 
292
                if ( ifstream( s_cert.c_str() ) && ifstream( s_key.c_str() ) ) {
 
293
                        for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
 
294
                                app.sslListen(s_cert, s_key, *ip, s_port);
 
295
                        }
 
296
                }
 
297
                else {
 
298
                        esyslog( "[live] ERROR: Unable to load cert/key (%s/%s): %s", s_cert.c_str(), s_key.c_str(), strerror( errno ) );
 
299
                }
 
300
#endif // TNT_SSL_SUPPORT
 
301
        }
 
302
#endif
 
303
 
 
304
        TntConfig const& TntConfig::Get()
 
305
        {
 
306
                static TntConfig instance;
 
307
                return instance;
 
308
        }
168
309
} // namespace vdrlive