/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_scripting.hxx"

#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/WrappedTargetException.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/UnknownPropertyException.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/util/XChangesBatch.hpp>
#include <com/sun/star/util/XMacroExpander.hpp>
#include <com/sun/star/util/XStringSubstitution.hpp>
#include <com/sun/star/awt/XDialog.hpp>
#include <com/sun/star/security/AccessControlException.hpp>
#include <com/sun/star/security/RuntimePermission.hpp>
#include <drafts/com/sun/star/script/framework/storage/XScriptStorageManager.hpp>
#include <drafts/com/sun/star/script/framework/storage/XScriptInfoAccess.hpp>
#include "ScriptSecurityManager.hxx"
#include <util/util.hxx>
#include <util/scriptingconstants.hxx>
#include <tools/diagnose_ex.h>

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::drafts::com::sun::star::script::framework;

// is this in the utils?
const char* const SCRIPTSTORAGEMANAGER_SERVICE =
    "/singletons/drafts.com.sun.star.script.framework.storage.theScriptStorageManager";

namespace scripting_securitymgr
{

static OUString s_configProv = ::rtl::OUString::createFromAscii(
    "com.sun.star.configuration.ConfigurationProvider");
 
static OUString s_configAccess = ::rtl::OUString::createFromAscii(
    "com.sun.star.configuration.ConfigurationAccess");

static OUString s_configUpdate = ::rtl::OUString::createFromAscii(
    "com.sun.star.configuration.ConfigurationUpdateAccess");

static OUString s_securityDialog = ::rtl::OUString::createFromAscii(
    "com.sun.star.script.framework.security.SecurityDialog");

static const int PERMISSION_NEVER = 0;
static const int PERMISSION_PATHLIST = 1;
static const int PERMISSION_ALWAYS = 2;

static const int ALLOW_RUN = 1;
static const int ADD_TO_PATH = 2;

//*************************************************************************
// ScriptSecurityManager Constructor
ScriptSecurityManager::ScriptSecurityManager(
    const Reference< XComponentContext > & xContext ) throw ( RuntimeException )
    : m_xContext( xContext, UNO_SET_THROW )
{
    OSL_TRACE( "< ScriptSecurityManager ctor called >\n" );

    // get the service manager from the context
    Reference< lang::XMultiComponentFactory > xMgr( m_xContext->getServiceManager(), UNO_SET_THROW );

    // create an instance of the ConfigurationProvider
    m_xConfigProvFactory.set( xMgr->createInstanceWithContext( s_configProv, m_xContext ), UNO_QUERY_THROW );
}

void ScriptSecurityManager::addScriptStorage( rtl::OUString scriptStorageURL, 
    sal_Int32 storageID)
throw ( RuntimeException )
{
    Permission_Hash::const_iterator ph_it = m_permissionSettings.find( scriptStorageURL );
    if ( ph_it != m_permissionSettings.end() )
    {
        OSL_TRACE( "ScriptSecurityManager::addScriptStorage: already called for %s",
            ::rtl::OUStringToOString( scriptStorageURL, 
                RTL_TEXTENCODING_ASCII_US ).pData->buffer);
        return;
    }
    StoragePerm newPerm;
    newPerm.scriptStorageURL=scriptStorageURL;
    newPerm.storageID=storageID;

    // we err on the side of caution!!
    newPerm.execPermission=sal_False;

    //need to check if storage has any scripts
    try 
    {
        // we have some scripts so read config & decide on that basis
        // Setup flags: m_runMacroSetting, m_warning, m_confirmationRequired, 
        readConfiguration();
    }
    catch ( RuntimeException & rte )
    {
        OSL_TRACE( "ScriptSecurityManager::addScriptStorage: caught RuntimeException: %s",
            ::rtl::OUStringToOString( rte.Message, 
                RTL_TEXTENCODING_ASCII_US ).pData->buffer);
        throw RuntimeException( 
            OUSTR( "ScriptSecurityManager::addScriptStorage: caught RuntimeException" ).concat( rte.Message ),
        Reference< XInterface >() );
    }

    switch( m_runMacroSetting )
    {
        case PERMISSION_NEVER:         // never
        {
            OSL_TRACE("never run");
            break;
        }
        case PERMISSION_PATHLIST:         // according to path list
        { 
            OSL_TRACE("according to path");
            // check path
            rtl::OUString path = scriptStorageURL.copy( 0, scriptStorageURL.lastIndexOf( '/' ) );
            OSL_TRACE( "no of elts in path list = %d",
                (int)m_secureURL.getLength() );
            bool match = isSecureURL( path );
            if( match &&  ( m_warning == sal_True ) )
            {
                OSL_TRACE("path match & warning dialog");
                int result = (int)executeStandardDialog();
                OSL_TRACE("result = %d", (int)result);
                if ( (result&ALLOW_RUN) == ALLOW_RUN )
                {
                    newPerm.execPermission=sal_True;
                }
                break;
            }
            else if ( match )
            {
                OSL_TRACE("path match & no warning dialog");
                newPerm.execPermission=sal_True;
                break;
            }
            else if( m_confirmationRequired == sal_True )
            {
                OSL_TRACE("no path match & confirmation dialog");
                int result = (int)executePathDialog( path );
                OSL_TRACE("result = %d", (int)result);
                if ( (result&ALLOW_RUN) == ALLOW_RUN )
                {
                    newPerm.execPermission=sal_True;
                }
                if ( (result&ADD_TO_PATH) == ADD_TO_PATH )
                {
                    /* if checkbox clicked then need to add path to registry*/
                    addToSecurePaths(path);
                }
            }
            break;
        } 
        case PERMISSION_ALWAYS:         // always
            if( m_warning == sal_True )
            {
                OSL_TRACE("always & warning dialog");
                short result = executeStandardDialog();
                if ( (result&ALLOW_RUN) == ALLOW_RUN )
                {
                    newPerm.execPermission=sal_True;
                }
            }
            else
            {
                OSL_TRACE("always & no warning dialog");
                newPerm.execPermission=sal_True;
            }
            break;
        default:
                // 
                throw RuntimeException(
                    OUSTR( "ScriptSecurityManager::addScriptStorage got invalid OfficeBasic setting"),
                    Reference< XInterface > ());
    }
    
    if ( newPerm.execPermission == sal_True )
    {
        OSL_TRACE("setting exec permission to true for %s",
            ::rtl::OUStringToOString( scriptStorageURL, 
                RTL_TEXTENCODING_ASCII_US ).pData->buffer );
    }
    else
    {
        OSL_TRACE("setting exec permission to false for %s",
            ::rtl::OUStringToOString( scriptStorageURL, 
                RTL_TEXTENCODING_ASCII_US ).pData->buffer );
    }

    m_permissionSettings[ scriptStorageURL ] = newPerm;
}

bool ScriptSecurityManager::isSecureURL( const OUString & path )
{
    bool match = false;
    OSL_TRACE( "no of elts in path list = %d",
        (int)m_secureURL.getLength() );
    OSL_TRACE("document path: %s",
        ::rtl::OUStringToOString( path, 
            RTL_TEXTENCODING_ASCII_US ).pData->buffer);
    int length = m_secureURL.getLength();
    for( int j = 0; j < length ; j++ )
    {
        OSL_TRACE("path list element: %s",
            ::rtl::OUStringToOString( m_secureURL[j], 
                RTL_TEXTENCODING_ASCII_US ).pData->buffer);
#ifdef WIN32
        OSL_TRACE("case insensitive comparison");
        if( path.equalsIgnoreAsciiCase( m_secureURL[j] ) )
#else
        OSL_TRACE("case sensitive comparison");
        if( path.equals( m_secureURL[j] ) )
#endif
        {
            match = true;
            break;
        }
    }
    return match;
}

short ScriptSecurityManager::executeStandardDialog()
throw ( RuntimeException )
{
    OUString dummyString;
    return executeDialog( dummyString );
}

short ScriptSecurityManager::executePathDialog( const OUString & path )
throw ( RuntimeException )
{
    return executeDialog( path );    
}

short ScriptSecurityManager::executeDialog( const OUString & path )
throw ( RuntimeException )
{
    Sequence < Any > aArgs;
    if( path.getLength() != 0 )
    {
        OSL_TRACE("reallocing");
        aArgs.realloc(1);
        aArgs[ 0 ] <<= path;
    }
    short result;
    try
    {
        Reference< lang::XMultiComponentFactory > xMgr( m_xContext->getServiceManager(), UNO_SET_THROW );
        Reference< awt::XDialog > xDialog(
            xMgr->createInstanceWithArgumentsAndContext( s_securityDialog, aArgs, m_xContext ),
            UNO_QUERY_THROW );
        result = xDialog->execute();
        Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY_THROW );
        xComponent->dispose();
    }
    catch ( RuntimeException & rte )
    {
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager::executeDialog: caught RuntimeException: ").concat( rte.Message ),
            Reference< XInterface > ());
    }
    catch ( Exception & e )
    {
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager::executeDialog: caught Exception: ").concat( e.Message ),
            Reference< XInterface > ());
    }
    return result;
}

