summaryrefslogtreecommitdiff
path: root/tntconfig.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tntconfig.cpp')
-rw-r--r--tntconfig.cpp389
1 files changed, 265 insertions, 124 deletions
diff --git a/tntconfig.cpp b/tntconfig.cpp
index cdc476e..71bee4d 100644
--- a/tntconfig.cpp
+++ b/tntconfig.cpp
@@ -3,8 +3,12 @@
#include <fstream>
#include <sstream>
#include <stdexcept>
+#include <cxxtools/loginit.h>
+#include <tnt/sessionscope.h>
+#include <tnt/httpreply.h>
#include <vdr/config.h>
#include <vdr/plugin.h>
+#include <vdr/videodir.h>
#include "i18n.h"
#include "live.h"
#include "setup.h"
@@ -12,157 +16,294 @@
namespace vdrlive {
-using namespace std;
+ using namespace std;
-TntConfig::TntConfig()
-{
- WriteConfig();
-}
-
-void TntConfig::WriteConfig()
-{
- WriteProperties();
+ TntConfig::TntConfig()
+ {
+#if TNTVERSION < 1606
+ WriteConfig();
+#endif
+ }
- string const configDir(Plugin::GetConfigDirectory());
+#if TNTVERSION < 1606
+ void TntConfig::WriteConfig()
+ {
+ WriteProperties();
- ostringstream builder;
- builder << configDir << "/httpd.config";
- m_configPath = builder.str();
+ string const configDir(Plugin::GetConfigDirectory());
- ofstream file( m_configPath.c_str(), ios::out | ios::trunc );
- if ( !file ) {
ostringstream builder;
- builder << "Can't open " << m_configPath << " for writing: " << strerror( errno );
- throw runtime_error( builder.str() );
- }
+ builder << configDir << "/httpd.config";
+ m_configPath = builder.str();
+
+ ofstream file( m_configPath.c_str(), ios::out | ios::trunc );
+ if ( !file ) {
+ ostringstream builder;
+ builder << "Can't open " << m_configPath << " for writing: " << strerror( errno );
+ throw runtime_error( builder.str() );
+ }
+
+ // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
+ // ------------------------------------------------------------------------
+ // These MapUrl statements are very security sensitive!
+ // A wrong mapping to content@ may allow retrieval of arbitrary files
+ // from your VDR system via live.
+ // Two meassures are taken against this in our implementation:
+ // 1. The MapUrls need to be checked regulary against possible exploits
+ // One tool to do this can be found here:
+ // http://www.lumadis.be/regex/test_regex.php
+ // Newly inserted MapUrls should be marked with author and confirmed
+ // by a second party. (use source code comments for this)
+ // 2. content.ecpp checks the given path to be
+ // a. an absolute path starting at /
+ // b. not containing ../ paths components
+ // In order to do so, the MapUrl statements must create absolute
+ // path arguments to content@
+ // ------------------------------------------------------------------------
+ // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
+
- // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
- // ------------------------------------------------------------------------
- // These MapUrl statements are very security sensitive!
- // A wrong mapping to content@ may allow retrieval of arbitrary files
- // from your VDR system via live.
- // Two meassures are taken against this in our implementation:
- // 1. The MapUrls need to be checked regulary against possible exploits
- // One tool to do this can be found here:
- // http://www.lumadis.be/regex/test_regex.php
- // Newly inserted MapUrls should be marked with author and confirmed
- // by a second party. (use source code comments for this)
- // 2. content.ecpp checks the given path to be
- // a. an absolute path starting at /
- // b. not containing ../ paths components
- // In order to do so, the MapUrl statements must create absolute
- // path arguments to content@
- // ------------------------------------------------------------------------
- // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
-
-
- file << "MapUrl ^/$ login@" << endl;
-
- // the following redirects vdr_request URL to the component
- // specified by the action parameter.
- // inserted by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/vdr_request/([^.]+) $1@" << endl;
-
- // the following selects the theme specific 'theme.css' file
- // inserted by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/themes/([^/]*)/css.*/(.+\\.css) content@ " << configDir << "/themes/$1/css/$2 text/css" << endl;
-
- // the following rules provide a search scheme for images. The first
- // rule where a image is found, terminates the search.
- // 1. /themes/<theme>/img/<imgname>.<ext>
- // 2. /img/<imgname>.<ext>
- // deprecated: 3. <imgname>.<ext> (builtin images)
- // inserted by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/themes/$1/img/$2.$3 image/$3" << endl;
- file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/img/$2.$3 image/$3" << endl;
- // deprecated: file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) $2@" << endl;
-
- // Epg images
- string const epgImgPath(LiveSetup().GetEpgImageDir());
- if (!epgImgPath.empty()) {
- // inserted by 'winni' -- EXPLOITABLE! (checked by tadi)
- // file << "MapUrl ^/epgimages/(.*)\\.(.+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
+ file << "MapUrl ^/$ login@" << endl;
+ // the following redirects vdr_request URL to the component
+ // specified by the action parameter.
// inserted by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/epgimages/([^/]*)\\.([^./]+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
- }
+ file << "MapUrl ^/vdr_request/([^.]+) $1@" << endl;
- // select additional (not build in) javascript.
- // WARNING: no path components with '.' in the name are allowed. Only
- // the basename may contain dots and must end with '.js'
- // inserted by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/js(/[^.]*)([^/]*\\.js) content@ " << configDir << "/js$1$2 text/javascript" << endl;
+ // the following selects the theme specific 'theme.css' file
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ file << "MapUrl ^/themes/([^/]*)/css.*/(.+\\.css) content@ " << configDir << "/themes/$1/css/$2 text/css" << endl;
- // map to 'css/basename(uri)'
- // inserted by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/css.*/(.+) content@ " << configDir << "/css/$1 text/css" << endl;
+ // the following rules provide a search scheme for images. The first
+ // rule where a image is found, terminates the search.
+ // 1. /themes/<theme>/img/<imgname>.<ext>
+ // 2. /img/<imgname>.<ext>
+ // deprecated: 3. <imgname>.<ext> (builtin images)
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/themes/$1/img/$2.$3 image/$3" << endl;
+ file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) content@ " << configDir << "/img/$2.$3 image/$3" << endl;
+ // deprecated: file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) $2@" << endl;
- // map to 'img/basename(uri)'
- // inserted by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/img.*/(.+)\\.([^.]+) content@ " << configDir << "/img/$1.$2 image/$2" << endl;
+ // Epg images
+ string const epgImgPath(LiveSetup().GetEpgImageDir());
+ if (!epgImgPath.empty()) {
+ // inserted by 'winni' -- EXPLOITABLE! (checked by tadi)
+ // file << "MapUrl ^/epgimages/(.*)\\.(.+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
- // Map favicon.ico into img directory
- file << "MapUrl ^/favicon.ico$ content@ " << configDir << "/img/favicon.ico image/x-icon" << endl;
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ file << "MapUrl ^/epgimages/([^/]*)\\.([^./]+) content@ " << epgImgPath << "/$1.$2 image/$2" << endl;
+ }
- // insecure by default: DO NOT UNKOMMENT!!!
- // file << "MapUrl /([^/]+/.+) content@ $1" << endl;
+ // select additional (not build in) javascript.
+ // WARNING: no path components with '.' in the name are allowed. Only
+ // the basename may contain dots and must end with '.js'
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ file << "MapUrl ^/js(/[^.]*)([^/]*\\.js) content@ " << configDir << "/js$1$2 text/javascript" << endl;
- // takes first path components without 'extension' when it does not
- // contain '.'
- // modified by 'tadi' -- verified with above, but not counterchecked yet!
- file << "MapUrl ^/([^./]+)(.*)? $1@" << endl;
+ // map to 'css/basename(uri)'
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ file << "MapUrl ^/css.*/(.+) content@ " << configDir << "/css/$1 text/css" << endl;
- file << "PropertyFile " << m_propertiesPath << endl;
- file << "SessionTimeout 86400" << endl;
- file << "DefaultContentType \"text/html; charset=" << LiveI18n().CharacterEncoding() << "\"" << endl;
+ // map to 'img/basename(uri)'
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ file << "MapUrl ^/img.*/(.+)\\.([^.]+) content@ " << configDir << "/img/$1.$2 image/$2" << endl;
- Setup::IpList const& ips = LiveSetup().GetServerIps();
- int port = LiveSetup().GetServerPort();
- for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
- file << "Listen " << *ip << " " << port << endl;
- }
+ // Map favicon.ico into img directory
+ file << "MapUrl ^/favicon.ico$ content@ " << configDir << "/img/favicon.ico image/x-icon" << endl;
-#ifdef TNTVERS7
- int s_port = LiveSetup().GetServerSslPort();
- string s_cert = LiveSetup().GetServerSslCert();
+ // insecure by default: DO NOT UNKOMMENT!!!
+ // file << "MapUrl /([^/]+/.+) content@ $1" << endl;
- if (s_cert.empty()) {
- s_cert = configDir + "/live.pem";
- }
+ // takes first path components without 'extension' when it does not
+ // contain '.'
+ // modified by 'tadi' -- verified with above, but not counterchecked yet!
+ file << "MapUrl ^/([^./]+)(.*)? $1@" << endl;
- if ( ifstream( s_cert.c_str() ) ) {
+ file << "PropertyFile " << m_propertiesPath << endl;
+ file << "SessionTimeout 86400" << endl;
+ file << "DefaultContentType \"text/html; charset=" << LiveI18n().CharacterEncoding() << "\"" << endl;
+
+ Setup::IpList const& ips = LiveSetup().GetServerIps();
+ int port = LiveSetup().GetServerPort();
for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
- file << "SslListen " << *ip << " " << s_port << " " << s_cert << endl;
+ file << "Listen " << *ip << " " << port << endl;
}
- }
- else {
- esyslog( "ERROR: %s: %s", s_cert.c_str(), strerror( errno ) );
+
+// not used any more see below: #ifdef TNTVERS7
+// not used any more see below: int s_port = LiveSetup().GetServerSslPort();
+// not used any more see below: string s_cert = LiveSetup().GetServerSslCert();
+// not used any more see below:
+// not used any more see below: if (s_cert.empty()) {
+// not used any more see below: s_cert = configDir + "/live.pem";
+// not used any more see below: }
+// not used any more see below:
+// not used any more see below: if ( ifstream( s_cert.c_str() ) ) {
+// not used any more see below: for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
+// not used any more see below: file << "SslListen " << *ip << " " << s_port << " " << s_cert << endl;
+// not used any more see below: }
+// not used any more see below: }
+// not used any more see below: else {
+// not used any more see below: esyslog( "ERROR: %s: %s", s_cert.c_str(), strerror( errno ) );
+// not used any more see below: }
+// not used any more see below: #endif
}
#endif
-}
-
-void TntConfig::WriteProperties()
-{
- ostringstream builder;
- builder << Plugin::GetConfigDirectory() << "/httpd.properties";
- m_propertiesPath = builder.str();
- ofstream file( m_propertiesPath.c_str(), ios::out | ios::trunc );
- if ( !file ) {
+#if TNTVERSION < 1606
+ void TntConfig::WriteProperties()
+ {
ostringstream builder;
- builder << "Can't open " << m_propertiesPath << " for writing: " << strerror( errno );
- throw runtime_error( builder.str() );
+ builder << Plugin::GetConfigDirectory() << "/httpd.properties";
+ m_propertiesPath = builder.str();
+
+ ofstream file( m_propertiesPath.c_str(), ios::out | ios::trunc );
+ if ( !file ) {
+ ostringstream builder;
+ builder << "Can't open " << m_propertiesPath << " for writing: " << strerror( errno );
+ throw runtime_error( builder.str() );
+ }
+
+ // XXX modularize
+ file << "rootLogger=" << LiveSetup().GetTntnetLogLevel() << endl;
+ file << "logger.tntnet=" << LiveSetup().GetTntnetLogLevel() << endl;
}
+#endif
+
+#if TNTVERSION >= 1606
+ void TntConfig::Configure(tnt::Tntnet& app) const
+ {
+ string const configDir(Plugin::GetConfigDirectory());
- // XXX modularize
- file << "rootLogger=" << LiveSetup().GetTntnetLogLevel() << endl;
- file << "logger.tntnet=" << LiveSetup().GetTntnetLogLevel() << endl;
-}
+ // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
+ // ------------------------------------------------------------------------
+ // These mapUrl statements are very security sensitive!
+ // A wrong mapping to content may allow retrieval of arbitrary files
+ // from your VDR system via live.
+ // Two meassures are taken against this in our implementation:
+ // 1. The MapUrls need to be checked regulary against possible exploits
+ // One tool to do this can be found here:
+ // http://www.lumadis.be/regex/test_regex.php
+ // Newly inserted MapUrls should be marked with author and confirmed
+ // by a second party. (use source code comments for this)
+ // 2. content.ecpp checks the given path to be
+ // a. an absolute path starting at /
+ // b. not containing ../ paths components
+ // In order to do so, the MapUrl statements must create absolute
+ // path arguments to content@
+ // ------------------------------------------------------------------------
+ // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++
+
+ app.mapUrl("^/$", "login");
+
+ // the following redirects vdr_request URL to the component
+ // specified by the action parameter.
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/vdr_request/([^.]+)", "$1");
-TntConfig const& TntConfig::Get()
-{
- static TntConfig instance;
- return instance;
-}
+ // the following redirects play_video URL to the content component.
+ // inserted by 'tadi' -- not verified, not counterchecked yet!
+ //app.mapUrl("^/vlc/(.+)", "static@tntnet")
+ // .setPathInfo("/$1")
+ // .pushArg(string("DocumentRoot=") + VideoDirectory);
+ // the following selects the theme specific 'theme.css' file
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/themes/([^/]*)/css.*/(.+\\.css)", "content")
+ .setPathInfo(configDir + "/themes/$1/css/$2")
+ .pushArg("text/css");
+
+ // the following rules provide a search scheme for images. The first
+ // rule where a image is found, terminates the search.
+ // 1. /themes/<theme>/img/<imgname>.<ext>
+ // 2. /img/<imgname>.<ext>
+ // deprecated: 3. <imgname>.<ext> (builtin images)
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/themes/([^/]*)/img.*/(.+)\\.(.+)", "content")
+ .setPathInfo(configDir + "/themes/$1/img/$2.$3")
+ .pushArg("image/$3");
+ app.mapUrl("^/themes/([^/]*)/img.*/(.+)\\.(.+)", "content")
+ .setPathInfo(configDir + "/img/$2.$3")
+ .pushArg("image/$3");
+ // deprecated: file << "MapUrl ^/themes/([^/]*)/img.*/(.+)\\.(.+) $2@" << endl;
+
+ // Epg images
+ string const epgImgPath(LiveSetup().GetEpgImageDir());
+ if (!epgImgPath.empty()) {
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/epgimages/([^/]*)\\.([^./]+)", "content")
+ .setPathInfo(epgImgPath + "/$1.$2")
+ .pushArg("image/$2");
+ }
+
+ // select additional (not build in) javascript.
+ // WARNING: no path components with '.' in the name are allowed. Only
+ // the basename may contain dots and must end with '.js'
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/js(/[^.]*)([^/]*\\.js)", "content")
+ .setPathInfo(configDir + "/js$1$2")
+ .pushArg("text/javascript");
+
+ // map to 'css/basename(uri)'
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/css.*/(.+)", "content")
+ .setPathInfo(configDir + "/css/$1")
+ .pushArg("text/css");
+
+ // map to 'img/basename(uri)'
+ // inserted by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/img.*/(.+)\\.([^.]+)", "content")
+ .setPathInfo(configDir + "/img/$1.$2")
+ .pushArg("image/$2");
+
+ // Map favicon.ico into img directory
+ app.mapUrl("^/favicon.ico$", "content")
+ .setPathInfo(configDir + "/img/favicon.ico")
+ .pushArg("image/x-icon");
+
+ // takes first path components without 'extension' when it does not
+ // contain '.'
+ // modified by 'tadi' -- verified with above, but not counterchecked yet!
+ app.mapUrl("^/([^./]+)(.*)?", "$1");
+
+ tnt::Sessionscope::setDefaultTimeout(86400);
+ tnt::HttpReply::setDefaultContentType(string("text/html; charset=") + LiveI18n().CharacterEncoding());
+
+ Setup::IpList const& ips = LiveSetup().GetServerIps();
+ int port = LiveSetup().GetServerPort();
+ for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
+ app.listen(*ip, port);
+ }
+
+#if TNTSSLSUPPORT
+ int s_port = LiveSetup().GetServerSslPort();
+ string s_cert = LiveSetup().GetServerSslCert();
+
+ if (s_cert.empty()) {
+ s_cert = configDir + "/live.pem";
+ }
+
+ if ( ifstream( s_cert.c_str() ) ) {
+ for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) {
+ app.sslListen(s_cert, s_cert, *ip, s_port);
+ }
+ }
+ else {
+ esyslog( "ERROR: %s: %s", s_cert.c_str(), strerror( errno ) );
+ }
+#endif // TNTSSLSUPPORT
+
+ std::istringstream logConf(
+ "rootLogger=" + LiveSetup().GetTntnetLogLevel() + "\n"
+ // "logger.tntnet.static=DEBUG\n"
+ // "logger.cxxtools.net.tcp=DEBUG\n"
+ );
+ log_init(logConf);
+ }
+#endif
+
+ TntConfig const& TntConfig::Get()
+ {
+ static TntConfig instance;
+ return instance;
+ }
} // namespace vdrlive