Example #1
0
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;
}
Example #2
0
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;
}