MythTV
master
libs
libmythupnp
htmlserver.cpp
Go to the documentation of this file.
1
// Program Name: htmlserver.cpp
3
// Created : Mar. 9, 2011
4
//
5
// Purpose : Http server extension to serve up static html content
6
//
7
// Copyright (c) 2011 David Blain <dblain@mythtv.org>
8
//
9
// Licensed under the GPL v2 or later, see COPYING for details
10
//
12
13
#include "
mythlogging.h
"
14
#include "
htmlserver.h
"
15
#include "
storagegroup.h
"
16
#include "
httprequest.h
"
17
18
#include "
serviceHosts/rttiServiceHost.h
"
19
20
#include <QFileInfo>
21
#include <QDir>
22
#include <QTextStream>
23
#include <QUuid>
24
26
//
28
29
HtmlServerExtension::HtmlServerExtension
(
const
QString &sSharePath,
30
const
QString &sApplicationPrefix)
31
:
HttpServerExtension
(
"Html"
, sSharePath),
32
m_indexFilename(sApplicationPrefix +
"index"
)
33
{
34
LOG
(VB_HTTP, LOG_INFO, QString(
"HtmlServerExtension() - SharePath = %1"
)
35
.
arg
(
m_sSharePath
));
36
m_scripting
.
SetResourceRootPath
(
m_sSharePath
);
37
38
// ----------------------------------------------------------------------
39
// Register Rtti with QtScript Engine.
40
// Rtti exposes internal enums complete with translations for use in scripts
41
// ----------------------------------------------------------------------
42
43
QScriptEngine *pEngine =
ScriptEngine
();
44
pEngine->globalObject().setProperty(
"Rtti"
,
45
pEngine->scriptValueFromQMetaObject<
ScriptableRtti
>() );
46
}
47
49
//
51
52
bool
HtmlServerExtension::ProcessRequest
(
HTTPRequest
*pRequest )
53
{
54
if
(pRequest)
55
{
56
if
( !pRequest->
m_sBaseUrl
.startsWith(
"/"
))
57
return
(
false
);
58
59
if
((pRequest->
m_eType
!=
RequestTypeGet
) &&
60
(pRequest->
m_eType
!=
RequestTypeHead
) &&
61
(pRequest->
m_eType
!=
RequestTypePost
))
62
{
63
pRequest->
m_eResponseType
=
ResponseTypeHTML
;
64
pRequest->
m_nResponseStatus
= 405;
// Method not allowed
65
// Conservative list, we can't really know what methods we
66
// actually allow for an arbitrary resource without some sort of
67
// high maintenance database
68
pRequest->
m_response
.write( pRequest->
GetResponsePage
() );
69
pRequest->
SetResponseHeader
(
"Allow"
,
"GET, HEAD"
);
70
return
true
;
71
}
72
73
bool
bStorageGroupFile =
false
;
74
QFileInfo oInfo(
m_sSharePath
+ pRequest->
m_sResourceUrl
);
75
76
if
(oInfo.isDir())
77
{
78
QString sIndexFileName = oInfo.filePath() +
m_indexFilename
+
".qsp"
;
79
80
if
(QFile::exists( sIndexFileName ))
81
oInfo.setFile( sIndexFileName );
82
else
83
oInfo.setFile( oInfo.filePath() +
m_indexFilename
+
".html"
);
84
}
85
86
if
(pRequest->
m_sResourceUrl
.startsWith(
"/StorageGroup/"
))
87
{
88
StorageGroup
oGroup(pRequest->
m_sResourceUrl
.section(
'/'
, 2, 2));
89
QString sFile =
90
oGroup.
FindFile
(pRequest->
m_sResourceUrl
.section(
'/'
, 3));
91
if
(!sFile.isEmpty())
92
{
93
oInfo.setFile(sFile);
94
bStorageGroupFile =
true
;
95
}
96
}
97
98
if
(bStorageGroupFile || oInfo.exists() )
99
{
100
QString sResName = oInfo.canonicalFilePath();
101
102
// --------------------------------------------------------------
103
// Checking for url's that contain ../ or similar.
104
// --------------------------------------------------------------
105
106
if
(( bStorageGroupFile ) ||
107
(sResName.startsWith(
m_sSharePath
, Qt::CaseInsensitive )))
108
{
109
if
(oInfo.exists())
110
{
111
if
(oInfo.isSymLink())
112
sResName = oInfo.symLinkTarget();
113
114
// ------------------------------------------------------
115
// CSP Nonce
116
// ------------------------------------------------------
117
QByteArray cspNonce = QUuid::createUuid().toByteArray().toBase64();
118
cspNonce = cspNonce.mid(1, cspNonce.length() - 2);
// UUID, with braces removed
119
120
// ------------------------------------------------------
121
// Is this a Qt Server Page (File contains script)...
122
// ------------------------------------------------------
123
124
QString sSuffix = oInfo.suffix().toLower();
125
126
QString sMimeType =
HTTPRequest::GetMimeType
(sSuffix);
127
128
if
(sMimeType ==
"text/html"
)
129
pRequest->
m_eResponseType
=
ResponseTypeHTML
;
130
else
if
(sMimeType ==
"text/xml"
)
131
pRequest->
m_eResponseType
=
ResponseTypeXML
;
132
else
if
(sMimeType ==
"application/javascript"
)
133
pRequest->
m_eResponseType
=
ResponseTypeJS
;
134
else
if
(sMimeType ==
"text/css"
)
135
pRequest->
m_eResponseType
=
ResponseTypeCSS
;
136
else
if
(sMimeType ==
"text/plain"
)
137
pRequest->
m_eResponseType
=
ResponseTypeText
;
138
else
if
(sMimeType ==
"image/svg+xml"
&&
139
sSuffix !=
"svgz"
)
// svgz are pre-compressed
140
pRequest->
m_eResponseType
=
ResponseTypeSVG
;
141
142
// ---------------------------------------------------------
143
// Force IE into 'standards' mode
144
// ---------------------------------------------------------
145
pRequest->
SetResponseHeader
(
"X-UA-Compatible"
,
"IE=Edge"
);
146
147
// ---------------------------------------------------------
148
// SECURITY: Set X-Content-Type-Options to 'nosniff'
149
//
150
// IE only for now. Prevents browsers ignoring the
151
// Content-Type header we supply and potentially executing
152
// malicious script embedded in an image or css file.
153
//
154
// Yes, really, you need to explicitly disable this sort of
155
// dangerous behaviour in 2015!
156
// ---------------------------------------------------------
157
pRequest->
SetResponseHeader
(
"X-Content-Type-Options"
,
158
"nosniff"
);
159
160
// ---------------------------------------------------------
161
// SECURITY: Set Content Security Policy
162
//
163
// *No external content allowed*
164
//
165
// This is an important safeguard. Third party content
166
// should never be permitted. It compromises security,
167
// privacy and violates the key principal that the
168
// WebFrontend should work on an isolated network with no
169
// internet access. Keep all content hosted locally!
170
// ---------------------------------------------------------
171
172
// For now the following are disabled as we use xhr to
173
// trigger playback on frontends if we switch to triggering
174
// that through an internal request then these would be
175
// better enabled
176
//"default-src 'self'; "
177
//"connect-src 'self' https://services.mythtv.org; "
178
179
// FIXME: unsafe-inline should be phased out, replaced by nonce-{csp_nonce} but it requires
180
// all inline event handlers and style attributes to be removed ...
181
QString cspPolicy =
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://services.mythtv.org; "
// QString('nonce-%1').arg(QString(cspNonce))
182
"style-src 'self' 'unsafe-inline'; "
183
"frame-src 'self'; "
184
"object-src 'self'; "
// TODO: When we no longer require flash for some browsers, change this to 'none'
185
"media-src 'self'; "
186
"font-src 'self'; "
187
"img-src 'self'; "
188
"form-action 'self'; "
189
"frame-ancestors 'self'; "
;
190
191
pRequest->
SetResponseHeader
(
"X-XSS-Protection"
,
"1; mode=block"
);
192
193
// For standards compliant browsers
194
pRequest->
SetResponseHeader
(
"Content-Security-Policy"
,
195
cspPolicy);
196
// For Internet Explorer
197
pRequest->
SetResponseHeader
(
"X-Content-Security-Policy"
,
198
cspPolicy);
199
200
if
((sSuffix ==
"qsp"
) ||
201
(sSuffix ==
"qxml"
) ||
202
(sSuffix ==
"qjs"
))
203
{
204
QTextStream stream( &pRequest->
m_response
);
205
206
m_scripting
.
EvaluatePage
( &stream, sResName, pRequest, cspNonce);
207
208
return
true
;
209
}
210
211
// ------------------------------------------------------
212
// Return the file.
213
// ------------------------------------------------------
214
215
pRequest->
FormatFileResponse
( sResName );
216
217
return
true
;
218
}
219
}
220
}
221
222
// force return as a 404...
223
pRequest->
FormatFileResponse
(
""
);
224
}
225
226
return
(
true
);
227
}
228
HTTPRequest::m_sBaseUrl
QString m_sBaseUrl
Definition:
httprequest.h:125
HTTPRequest
Definition:
httprequest.h:107
ResponseTypeCSS
@ ResponseTypeCSS
Definition:
httprequest.h:79
HTTPRequest::m_sResourceUrl
QString m_sResourceUrl
Definition:
httprequest.h:126
StorageGroup::FindFile
QString FindFile(const QString &filename)
Definition:
storagegroup.cpp:602
arg
arg(title).arg(filename).arg(doDelete))
ResponseTypeJS
@ ResponseTypeJS
Definition:
httprequest.h:78
RequestTypePost
@ RequestTypePost
Definition:
httprequest.h:49
ScriptableRtti
Definition:
rtti.h:63
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition:
mythlogging.h:23
HtmlServerExtension::m_indexFilename
QString m_indexFilename
Definition:
htmlserver.h:32
HTTPRequest::m_nResponseStatus
long m_nResponseStatus
Definition:
httprequest.h:150
mythlogging.h
HTTPRequest::GetResponsePage
QByteArray GetResponsePage(void)
Definition:
httprequest.cpp:1016
HTTPRequest::GetMimeType
static QString GetMimeType(const QString &sFileExtension)
Definition:
httprequest.cpp:1045
RequestTypeHead
@ RequestTypeHead
Definition:
httprequest.h:48
storagegroup.h
htmlserver.h
rttiServiceHost.h
ResponseTypeXML
@ ResponseTypeXML
Definition:
httprequest.h:76
HtmlServerExtension::HtmlServerExtension
HtmlServerExtension(const QString &sSharePath, const QString &sApplicationPrefix)
Definition:
htmlserver.cpp:29
ResponseTypeHTML
@ ResponseTypeHTML
Definition:
httprequest.h:77
ResponseTypeText
@ ResponseTypeText
Definition:
httprequest.h:80
HTTPRequest::FormatFileResponse
void FormatFileResponse(const QString &sFileName)
Definition:
httprequest.cpp:859
HTTPRequest::SetResponseHeader
void SetResponseHeader(const QString &sKey, const QString &sValue, bool replace=false)
Definition:
httprequest.cpp:2160
HTTPRequest::m_eResponseType
HttpResponseType m_eResponseType
Definition:
httprequest.h:147
ServerSideScripting::SetResourceRootPath
QString SetResourceRootPath(const QString &path)
Definition:
serverSideScripting.cpp:101
StorageGroup
Definition:
storagegroup.h:11
ServerSideScripting::EvaluatePage
bool EvaluatePage(QTextStream *pOutStream, const QString &sFileName, HTTPRequest *pRequest, const QByteArray &cspToken)
Definition:
serverSideScripting.cpp:150
HtmlServerExtension::ScriptEngine
QScriptEngine * ScriptEngine()
Definition:
htmlserver.h:47
HtmlServerExtension::m_scripting
ServerSideScripting m_scripting
Definition:
htmlserver.h:31
HtmlServerExtension::ProcessRequest
bool ProcessRequest(HTTPRequest *pRequest) override
Definition:
htmlserver.cpp:52
ResponseTypeSVG
@ ResponseTypeSVG
Definition:
httprequest.h:81
RequestTypeGet
@ RequestTypeGet
Definition:
httprequest.h:47
HttpServerExtension
Definition:
httpserver.h:71
httprequest.h
HTTPRequest::m_response
QBuffer m_response
Definition:
httprequest.h:155
HttpServerExtension::m_sSharePath
QString m_sSharePath
Definition:
httpserver.h:78
HTTPRequest::m_eType
HttpRequestType m_eType
Definition:
httprequest.h:118
Generated on Sun Jan 24 2021 03:17:05 for MythTV by
1.8.17