13 #include <QCoreApplication>
17 #include <QVariantMap>
25 QScriptValue
formatStr(QScriptContext *context, QScriptEngine *interpreter);
31 QScriptValue
formatStr(QScriptContext *context, QScriptEngine *interpreter)
33 unsigned int count = context->argumentCount();
36 return {interpreter, QString()};
39 return {interpreter, context->argument(0).toString()};
41 QString result = context->argument(0).toString();
42 for (
unsigned int i = 1; i < count; i++)
43 result.replace(QString(
"%%1").arg(i), context->argument(i).toString());
45 return {interpreter, result};
64 m_engine.installTranslatorFunctions();
71 m_engine.globalObject().setProperty(
"formatStr", qsFormatStr);
118 const QMetaObject *pMetaObject,
119 QScriptEngine::FunctionSignature pFunction)
122 QScriptValue ctor =
m_engine.newFunction( pFunction );
124 QScriptValue metaObject =
m_engine.newQMetaObject( pMetaObject, ctor );
125 m_engine.globalObject().setProperty( sName, metaObject );
169 QFileInfo fileInfo ( sFileName );
170 QDateTime dtLastModified = fileInfo.lastModified();
173 if ((pInfo ==
nullptr) || (pInfo->
m_dtTimeStamp != dtLastModified ))
177 QScriptValue func =
m_engine.evaluate( sCode, sFileName );
179 if (
m_engine.hasUncaughtException() )
181 LOG(VB_GENERAL, LOG_ERR,
182 QString(
"Uncaught exception loading QSP File: %1 - (line %2) %3")
184 .arg(
m_engine.uncaughtExceptionLineNumber())
185 .arg(
m_engine.uncaughtException().toString()));
191 if (pInfo !=
nullptr)
198 pInfo =
new ScriptInfo( func, dtLastModified );
213 static const QRegularExpression validChars {
214 R
"(^([a-zA-Z]|_|\$)(\w|\$)+$)",
215 QRegularExpression::UseUnicodePropertiesOption };
218 QString prevArrayName = "";
220 for (
auto it = mapParams.cbegin(); it != mapParams.cend(); ++it)
222 const QString& key = it.key();
223 QVariant value = QVariant(it.value());
226 if (key.contains(
"["))
228 QString arrayName = key.section(
'[',0,0);
229 QString arrayKey = key.section(
'[',1,1);
231 if (prevArrayName != arrayName)
233 if (!array.isEmpty())
235 params.insert(prevArrayName, QVariant(array));
238 prevArrayName = arrayName;
241 auto match = validChars.match(arrayKey);
242 if (!match.hasMatch())
245 array.insert(arrayKey, value);
247 if ((it + 1) != mapParams.cend())
251 if (!array.isEmpty())
253 params.insert(prevArrayName, QVariant(array));
258 auto match = validChars.match(key);
259 if (!match.hasMatch())
262 params.insert(key, value);
272 QVariantMap requestHeaders;
273 for (
auto it = mapHeaders.begin(); it != mapHeaders.end(); ++it)
275 QString key = it.key();
276 key = key.replace(
'-',
'_');
277 QVariant value = QVariant(it.value());
279 auto match = validChars.match(key);
280 if (!match.hasMatch())
283 requestHeaders.insert(key, value);
292 QVariantMap requestCookies;
293 for (
auto it = mapCookies.begin(); it != mapCookies.end(); ++it)
295 QString key = it.key();
296 key = key.replace(
'-',
'_');
297 QVariant value = QVariant(it.value());
299 auto match = validChars.match(key);
300 if (!match.hasMatch())
303 requestCookies.insert(key, value);
311 QVariantMap serverVars;
313 serverVars.insert(
"REQUEST_METHOD", QVariant(pRequest->
GetRequestType()));
314 serverVars.insert(
"SCRIPT_NAME", QVariant(sFileName));
315 serverVars.insert(
"REMOTE_ADDR", QVariant(pRequest->
GetPeerAddress()));
316 serverVars.insert(
"SERVER_NAME", QVariant(pRequest->
GetHostName()));
317 serverVars.insert(
"SERVER_PORT", QVariant(pRequest->
GetHostPort()));
323 if (clientIP.protocol() == QAbstractSocket::IPv4Protocol)
325 serverVars.insert(
"IP_PROTOCOL",
"IPv4");
327 else if (clientIP.protocol() == QAbstractSocket::IPv6Protocol)
329 serverVars.insert(
"IP_PROTOCOL",
"IPv6");
332 if (((clientIP.protocol() == QAbstractSocket::IPv4Protocol) &&
333 (clientIP.isInSubnet(QHostAddress(
"172.16.0.0"), 12) ||
334 clientIP.isInSubnet(QHostAddress(
"192.168.0.0"), 16) ||
335 clientIP.isInSubnet(QHostAddress(
"10.0.0.0"), 8))) ||
336 ((clientIP.protocol() == QAbstractSocket::IPv6Protocol) &&
337 clientIP.isInSubnet(serverIP, 64)))
339 serverVars.insert(
"CLIENT_NETWORK",
"local");
343 serverVars.insert(
"CLIENT_NETWORK",
"remote");
356 QVariantMap sessionVars;
357 sessionVars.insert(
"username", session.
GetUserName());
358 sessionVars.insert(
"userid", session.
GetUserId());
368 m_engine.globalObject().setProperty(
"Parameters",
370 m_engine.globalObject().setProperty(
"RequestHeaders",
371 m_engine.toScriptValue(requestHeaders));
372 QVariantMap respHeaderMap;
373 m_engine.globalObject().setProperty(
"ResponseHeaders",
374 m_engine.toScriptValue(respHeaderMap));
375 m_engine.globalObject().setProperty(
"Server",
376 m_engine.toScriptValue(serverVars));
377 m_engine.globalObject().setProperty(
"Session",
378 m_engine.toScriptValue(sessionVars));
379 QScriptValue qsCspToken =
m_engine.toScriptValue(cspToken);
380 m_engine.globalObject().setProperty(
"CSP_NONCE", qsCspToken);
389 QScriptValueList
args;
393 QScriptValue ret = pInfo->
m_oFunc.call( QScriptValue(),
args );
397 QScriptValue lineNo = ret.property(
"lineNumber" );
399 LOG(VB_GENERAL, LOG_ERR,
400 QString(
"Error calling QSP File: %1(%2) - %3")
402 .arg( lineNo.toInt32 () )
403 .arg( ret .toString() ));
409 if (
m_engine.hasUncaughtException())
411 LOG(VB_GENERAL, LOG_ERR,
412 QString(
"Uncaught exception calling QSP File: %1(%2) - %3")
414 .arg(
m_engine.uncaughtExceptionLineNumber() )
415 .arg(
m_engine.uncaughtException().toString()));
423 LOG(VB_GENERAL, LOG_ERR,
424 QString(
"Exception while evaluating QSP File: %1") .arg(sFileName));
431 QVariantMap responseHeaders;
432 responseHeaders =
m_engine.fromScriptValue< QVariantMap >
433 (
m_engine.globalObject().property(
"ResponseHeaders"));
434 QVariantMap::iterator it;
435 for (it = responseHeaders.begin(); it != responseHeaders.end(); ++it)
449 bool bInCode =
false;
451 QTextStream sCode( &sBuffer );
453 QFile scriptFile( sFileName );
455 if (!scriptFile.open( QIODevice::ReadOnly ))
456 throw "Unable to open file";
460 QTextStream stream( &scriptFile );
461 QString sTransBuffer;
463 sCode <<
"(function( os, ARGS ) {\n";
466 while( !stream.atEnd() )
468 QString sLine = stream.readLine();
470 bInCode =
ProcessLine( sCode, sLine, bInCode, sTransBuffer );
473 sCode <<
"} catch( err ) { return err; }\n";
478 LOG(VB_GENERAL, LOG_ERR,
479 QString(
"Exception while reading QSP File: %1") .arg(sFileName));
496 QFile scriptFile( sFileName );
498 if (!scriptFile.open( QIODevice::ReadOnly ))
499 throw "Unable to open file";
503 QTextStream stream( &scriptFile );
505 sCode = stream.readAll();
509 LOG(VB_GENERAL, LOG_ERR,
510 QString(
"Exception while Reading File Contents File: %1") .arg(sFileName));
525 QString &sTransBuffer )
const
527 QString sLowerLine = sLine.toLower();
529 if (!sTransBuffer.isEmpty())
531 int nEndTransPos = sLowerLine.indexOf(
"</i18n>");
533 if (nEndTransPos == -1)
535 sTransBuffer.append(
" ");
536 sTransBuffer.append(sLine);
540 if (nEndTransPos > 0)
541 sTransBuffer.append(
" ");
543 sTransBuffer.append(sLine.left(nEndTransPos).trimmed());
545 QCoreApplication::translate(
"HtmlUI", sTransBuffer.trimmed().toLocal8Bit().data());
546 trStr.replace(
'"',
"\\\"" );
547 sCode <<
"os.write( \"" << trStr <<
"\" );\n";
550 if (nEndTransPos == (sLine.length() - 7))
553 sLine = sLine.right(sLine.length() - (nEndTransPos + 7));
556 int nStartTransPos = sLowerLine.indexOf(
"<i18n>");
557 if (nStartTransPos != -1)
559 int nEndTransPos = sLowerLine.indexOf(
"</i18n>");
560 if (nEndTransPos != -1)
562 QString patStr = sLine.mid(nStartTransPos,
563 (nEndTransPos + 7 - nStartTransPos));
564 QString repStr = patStr.mid(6, patStr.length() - 13).trimmed();
565 sLine.replace(patStr, QCoreApplication::translate(
"HtmlUI", repStr.toLocal8Bit().data()));
566 return ProcessLine(sCode, sLine, bInCode, sTransBuffer);
570 sTransBuffer.append(sLine.mid(nStartTransPos + 6).trimmed());
571 sLine = sLine.left(nStartTransPos);
577 bool bMatchFound =
false;
579 QString sExpecting = bInCode ?
"%>" :
"<%";
580 bool bNewLine = !(sLine.startsWith( sExpecting ));
582 while (nStartPos < sLine.length())
584 nEndPos = sLine.length() - 1;
586 sExpecting = bInCode ?
"%>" :
"<%";
587 nMatchPos = sLine.indexOf( sExpecting, nStartPos );
595 nMatchPos = nEndPos + 1;
607 QString sSegment = sLine.mid( nStartPos, nMatchPos - nStartPos );
609 if ( !sSegment.isEmpty())
615 if (sSegment.startsWith(
"=" ))
619 sCode <<
"os.write( " << sSegment.mid( 1 ) <<
" ); "
622 else if (sSegment.startsWith(
"import" ))
632 QStringList sParts = sSegment.split(
' ', Qt::SkipEmptyParts );
633 if (sParts.length() > 1 )
635 QString sFileName = sParts[1].mid( 1, sParts[1].length() - 2 );
646 LOG(VB_GENERAL, LOG_ERR,
647 QString(
"ServerSideScripting::ProcessLine 'import' - File not found: %1%2")
653 LOG(VB_GENERAL, LOG_ERR,
654 QString(
"ServerSideScripting::ProcessLine 'import' - Malformed [%1]")
661 sCode << sSegment <<
"\n";
671 sSegment.replace(
'"',
"\\\"" );
673 sCode <<
"os.write( \"" << sSegment <<
"\" );\n";
685 nStartPos = nMatchPos + 2;
688 if ((bNewLine) && !bInCode )
689 sCode <<
"os.writeln( \"\" );\n";