/**
 * checks to see whether the requested ScriptPermission is allowed. 
 * This was modelled after the Java AccessController, but at this time
 * we can't see a good reason not to return a bool, rather than throw
 * an exception if the request is not granted (as is the case in Java).
 */
void ScriptSecurityManager::checkPermission( const OUString & scriptStorageURL,
    const OUString & permissionRequest ) 
    throw ( RuntimeException, lang::IllegalArgumentException, security::AccessControlException )
{
    if( permissionRequest.equals( OUString::createFromAscii( "execute" ) ) )
    {
        OSL_TRACE( 
            "ScriptSecurityManager::checkPermission: execute permission request for %s", 
            ::rtl::OUStringToOString( scriptStorageURL, 
                RTL_TEXTENCODING_ASCII_US ).pData->buffer);
        Permission_Hash::const_iterator ph_it = m_permissionSettings.find( scriptStorageURL );
        Permission_Hash::const_iterator ph_itend = 
            m_permissionSettings.end();
        if ( ph_it != ph_itend )
        {
            if ( ph_it->second.execPermission )
            {
                return;
            }
            else
            {
                OSL_TRACE( "permission refused" );
                Any aPermission;
                security::RuntimePermission permission;
                permission.Name = OUString::createFromAscii( "execute" ).concat( scriptStorageURL );
                aPermission <<= permission;
                throw security::AccessControlException( 
                    OUString::createFromAscii( "ScriptSecurityManager::checkPermission: no execute permission for URL" ).concat( scriptStorageURL ), 
                    Reference< XInterface > (), aPermission );
            }
        }
        // we should never get here!!
        throw lang::IllegalArgumentException( OUString::createFromAscii( "ScriptSecurityManager::checkPermission: storageURL not found" ), Reference< XInterface > (), 0 );
    }
    // inappropriate permission request
    throw lang::IllegalArgumentException( OUString::createFromAscii( "ScriptSecurityManager::checkPermission: storageURL not found" ), Reference< XInterface > (), 1 );
}

