bool ServerSideScripting::EvaluatePage( QTextStream *pOutStream, const QString &sFileName ) { try { bool bFound( false ); ScriptInfo *pInfo = NULL; // ------------------------------------------------------------------ // See if page has already been loaded // ------------------------------------------------------------------ Lock(); if ( (bFound = m_mapScripts.contains( sFileName )) == true ) pInfo = m_mapScripts[ sFileName ]; Unlock(); // ------------------------------------------------------------------ // Load Script File and Create Function // ------------------------------------------------------------------ QFileInfo fileInfo ( sFileName ); QDateTime dtLastModified = fileInfo.lastModified(); if ((pInfo == NULL) || (pInfo->m_dtTimeStamp != dtLastModified )) { QString sCode = CreateMethodFromFile( sFileName ); QScriptValue func = m_engine.evaluate( sCode, sFileName ); if ( m_engine.hasUncaughtException() ) { LOG(VB_GENERAL, LOG_ERR, QString("Error Loading QSP File: %1 - (%2)%3") .arg(sFileName) .arg(m_engine.uncaughtExceptionLineNumber()) .arg(m_engine.uncaughtException().toString())); return false; } if (pInfo != NULL) { pInfo->m_oFunc = func; pInfo->m_dtTimeStamp = dtLastModified; } else { pInfo = new ScriptInfo( func, dtLastModified ); Lock(); m_mapScripts[ sFileName ] = pInfo; Unlock(); } } // ------------------------------------------------------------------ // Execute function to render output // ------------------------------------------------------------------ OutputStream outStream( pOutStream ); QScriptValueList args; args << m_engine.newQObject( &outStream ); pInfo->m_oFunc.call( QScriptValue(), args ); if (m_engine.hasUncaughtException()) { LOG(VB_GENERAL, LOG_ERR, QString("Error calling QSP File: %1 - %2") .arg(sFileName) .arg(m_engine.uncaughtException().toString())); return false; } } catch(...) { LOG(VB_GENERAL, LOG_ERR, QString("Exception while evaluating QSP File: %1") .arg(sFileName)); return false; } return true; }
bool ServerSideScripting::EvaluatePage( QTextStream *pOutStream, const QString &sFileName, HTTPRequest *pRequest) { try { ScriptInfo *pInfo = NULL; // ------------------------------------------------------------------ // See if page has already been loaded // ------------------------------------------------------------------ pInfo = GetLoadedScript( sFileName ); // ------------------------------------------------------------------ // Load Script File and Create Function // ------------------------------------------------------------------ QFileInfo fileInfo ( sFileName ); QDateTime dtLastModified = fileInfo.lastModified(); Lock(); if ((pInfo == NULL) || (pInfo->m_dtTimeStamp != dtLastModified )) { QString sCode = CreateMethodFromFile( sFileName ); QScriptValue func = m_engine.evaluate( sCode, sFileName ); if ( m_engine.hasUncaughtException() ) { LOG(VB_GENERAL, LOG_ERR, QString("Error Loading QSP File: %1 - (line %2) %3") .arg(sFileName) .arg(m_engine.uncaughtExceptionLineNumber()) .arg(m_engine.uncaughtException().toString())); Unlock(); return false; } if (pInfo != NULL) { pInfo->m_oFunc = func; pInfo->m_dtTimeStamp = dtLastModified; } else { pInfo = new ScriptInfo( func, dtLastModified ); m_mapScripts[ sFileName ] = pInfo; } } // ------------------------------------------------------------------ // Build array of arguments passed to script // ------------------------------------------------------------------ QStringMap mapParams = pRequest->m_mapParams; // Valid characters for object property names must contain only // word characters and numbers, _ and $ // They must not start with a number - to simplify the regexp, we // restrict the first character to the English alphabet QRegExp validChars = QRegExp("^([a-zA-Z]|_|\\$)(\\w|\\$)+$"); QVariantMap params; QMap<QString, QString>::const_iterator it = mapParams.begin(); QString prevArrayName = ""; QVariantMap array; for (; it != mapParams.end(); ++it) { QString key = it.key(); QVariant value = QVariant(it.value()); // PHP Style parameter array if (key.contains("[")) { QString arrayName = key.section('[',0,0); QString arrayKey = key.section('[',1,1); arrayKey.chop(1); // Remove trailing ] if (prevArrayName != arrayName) // New or different array { if (!array.isEmpty()) { params.insert(prevArrayName, QVariant(array)); array.clear(); } prevArrayName = arrayName; } if (!validChars.exactMatch(arrayKey)) // Discard anything that isn't valid for now continue; array.insert(arrayKey, value); if ((it + 1) != mapParams.end()) continue; } if (!array.isEmpty()) { params.insert(prevArrayName, QVariant(array)); array.clear(); } // End Array handling if (!validChars.exactMatch(key)) // Discard anything that isn't valid for now continue; params.insert(key, value); } // ------------------------------------------------------------------ // Build array of request headers // ------------------------------------------------------------------ QStringMap mapHeaders = pRequest->m_mapHeaders; QVariantMap requestHeaders; for (it = mapHeaders.begin(); it != mapHeaders.end(); ++it) { QString key = it.key(); key = key.replace('-', '_'); // May be other valid chars in a request header that we need to replace QVariant value = QVariant(it.value()); if (!validChars.exactMatch(key)) // Discard anything that isn't valid for now continue; requestHeaders.insert(key, value); } // ------------------------------------------------------------------ // Build array of information from the server e.g. client IP // See RFC 3875 - The Common Gateway Interface // ------------------------------------------------------------------ QVariantMap serverVars; serverVars.insert("REMOTE_ADDR", QVariant(pRequest->GetPeerAddress())); serverVars.insert("SERVER_ADDR", QVariant(pRequest->GetHostAddress())); serverVars.insert("SERVER_PROTOCOL", QVariant(pRequest->GetRequestProtocol())); serverVars.insert("SERVER_SOFTWARE", QVariant(HttpServer::GetServerVersion())); QHostAddress clientIP = QHostAddress(pRequest->GetPeerAddress()); QHostAddress serverIP = QHostAddress(pRequest->GetHostAddress()); if (clientIP.protocol() == QAbstractSocket::IPv4Protocol) { serverVars.insert("IP_PROTOCOL", "IPv4"); } else if (clientIP.protocol() == QAbstractSocket::IPv6Protocol) { serverVars.insert("IP_PROTOCOL", "IPv6"); } if (((clientIP.protocol() == QAbstractSocket::IPv4Protocol) && (clientIP.isInSubnet(QHostAddress("172.16.0.0"), 12) || clientIP.isInSubnet(QHostAddress("192.168.0.0"), 16) || clientIP.isInSubnet(QHostAddress("10.0.0.0"), 8))) || ((clientIP.protocol() == QAbstractSocket::IPv6Protocol) && clientIP.isInSubnet(serverIP, 64))) // default subnet size is assumed to be /64 { serverVars.insert("CLIENT_NETWORK", "local"); } else { serverVars.insert("CLIENT_NETWORK", "remote"); } // ------------------------------------------------------------------ // Add the arrays (objects) we've just created to the global scope // They may be accessed as 'Server.REMOTE_ADDR' // ------------------------------------------------------------------ m_engine.globalObject().setProperty("Parameters", m_engine.toScriptValue(params)); m_engine.globalObject().setProperty("RequestHeaders", m_engine.toScriptValue(requestHeaders)); m_engine.globalObject().setProperty("Server", m_engine.toScriptValue(serverVars)); // ------------------------------------------------------------------ // Execute function to render output // ------------------------------------------------------------------ OutputStream outStream( pOutStream ); QScriptValueList args; args << m_engine.newQObject( &outStream ); args << m_engine.toScriptValue(params); QScriptValue ret = pInfo->m_oFunc.call( QScriptValue(), args ); if (ret.isError()) { QScriptValue lineNo = ret.property( "lineNumber" ); LOG(VB_GENERAL, LOG_ERR, QString("Error calling QSP File: %1(%2) - %3") .arg(sFileName) .arg( lineNo.toInt32 () ) .arg( ret .toString() )); Unlock(); return false; } if (m_engine.hasUncaughtException()) { LOG(VB_GENERAL, LOG_ERR, QString("Error calling QSP File: %1(%2) - %3") .arg(sFileName) .arg(m_engine.uncaughtExceptionLineNumber() ) .arg(m_engine.uncaughtException().toString())); Unlock(); return false; } Unlock(); } catch(...) { LOG(VB_GENERAL, LOG_ERR, QString("Exception while evaluating QSP File: %1") .arg(sFileName)); Unlock(); return false; } return true; }