MythTV  master
serverSideScripting.cpp
Go to the documentation of this file.
1 // Program Name: serverSideScripting.cpp
3 // Created : Mar. 22, 2011
4 //
5 // Purpose : Server Side Scripting support for Html Server
6 //
7 // Copyright (c) 2011 David Blain <dblain@mythtv.org>
8 //
9 // Licensed under the GPL v2 or later, see LICENSE for details
10 //
12 
13 #include <QCoreApplication>
14 #include <QFile>
15 #include <QFileInfo>
16 #include <QVariant>
17 #include <QVariantMap>
18 
21 
22 #include "httpserver.h"
23 #include "serverSideScripting.h"
24 
25 QScriptValue formatStr(QScriptContext *context, QScriptEngine *interpreter);
26 
28 //
30 
31 QScriptValue formatStr(QScriptContext *context, QScriptEngine *interpreter)
32 {
33  unsigned int count = context->argumentCount();
34 
35  if (count == 0)
36  return {interpreter, QString()};
37 
38  if (count == 1)
39  return {interpreter, context->argument(0).toString()};
40 
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());
44 
45  return {interpreter, result};
46 }
47 
49 //
51 
53 {
54  Lock();
55 
56 #ifdef _WIN32
57  m_debugger.attachTo( &m_engine );
58 #endif
59 
60  // ----------------------------------------------------------------------
61  // Enable Translation functions
62  // ----------------------------------------------------------------------
63 
64  m_engine.installTranslatorFunctions();
65 
66  // ----------------------------------------------------------------------
67  // Register C++ functions
68  // ----------------------------------------------------------------------
69 
70  QScriptValue qsFormatStr = m_engine.newFunction(formatStr);
71  m_engine.globalObject().setProperty("formatStr", qsFormatStr);
72 
73  // ----------------------------------------------------------------------
74  // Add Scriptable Objects
75  // ----------------------------------------------------------------------
76 
77  // Q_SCRIPT_DECLARE_QMETAOBJECT( DTC::MythService, QObject*)
78  // QScriptValue oClass = engine.scriptValueFromQMetaObject< DTC::MythService >();
79  // engine.globalObject().setProperty("Myth", oClass);
80  Unlock();
81 }
82 
84 //
86 
88 {
89  Lock();
90 
91  for (const auto *script : std::as_const(m_mapScripts))
92  delete script;
93 
94  m_mapScripts.clear();
95  Unlock();
96 }
97 
99 //
101 
102 QString ServerSideScripting::SetResourceRootPath( const QString &path )
103 {
104  Lock();
105  QString sOrig = m_sResRootPath;
106 
107  m_sResRootPath = path;
108  Unlock();
109 
110  return sOrig;
111 }
112 
114 //
116 
118  const QMetaObject *pMetaObject,
119  QScriptEngine::FunctionSignature pFunction)
120 {
121  Lock();
122  QScriptValue ctor = m_engine.newFunction( pFunction );
123 
124  QScriptValue metaObject = m_engine.newQMetaObject( pMetaObject, ctor );
125  m_engine.globalObject().setProperty( sName, metaObject );
126  Unlock();
127 }
128 
130 //
132 
134 {
135  ScriptInfo *pInfo = nullptr;
136 
137  Lock();
138 
139  if ( m_mapScripts.contains( sFileName ) )
140  pInfo = m_mapScripts[ sFileName ];
141 
142  Unlock();
143 
144  return pInfo;
145 }
146 
148 //
150 
151 bool ServerSideScripting::EvaluatePage( QTextStream *pOutStream, const QString &sFileName,
152  HTTPRequest *pRequest, const QByteArray &cspToken)
153 {
154  try
155  {
156 
157  ScriptInfo *pInfo = nullptr;
158 
159  // ------------------------------------------------------------------
160  // See if page has already been loaded
161  // ------------------------------------------------------------------
162 
163  pInfo = GetLoadedScript( sFileName );
164 
165  // ------------------------------------------------------------------
166  // Load Script File and Create Function
167  // ------------------------------------------------------------------
168 
169  QFileInfo fileInfo ( sFileName );
170  QDateTime dtLastModified = fileInfo.lastModified();
171 
172  Lock();
173  if ((pInfo == nullptr) || (pInfo->m_dtTimeStamp != dtLastModified ))
174  {
175  QString sCode = CreateMethodFromFile( sFileName );
176 
177  QScriptValue func = m_engine.evaluate( sCode, sFileName );
178 
179  if ( m_engine.hasUncaughtException() )
180  {
181  LOG(VB_GENERAL, LOG_ERR,
182  QString("Uncaught exception loading QSP File: %1 - (line %2) %3")
183  .arg(sFileName)
184  .arg(m_engine.uncaughtExceptionLineNumber())
185  .arg(m_engine.uncaughtException().toString()));
186 
187  Unlock();
188  return false;
189  }
190 
191  if (pInfo != nullptr)
192  {
193  pInfo->m_oFunc = func;
194  pInfo->m_dtTimeStamp = dtLastModified;
195  }
196  else
197  {
198  pInfo = new ScriptInfo( func, dtLastModified );
199  m_mapScripts[ sFileName ] = pInfo;
200  }
201  }
202 
203  // ------------------------------------------------------------------
204  // Build array of arguments passed to script
205  // ------------------------------------------------------------------
206 
207  QStringMap mapParams = pRequest->m_mapParams;
208 
209  // Valid characters for object property names must contain only
210  // word characters and numbers, _ and $
211  // They must not start with a number - to simplify the regexp, we
212  // restrict the first character to the English alphabet
213  static const QRegularExpression validChars {
214  R"(^([a-zA-Z]|_|\$)(\w|\$)+$)",
215  QRegularExpression::UseUnicodePropertiesOption };
216 
217  QVariantMap params;
218  QString prevArrayName = "";
219  QVariantMap array;
220  for (auto it = mapParams.cbegin(); it != mapParams.cend(); ++it)
221  {
222  const QString& key = it.key();
223  QVariant value = QVariant(it.value());
224 
225  // PHP Style parameter array
226  if (key.contains("["))
227  {
228  QString arrayName = key.section('[',0,0);
229  QString arrayKey = key.section('[',1,1);
230  arrayKey.chop(1); // Remove trailing ]
231  if (prevArrayName != arrayName) // New or different array
232  {
233  if (!array.isEmpty())
234  {
235  params.insert(prevArrayName, QVariant(array));
236  array.clear();
237  }
238  prevArrayName = arrayName;
239  }
240 
241  auto match = validChars.match(arrayKey);
242  if (!match.hasMatch()) // Discard anything that isn't valid for now
243  continue;
244 
245  array.insert(arrayKey, value);
246 
247  if ((it + 1) != mapParams.cend())
248  continue;
249  }
250 
251  if (!array.isEmpty())
252  {
253  params.insert(prevArrayName, QVariant(array));
254  array.clear();
255  }
256  // End Array handling
257 
258  auto match = validChars.match(key);
259  if (!match.hasMatch()) // Discard anything that isn't valid for now
260  continue;
261 
262  params.insert(key, value);
263 
264  }
265 
266  // ------------------------------------------------------------------
267  // Build array of request headers
268  // ------------------------------------------------------------------
269 
270  QStringMap mapHeaders = pRequest->m_mapHeaders;
271 
272  QVariantMap requestHeaders;
273  for (auto it = mapHeaders.begin(); it != mapHeaders.end(); ++it)
274  {
275  QString key = it.key();
276  key = key.replace('-', '_'); // May be other valid chars in a request header that we need to replace
277  QVariant value = QVariant(it.value());
278 
279  auto match = validChars.match(key);
280  if (!match.hasMatch()) // Discard anything that isn't valid for now
281  continue;
282 
283  requestHeaders.insert(key, value);
284  }
285 
286  // ------------------------------------------------------------------
287  // Build array of cookies
288  // ------------------------------------------------------------------
289 
290  QStringMap mapCookies = pRequest->m_mapCookies;
291 
292  QVariantMap requestCookies;
293  for (auto it = mapCookies.begin(); it != mapCookies.end(); ++it)
294  {
295  QString key = it.key();
296  key = key.replace('-', '_'); // May be other valid chars in a request header that we need to replace
297  QVariant value = QVariant(it.value());
298 
299  auto match = validChars.match(key);
300  if (!match.hasMatch()) // Discard anything that isn't valid for now
301  continue;
302 
303  requestCookies.insert(key, value);
304  }
305 
306  // ------------------------------------------------------------------
307  // Build array of information from the server e.g. client IP
308  // See RFC 3875 - The Common Gateway Interface
309  // ------------------------------------------------------------------
310 
311  QVariantMap serverVars;
312  //serverVars.insert("QUERY_STRING", QVariant())
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()));
318  serverVars.insert("SERVER_PROTOCOL", QVariant(pRequest->GetRequestProtocol()));
319  serverVars.insert("SERVER_SOFTWARE", QVariant(HttpServer::GetServerVersion()));
320 
321  QHostAddress clientIP = QHostAddress(pRequest->GetPeerAddress());
322  QHostAddress serverIP = QHostAddress(pRequest->GetHostAddress());
323  if (clientIP.protocol() == QAbstractSocket::IPv4Protocol)
324  {
325  serverVars.insert("IP_PROTOCOL", "IPv4");
326  }
327  else if (clientIP.protocol() == QAbstractSocket::IPv6Protocol)
328  {
329  serverVars.insert("IP_PROTOCOL", "IPv6");
330  }
331 
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))) // default subnet size is assumed to be /64
338  {
339  serverVars.insert("CLIENT_NETWORK", "local");
340  }
341  else
342  {
343  serverVars.insert("CLIENT_NETWORK", "remote");
344  }
345 
346  // ------------------------------------------------------------------
347  // User Session information
348  //
349  // SECURITY
350  // The session token and password digest are considered sensitive on
351  // unencrypted connections and therefore must never be included in the
352  // HTML. An intercepted session token or password digest can be used
353  // to login or hijack an existing session.
354  // ------------------------------------------------------------------
355  MythUserSession session = pRequest->m_userSession;
356  QVariantMap sessionVars;
357  sessionVars.insert("username", session.GetUserName());
358  sessionVars.insert("userid", session.GetUserId());
359  sessionVars.insert("created", session.GetSessionCreated());
360  sessionVars.insert("lastactive", session.GetSessionLastActive());
361  sessionVars.insert("expires", session.GetSessionExpires());
362 
363  // ------------------------------------------------------------------
364  // Add the arrays (objects) we've just created to the global scope
365  // They may be accessed as 'Server.REMOTE_ADDR'
366  // ------------------------------------------------------------------
367 
368  m_engine.globalObject().setProperty("Parameters",
369  m_engine.toScriptValue(params));
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);
381 
382 
383  // ------------------------------------------------------------------
384  // Execute function to render output
385  // ------------------------------------------------------------------
386 
387  OutputStream outStream( pOutStream );
388 
389  QScriptValueList args;
390  args << m_engine.newQObject( &outStream );
391  args << m_engine.toScriptValue(params);
392 
393  QScriptValue ret = pInfo->m_oFunc.call( QScriptValue(), args );
394 
395  if (ret.isError())
396  {
397  QScriptValue lineNo = ret.property( "lineNumber" );
398 
399  LOG(VB_GENERAL, LOG_ERR,
400  QString("Error calling QSP File: %1(%2) - %3")
401  .arg(sFileName)
402  .arg( lineNo.toInt32 () )
403  .arg( ret .toString() ));
404  Unlock();
405  return false;
406 
407  }
408 
409  if (m_engine.hasUncaughtException())
410  {
411  LOG(VB_GENERAL, LOG_ERR,
412  QString("Uncaught exception calling QSP File: %1(%2) - %3")
413  .arg(sFileName)
414  .arg(m_engine.uncaughtExceptionLineNumber() )
415  .arg(m_engine.uncaughtException().toString()));
416  Unlock();
417  return false;
418  }
419  Unlock();
420  }
421  catch(...)
422  {
423  LOG(VB_GENERAL, LOG_ERR,
424  QString("Exception while evaluating QSP File: %1") .arg(sFileName));
425 
426  Unlock();
427  return false;
428  }
429 
430  // Apply any custom headers defined by the script
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)
436  {
437  pRequest->SetResponseHeader(it.key(), it.value().toString(), true);
438  }
439 
440  return true;
441 }
442 
444 //
446 
447 QString ServerSideScripting::CreateMethodFromFile( const QString &sFileName ) const
448 {
449  bool bInCode = false;
450  QString sBuffer;
451  QTextStream sCode( &sBuffer );
452 
453  QFile scriptFile( sFileName );
454 
455  if (!scriptFile.open( QIODevice::ReadOnly ))
456  throw "Unable to open file";
457 
458  try
459  {
460  QTextStream stream( &scriptFile );
461  QString sTransBuffer;
462 
463  sCode << "(function( os, ARGS ) {\n";
464  sCode << "try {\n";
465 
466  while( !stream.atEnd() )
467  {
468  QString sLine = stream.readLine();
469 
470  bInCode = ProcessLine( sCode, sLine, bInCode, sTransBuffer );
471  }
472 
473  sCode << "} catch( err ) { return err; }\n";
474  sCode << "})";
475  }
476  catch(...)
477  {
478  LOG(VB_GENERAL, LOG_ERR,
479  QString("Exception while reading QSP File: %1") .arg(sFileName));
480  }
481 
482  scriptFile.close();
483 
484  sCode.flush();
485 
486  return sBuffer;
487 }
488 
490 //
492 
493 QString ServerSideScripting::ReadFileContents( const QString &sFileName )
494 {
495  QString sCode;
496  QFile scriptFile( sFileName );
497 
498  if (!scriptFile.open( QIODevice::ReadOnly ))
499  throw "Unable to open file";
500 
501  try
502  {
503  QTextStream stream( &scriptFile );
504 
505  sCode = stream.readAll();
506  }
507  catch(...)
508  {
509  LOG(VB_GENERAL, LOG_ERR,
510  QString("Exception while Reading File Contents File: %1") .arg(sFileName));
511  }
512 
513  scriptFile.close();
514 
515  return sCode;
516 }
517 
519 //
521 
522 bool ServerSideScripting::ProcessLine( QTextStream &sCode,
523  QString &sLine,
524  bool bInCode,
525  QString &sTransBuffer ) const
526 {
527  QString sLowerLine = sLine.toLower();
528 
529  if (!sTransBuffer.isEmpty())
530  {
531  int nEndTransPos = sLowerLine.indexOf("</i18n>");
532 
533  if (nEndTransPos == -1)
534  {
535  sTransBuffer.append(" ");
536  sTransBuffer.append(sLine);
537  return bInCode;
538  }
539 
540  if (nEndTransPos > 0)
541  sTransBuffer.append(" ");
542 
543  sTransBuffer.append(sLine.left(nEndTransPos).trimmed());
544  QString trStr =
545  QCoreApplication::translate("HtmlUI", sTransBuffer.trimmed().toLocal8Bit().data());
546  trStr.replace( '"', "\\\"" );
547  sCode << "os.write( \"" << trStr << "\" );\n";
548  sTransBuffer = "";
549 
550  if (nEndTransPos == (sLine.length() - 7))
551  return bInCode;
552 
553  sLine = sLine.right(sLine.length() - (nEndTransPos + 7));
554  }
555 
556  int nStartTransPos = sLowerLine.indexOf("<i18n>");
557  if (nStartTransPos != -1)
558  {
559  int nEndTransPos = sLowerLine.indexOf("</i18n>");
560  if (nEndTransPos != -1)
561  {
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);
567  }
568 
569  sTransBuffer = " ";
570  sTransBuffer.append(sLine.mid(nStartTransPos + 6).trimmed());
571  sLine = sLine.left(nStartTransPos);
572  }
573 
574  int nStartPos = 0;
575  int nEndPos = 0;
576  int nMatchPos = 0;
577  bool bMatchFound = false;
578 
579  QString sExpecting = bInCode ? "%>" : "<%";
580  bool bNewLine = !(sLine.startsWith( sExpecting ));
581 
582  while (nStartPos < sLine.length())
583  {
584  nEndPos = sLine.length() - 1;
585 
586  sExpecting = bInCode ? "%>" : "<%";
587  nMatchPos = sLine.indexOf( sExpecting, nStartPos );
588 
589  // ------------------------------------------------------------------
590  // If not found, Adjust to Save entire line
591  // ------------------------------------------------------------------
592 
593  if (nMatchPos < 0)
594  {
595  nMatchPos = nEndPos + 1;
596  bMatchFound = false;
597  }
598  else
599  bMatchFound = true;
600 
601  // ------------------------------------------------------------------
602  // Add Code or Text to Line
603  // ------------------------------------------------------------------
604 
605  QString sSegment = sLine.mid( nStartPos, nMatchPos - nStartPos );
606 
607  if ( !sSegment.isEmpty())
608  {
609  if (bInCode)
610  {
611  // Add Code
612 
613  if (sSegment.startsWith( "=" ))
614  {
615  // Evaluate statement and render results.
616 
617  sCode << "os.write( " << sSegment.mid( 1 ) << " ); "
618  << "\n";
619  }
620  else if (sSegment.startsWith( "import" ))
621  {
622  // Loads supplied path as script file.
623  //
624  // Syntax: import "/relative/path/to/script.js"
625  // - must be at start of line (no leading spaces)
626  //
627 
628  // Extract filename (remove quotes)
629 
630  QStringList sParts = sSegment.split( ' ', Qt::SkipEmptyParts );
631  if (sParts.length() > 1 )
632  {
633  QString sFileName = sParts[1].mid( 1, sParts[1].length() - 2 );
634 
635  QFileInfo oInfo( m_sResRootPath + sFileName );
636 
637  if (oInfo.exists())
638  {
639  sCode << ReadFileContents( oInfo.canonicalFilePath() )
640  << "\n";
641  }
642  else
643  {
644  LOG(VB_GENERAL, LOG_ERR,
645  QString("ServerSideScripting::ProcessLine 'import' - File not found: %1%2")
646  .arg(m_sResRootPath, sFileName));
647  }
648  }
649  else
650  {
651  LOG(VB_GENERAL, LOG_ERR,
652  QString("ServerSideScripting::ProcessLine 'import' - Malformed [%1]")
653  .arg( sSegment ));
654  }
655 
656  }
657  else
658  sCode << sSegment << "\n";
659 
660  if (bMatchFound)
661  bInCode = false;
662  }
663  else
664  {
665  // Add Text
666 
667  sSegment.replace( '"', "\\\"" );
668 
669  sCode << "os.write( \"" << sSegment << "\" );\n";
670 
671  if (bMatchFound)
672  bInCode = true;
673  }
674  }
675  else
676  {
677  if (bMatchFound)
678  bInCode = !bInCode;
679  }
680 
681  nStartPos = nMatchPos + 2;
682  }
683 
684  if ((bNewLine) && !bInCode )
685  sCode << "os.writeln( \"\" );\n";
686 
687  return bInCode;
688 }
ScriptInfo::m_dtTimeStamp
QDateTime m_dtTimeStamp
Definition: serverSideScripting.h:40
build_compdb.args
args
Definition: build_compdb.py:11
HTTPRequest
Definition: httprequest.h:109
HTTPRequest::GetHostPort
virtual quint16 GetHostPort()=0
HttpServer::GetServerVersion
static QString GetServerVersion(void)
Definition: httpserver.cpp:288
ScriptInfo::m_oFunc
QScriptValue m_oFunc
Definition: serverSideScripting.h:39
HTTPRequest::GetPeerAddress
virtual QString GetPeerAddress()=0
ServerSideScripting::m_sResRootPath
QString m_sResRootPath
Definition: serverSideScripting.h:75
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
HTTPRequest::m_userSession
MythUserSession m_userSession
Definition: httprequest.h:162
formatStr
QScriptValue formatStr(QScriptContext *context, QScriptEngine *interpreter)
Definition: serverSideScripting.cpp:31
ServerSideScripting::ReadFileContents
static QString ReadFileContents(const QString &sFileName)
Definition: serverSideScripting.cpp:493
ServerSideScripting::m_engine
QScriptEngine m_engine
Definition: serverSideScripting.h:53
MythUserSession
Definition: mythsession.h:16
mythlogging.h
MythUserSession::GetUserId
uint GetUserId(void) const
Definition: mythsession.h:40
ServerSideScripting::ServerSideScripting
ServerSideScripting()
Definition: serverSideScripting.cpp:52
HTTPRequest::m_mapParams
QStringMap m_mapParams
Definition: httprequest.h:131
QStringMap
QMap< QString, QString > QStringMap
Definition: upnputil.h:32
serverSideScripting.h
ServerSideScripting::GetLoadedScript
ScriptInfo * GetLoadedScript(const QString &sFileName)
Definition: serverSideScripting.cpp:133
ServerSideScripting::RegisterMetaObjectType
void RegisterMetaObjectType(const QString &sName, const QMetaObject *pMetaObject, QScriptEngine::FunctionSignature pFunction)
Definition: serverSideScripting.cpp:117
MythUserSession::GetSessionLastActive
QDateTime GetSessionLastActive() const
Definition: mythsession.h:46
HTTPRequest::m_mapHeaders
QStringMultiMap m_mapHeaders
Definition: httprequest.h:132
HTTPRequest::GetHostName
virtual QString GetHostName()
Definition: httprequest.cpp:2127
MythUserSession::GetSessionExpires
QDateTime GetSessionExpires() const
Definition: mythsession.h:47
ServerSideScripting::~ServerSideScripting
~ServerSideScripting()
Definition: serverSideScripting.cpp:87
ServerSideScripting::m_debugger
QScriptEngineDebugger m_debugger
Definition: serverSideScripting.h:56
MythUserSession::GetSessionCreated
QDateTime GetSessionCreated() const
Definition: mythsession.h:45
HTTPRequest::SetResponseHeader
void SetResponseHeader(const QString &sKey, const QString &sValue, bool replace=false)
Definition: httprequest.cpp:2073
OutputStream
Definition: serverSideScripting.h:93
HTTPRequest::GetRequestProtocol
QString GetRequestProtocol() const
Definition: httprequest.cpp:841
ServerSideScripting::SetResourceRootPath
QString SetResourceRootPath(const QString &path)
Definition: serverSideScripting.cpp:102
ServerSideScripting::Lock
void Lock()
Definition: serverSideScripting.h:77
ServerSideScripting::EvaluatePage
bool EvaluatePage(QTextStream *pOutStream, const QString &sFileName, HTTPRequest *pRequest, const QByteArray &cspToken)
Definition: serverSideScripting.cpp:151
ServerSideScripting::Unlock
void Unlock()
Definition: serverSideScripting.h:78
httpserver.h
ScriptInfo
Definition: serverSideScripting.h:36
HTTPRequest::GetHostAddress
virtual QString GetHostAddress()=0
ServerSideScripting::ProcessLine
bool ProcessLine(QTextStream &sCode, QString &sLine, bool bInCode, QString &sTransBuffer) const
Definition: serverSideScripting.cpp:522
MythUserSession::GetUserName
QString GetUserName(void) const
Definition: mythsession.h:39
mythsession.h
ServerSideScripting::m_mapScripts
QMap< QString, ScriptInfo * > m_mapScripts
Definition: serverSideScripting.h:74
HTTPRequest::GetRequestType
QString GetRequestType() const
Definition: httprequest.cpp:2153
ServerSideScripting::CreateMethodFromFile
QString CreateMethodFromFile(const QString &sFileName) const
Definition: serverSideScripting.cpp:447
HTTPRequest::m_mapCookies
QStringMap m_mapCookies
Definition: httprequest.h:133