void ScriptSecurityManager::removePermissionSettings ( ::rtl::OUString & scriptStorageURL )
{
    Permission_Hash::const_iterator ph_it =
        m_permissionSettings.find( scriptStorageURL );

    if ( ph_it == m_permissionSettings.end() )
    {
        OSL_TRACE( "Entry for storage url %s doesn't exist in map", 
            ::rtl::OUStringToOString( scriptStorageURL, 
                RTL_TEXTENCODING_ASCII_US ).pData->buffer);
        return;
    }

    // erase the entry from the hash
    m_permissionSettings.erase( scriptStorageURL );

}

void ScriptSecurityManager::readConfiguration()
    throw ( RuntimeException)
{
    try 
    {
        beans::PropertyValue configPath;
        configPath.Name = ::rtl::OUString::createFromAscii( "nodepath" );
        configPath.Value <<= ::rtl::OUString::createFromAscii( "org.openoffice.Office.Common/Security/Scripting" );
        Sequence < Any > aargs( 1 );
        aargs[ 0 ] <<= configPath;
        ENSURE_OR_THROW( m_xConfigProvFactory.is(),
            "ScriptSecurityManager::readConfiguration: ConfigProviderFactory no longer valid!" );
        // get the XPropertySet interface from the ConfigurationAccess service
        Reference < beans::XPropertySet > xPropSet( m_xConfigProvFactory->createInstanceWithArguments( s_configAccess, aargs ), UNO_QUERY_THROW );

        m_confirmationRequired = sal_True;
        OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "Confirmation" ) ) >>= m_confirmationRequired );
        if ( m_confirmationRequired == sal_True ) 
        {
            OSL_TRACE( "ScriptSecurityManager:readConfiguration: confirmation is true" );
        }
        else
        {
            OSL_TRACE( "ScriptSecurityManager:readConfiguration: confirmation is false" );
        }

        m_warning = true;
        OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "Warning" ) ) >>= m_warning );

        if ( m_warning == sal_True ) 
        {
            OSL_TRACE( "ScriptSecurityManager:readConfiguration: warning is true" );
        }
        else
        {
            OSL_TRACE( "ScriptSecurityManager:readConfiguration: warning is false" );
        }

        m_runMacroSetting = sal_True;
        OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "OfficeBasic" ) ) >>= m_runMacroSetting );
        OSL_TRACE( "ScriptSecurityManager:readConfiguration: OfficeBasic = %d", m_runMacroSetting );

        m_secureURL = ::rtl::OUString();
        OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "SecureURL" ) ) >>= m_secureURL );
    }
    catch ( beans::UnknownPropertyException & upe )
    {
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager:readConfiguration: Attempt to read unknown property: " ).concat( upe.Message ),
            Reference< XInterface > () );
    }
    catch ( lang::WrappedTargetException & wte )
    {
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager:readConfiguration: wrapped target exception? :" ).concat( wte.Message ),
            Reference< XInterface > () );
    }
    catch ( Exception & e )
    {
        OSL_TRACE( "Unknown exception in readconf: %s",
            ::rtl::OUStringToOString(e.Message , 
            RTL_TEXTENCODING_ASCII_US ).pData->buffer  );
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager:readConfiguration: exception? :" ).concat( e.Message ),
            Reference< XInterface > () );
    }
#ifdef _DEBUG
    catch ( ... )
    {
        OSL_TRACE( "Completely Unknown exception in readconf!!!!!!");
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager:readConfiguration: exception? :" ),
            Reference< XInterface > () );
    }
#endif

    int length = m_secureURL.getLength();

    // PathSubstitution needed to interpret variables found in config
    Reference< lang::XMultiComponentFactory > xMgr( m_xContext->getServiceManager(), UNO_SET_THROW );
    Reference< XInterface > xInterface = );
    Reference< util::XStringSubstitution > xStringSubstitution(
        xMgr->createInstanceWithContext(
            ::rtl::OUString::createFromAscii( "com.sun.star.util.PathSubstitution" ), m_xContext
        ),
        UNO_QUERY_THROW
    );
    for( int i = 0; i < length; i++ )
    {
        OSL_TRACE( "ScriptSecurityManager:readConfiguration path = %s", 
            ::rtl::OUStringToOString(m_secureURL[i] , 
            RTL_TEXTENCODING_ASCII_US ).pData->buffer  );

        OSL_TRACE( "ScriptSecurityManager: subpath = %s",
            ::rtl::OUStringToOString( 
            xStringSubstitution->substituteVariables( m_secureURL[i], true ),
            RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        m_secureURL[i] = xStringSubstitution->substituteVariables( m_secureURL[i], true );
    }
#ifdef _DEBUG
    int length2 = m_secureURL.getLength();
    for( int j = 0; j < length2 ; j++ )
    {
        OSL_TRACE( "ScriptSecurityManager: path = %s", 
            ::rtl::OUStringToOString(m_secureURL[j] , 
            RTL_TEXTENCODING_ASCII_US ).pData->buffer  );
    }
#endif
}

void ScriptSecurityManager::addToSecurePaths( const OUString & path )
throw ( RuntimeException )
{
    OSL_TRACE( "--->ScriptSecurityManager::addToSecurePaths" );
    beans::PropertyValue configPath;
    configPath.Name = ::rtl::OUString::createFromAscii( "nodepath" );
    configPath.Value <<= ::rtl::OUString::createFromAscii( "org.openoffice.Office.Common/Security/Scripting" );
    Sequence < Any > aargs( 1 );
    aargs[ 0 ] <<= configPath;
    Reference < container::XNameReplace > xNameReplace(
        m_xConfigProvFactory->createInstanceWithArguments( s_configUpdate, aargs ), UNO_QUERY_THROW );
    Reference < util::XChangesBatch > xChangesBatch( xNameReplace, UNO_QUERY_THROW );

    OSL_TRACE( "--->ScriptSecurityManager::addToSecurePaths: after if stuff" );
    Reference < beans::XPropertySet > xPropSet( xInterface, UNO_QUERY );
    css::uno::Sequence< rtl::OUString > newSecureURL;
    Any value;
    OUString pathListPropName = OUSTR ( "SecureURL" );
    value=xPropSet->getPropertyValue( pathListPropName );
    if ( sal_False == ( value >>= newSecureURL ) )
    {
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager::addToSecurePaths: can't get SecureURL setting" ),
            Reference< XInterface > () );
    }
    try
    {
        sal_Int32 length = newSecureURL.getLength();
        newSecureURL.realloc( length + 1 );
        newSecureURL[ length ] = path;
        Any aNewSecureURL;
        aNewSecureURL <<= newSecureURL;
        xNameReplace->replaceByName( pathListPropName, aNewSecureURL );
        xChangesBatch->commitChanges();
        m_secureURL = newSecureURL;
    }
    catch ( Exception & e )
    {
        OSL_TRACE( "Error updating secure paths: " );
        throw RuntimeException(
            OUSTR( "ScriptSecurityManager::addToSecurePaths: error updating SecureURL setting" ).concat( e.Message ),
            Reference< XInterface > () );
    }
}

//*************************************************************************
// ScriptSecurityManager Destructor
ScriptSecurityManager::~ScriptSecurityManager()
{
    OSL_TRACE( "< ScriptSecurityManager dtor called >\n" );
}

} // Namespace
