/**************************************************************
 *
 * 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_xmlsecurity.hxx"

#include <documentdigitalsignatures.hxx>
#include <xmlsecurity/digitalsignaturesdialog.hxx>
#include <xmlsecurity/certificateviewer.hxx>
#include <xmlsecurity/macrosecurity.hxx>
#include <xmlsecurity/biginteger.hxx>
#include <xmlsecurity/global.hrc>

#include <xmloff/xmluconv.hxx>

#include <../dialogs/resourcemanager.hxx>
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/ucb/XContent.hpp>
#include <com/sun/star/ucb/XContentProvider.hpp>
#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
#include <com/sun/star/ucb/XCommandProcessor.hpp>
#include <com/sun/star/ucb/Command.hpp>
#include <tools/urlobj.hxx>
#include <vcl/msgbox.hxx>
#include <unotools/securityoptions.hxx>
#include <com/sun/star/security/CertificateValidity.hpp>
#include <com/sun/star/security/SerialNumberAdapter.hpp>
#include <ucbhelper/contentbroker.hxx>
#include <unotools/ucbhelper.hxx>
#include <comphelper/componentcontext.hxx>
#include "comphelper/documentconstants.hxx"

#include "com/sun/star/lang/IllegalArgumentException.hpp"

#include <stdio.h>


using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
namespace css = ::com::sun::star;

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )

DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponentContext >& rxCtx ):
    mxCtx(rxCtx),
    m_sODFVersion(ODFVER_012_TEXT),
    m_nArgumentsCount(0),
    m_bHasDocumentSignature(false)
{
}

void DocumentDigitalSignatures::initialize( const Sequence< Any >& aArguments)
		throw (css::uno::Exception, css::uno::RuntimeException)
{
    if (aArguments.getLength() == 0 || aArguments.getLength() > 2)
        throw css::lang::IllegalArgumentException(
        OUSTR("DocumentDigitalSignatures::initialize requires one or two arguments"),
        Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0);

    m_nArgumentsCount = aArguments.getLength();

    if (!(aArguments[0] >>= m_sODFVersion))
        throw css::lang::IllegalArgumentException(
        OUSTR("DocumentDigitalSignatures::initialize: the first arguments must be a string"),
        Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0);

    if (aArguments.getLength() == 2
        && !(aArguments[1] >>= m_bHasDocumentSignature))
        throw css::lang::IllegalArgumentException(
        OUSTR("DocumentDigitalSignatures::initialize: the second arguments must be a bool"),
        Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 1);

    //the Version is supported as of ODF1.2, so for and 1.1 document or older we will receive the
    //an empty string. In this case we set it to ODFVER_010_TEXT. Then we can later check easily
    //if initialize was called. Only then m_sODFVersion.getLength() is greater than 0
    if (m_sODFVersion.getLength() == 0)
        m_sODFVersion = ODFVER_010_TEXT;
}

sal_Bool DocumentDigitalSignatures::signDocumentContent(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XStream >& xSignStream)
        throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(), "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    return ImplViewSignatures( rxStorage, xSignStream, SignatureModeDocumentContent, false );
}

Sequence< css::security::DocumentSignatureInformation >
DocumentDigitalSignatures::verifyDocumentContentSignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeDocumentContent );
}

void DocumentDigitalSignatures::showDocumentContentSignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    ImplViewSignatures( rxStorage, xSignInStream, SignatureModeDocumentContent, true );
}

::rtl::OUString DocumentDigitalSignatures::getDocumentContentSignatureDefaultStreamName()
    throw (css::uno::RuntimeException)
{
	return DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName();
}

sal_Bool DocumentDigitalSignatures::signScriptingContent(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XStream >& xSignStream ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    OSL_ENSURE(m_nArgumentsCount == 2, "DocumentDigitalSignatures: Service was not initialized properly");
    return ImplViewSignatures( rxStorage, xSignStream, SignatureModeMacros, false );
}

Sequence< css::security::DocumentSignatureInformation >
DocumentDigitalSignatures::verifyScriptingContentSignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeMacros );
}

void DocumentDigitalSignatures::showScriptingContentSignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    ImplViewSignatures( rxStorage, xSignInStream, SignatureModeMacros, true );
}

::rtl::OUString DocumentDigitalSignatures::getScriptingContentSignatureDefaultStreamName()
    throw (css::uno::RuntimeException)
{
	return DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName();
}


sal_Bool DocumentDigitalSignatures::signPackage(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XStream >& xSignStream  ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    return ImplViewSignatures( rxStorage, xSignStream, SignatureModePackage, false );
}

Sequence< css::security::DocumentSignatureInformation >
DocumentDigitalSignatures::verifyPackageSignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModePackage );
}

void DocumentDigitalSignatures::showPackageSignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
{
    OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
    ImplViewSignatures( rxStorage, xSignInStream, SignatureModePackage, true );
}

::rtl::OUString DocumentDigitalSignatures::getPackageSignatureDefaultStreamName(  )
    throw (::com::sun::star::uno::RuntimeException)
{
	return DocumentSignatureHelper::GetPackageSignatureDefaultStreamName();
}


sal_Bool DocumentDigitalSignatures::ImplViewSignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignStream,
    DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException)
{
	Reference< io::XStream > xStream;
	if ( xSignStream.is() )
		xStream = Reference< io::XStream >( xSignStream, UNO_QUERY );
	return ImplViewSignatures( rxStorage, xStream, eMode, bReadOnly );
}

sal_Bool DocumentDigitalSignatures::ImplViewSignatures(
    const Reference< css::embed::XStorage >& rxStorage, const Reference< css::io::XStream >& xSignStream,
    DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException)
{
    sal_Bool bChanges = sal_False;
    DigitalSignaturesDialog aSignaturesDialog(
        NULL, mxCtx, eMode, bReadOnly, m_sODFVersion, m_bHasDocumentSignature);
    bool bInit = aSignaturesDialog.Init();
    DBG_ASSERT( bInit, "Error initializing security context!" );
    if ( bInit )
    {
        aSignaturesDialog.SetStorage( rxStorage );
        aSignaturesDialog.SetSignatureStream( xSignStream );
        if ( aSignaturesDialog.Execute() )
        {
            if ( aSignaturesDialog.SignaturesChanged() )
    		{
    			bChanges = sal_True;
    			// If we have a storage and no stream, we are responsible for commit
    			if ( rxStorage.is() && !xSignStream.is() )
    			{
                    uno::Reference< embed::XTransactedObject > xTrans( rxStorage, uno::UNO_QUERY );
                    xTrans->commit();
    			}
    		}
    	}
    }
    else
    {
        WarningBox aBox( NULL, XMLSEC_RES( RID_XMLSECWB_NO_MOZILLA_PROFILE ) );
        aBox.Execute();
    }

    return bChanges;
}

Sequence< css::security::DocumentSignatureInformation >
DocumentDigitalSignatures::ImplVerifySignatures(
    const Reference< css::embed::XStorage >& rxStorage,
    const Reference< css::io::XInputStream >& xSignStream, DocumentSignatureMode eMode ) throw (RuntimeException)
{
    if (!rxStorage.is())
    {
        DBG_ASSERT(0, "Error, no XStorage provided");
        return Sequence<css::security::DocumentSignatureInformation>();
    }
	// First check for the InputStream, to avoid unnecessary initialization of the security environemnt...
	SignatureStreamHelper aStreamHelper;
	Reference< io::XInputStream > xInputStream = xSignStream;

	if ( !xInputStream.is() )
	{
		aStreamHelper = DocumentSignatureHelper::OpenSignatureStream( rxStorage, embed::ElementModes::READ, eMode );
		if ( aStreamHelper.xSignatureStream.is() )
			xInputStream = Reference< io::XInputStream >( aStreamHelper.xSignatureStream, UNO_QUERY );
	}

	if ( !xInputStream.is() )
		return Sequence< ::com::sun::star::security::DocumentSignatureInformation >(0);


	XMLSignatureHelper aSignatureHelper( mxCtx );

    bool bInit = aSignatureHelper.Init();

	DBG_ASSERT( bInit, "Error initializing security context!" );

	if ( !bInit )
		return Sequence< ::com::sun::star::security::DocumentSignatureInformation >(0);

	aSignatureHelper.SetStorage(rxStorage, m_sODFVersion);

    aSignatureHelper.StartMission();

	aSignatureHelper.ReadAndVerifySignature( xInputStream );

    aSignatureHelper.EndMission();

    Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = aSignatureHelper.GetSecurityEnvironment();

    SignatureInformations aSignInfos = aSignatureHelper.GetSignatureInformations();
	int nInfos = aSignInfos.size();
    Sequence< css::security::DocumentSignatureInformation > aInfos(nInfos);
    css::security::DocumentSignatureInformation* arInfos = aInfos.getArray();

    if ( nInfos )
    {
       Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
            ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);

        for( int n = 0; n < nInfos; ++n )
        {
            DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
                m_sODFVersion, aSignInfos[n]);
            const std::vector< rtl::OUString > aElementsToBeVerified =
                DocumentSignatureHelper::CreateElementList(
                rxStorage, ::rtl::OUString(), eMode, mode);

		    const SignatureInformation& rInfo = aSignInfos[n];
            css::security::DocumentSignatureInformation& rSigInfo = arInfos[n];

            if (rInfo.ouX509Certificate.getLength())
           	rSigInfo.Signer = xSecEnv->createCertificateFromAscii( rInfo.ouX509Certificate ) ;
            if (!rSigInfo.Signer.is())
                rSigInfo.Signer = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );

            // --> PB 2004-12-14 #i38744# time support again
            Date aDate( rInfo.stDateTime.Day, rInfo.stDateTime.Month, rInfo.stDateTime.Year );
            Time aTime( rInfo.stDateTime.Hours, rInfo.stDateTime.Minutes,
                        rInfo.stDateTime.Seconds, rInfo.stDateTime.HundredthSeconds );
            rSigInfo.SignatureDate = aDate.GetDate();
            rSigInfo.SignatureTime = aTime.GetTime();

            // Verify certificate
            //We have patched our version of libxmlsec, so that it does not verify the certificates. This has two
            //reasons. First we want two separate status for signature and certificate. Second libxmlsec calls
            //CERT_VerifyCertificate (solaris, linux) falsely, so that it always regards the certificate as valid.
            //On Window the checking of the certificate path is buggy. It does name matching (issuer, subject name)
            //to find the parent certificate. It does not take into account that there can be several certificates
            //with the same subject name.
            if (rSigInfo.Signer.is())
            {
                try {
                    rSigInfo.CertificateStatus = xSecEnv->verifyCertificate(rSigInfo.Signer,
                        Sequence<Reference<css::security::XCertificate> >());
                } catch (SecurityException& ) {
                    OSL_ENSURE(0, "Verification of certificate failed");
                    rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
                }
            }
            else
            {
                //We should always be able to get the certificates because it is contained in the document,
				//unless the document is damaged so that signature xml file could not be parsed.
                rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
            }

            rSigInfo.SignatureIsValid = ( rInfo.nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );


            if ( rSigInfo.SignatureIsValid )
            {
                 rSigInfo.SignatureIsValid =
                      DocumentSignatureHelper::checkIfAllFilesAreSigned(
                      aElementsToBeVerified, rInfo, mode);
            }
            if (eMode == SignatureModeDocumentContent)
                rSigInfo.PartialDocumentSignature =
                    ! DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]);

        }
    }
    return aInfos;

}

void DocumentDigitalSignatures::manageTrustedSources(  ) throw (RuntimeException)
{
	// MT: i45295
	// SecEnv is only needed to display certificate information from trusted sources.
	// Macro Security also has some options where no security environment is needed, so raise dialog anyway.
	// Later I should change the code so the Dialog creates the SecEnv on demand...

	Reference< dcss::xml::crypto::XSecurityEnvironment > xSecEnv;

	XMLSignatureHelper aSignatureHelper( mxCtx );
	if ( aSignatureHelper.Init() )
		xSecEnv = aSignatureHelper.GetSecurityEnvironment();

	MacroSecurity aDlg( NULL, mxCtx, xSecEnv );
	aDlg.Execute();
}

void DocumentDigitalSignatures::showCertificate(
    const Reference< css::security::XCertificate >& _Certificate ) throw (RuntimeException)
{
    XMLSignatureHelper aSignatureHelper( mxCtx );

	bool bInit = aSignatureHelper.Init();

	DBG_ASSERT( bInit, "Error initializing security context!" );

	if ( bInit )
	{
		CertificateViewer aViewer( NULL, aSignatureHelper.GetSecurityEnvironment(), _Certificate, sal_False );
		aViewer.Execute();
	}

}

::sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
    const Reference< css::security::XCertificate >& Author ) throw (RuntimeException)
{
	sal_Bool bFound = sal_False;

    Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
        ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);

	::rtl::OUString sSerialNum = xSerialNumberAdapter->toString( Author->getSerialNumber() );

    Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors();
	const SvtSecurityOptions::Certificate* pAuthors = aTrustedAuthors.getConstArray();
	const SvtSecurityOptions::Certificate* pAuthorsEnd = pAuthors + aTrustedAuthors.getLength();
	for ( ; pAuthors != pAuthorsEnd; ++pAuthors )
	{
		SvtSecurityOptions::Certificate aAuthor = *pAuthors;
		if ( ( aAuthor[0] == Author->getIssuerName() ) && ( aAuthor[1] == sSerialNum ) )
		{
			bFound = sal_True;
			break;
		}
	}

	return bFound;
}

::sal_Bool DocumentDigitalSignatures::isLocationTrusted( const ::rtl::OUString& Location ) throw (RuntimeException)
{
	sal_Bool bFound = sal_False;
	INetURLObject aLocObj( Location );
	INetURLObject aLocObjLowCase( Location.toAsciiLowerCase() ); // will be used for case insensitive comparing

	::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProvider > xContentProvider;
	::ucbhelper::ContentBroker* pBroker = NULL;

    //warning free code
	//if ( aLocObj.GetProtocol() == INET_PROT_FILE && ( pBroker = ::ucbhelper::ContentBroker::get() ) )
	//	xContentProvider = pBroker->getContentProviderInterface();
	if ( aLocObj.GetProtocol() == INET_PROT_FILE)
    {
        pBroker = ::ucbhelper::ContentBroker::get();
        if (pBroker)
		    xContentProvider = pBroker->getContentProviderInterface();
    }

    Sequence< ::rtl::OUString > aSecURLs = SvtSecurityOptions().GetSecureURLs();
	const ::rtl::OUString* pSecURLs = aSecURLs.getConstArray();
	const ::rtl::OUString* pSecURLsEnd = pSecURLs + aSecURLs.getLength();
	for ( ; pSecURLs != pSecURLsEnd && !bFound; ++pSecURLs )
		bFound = ::utl::UCBContentHelper::IsSubPath( *pSecURLs, Location, xContentProvider );

	return bFound;
}

void DocumentDigitalSignatures::addAuthorToTrustedSources(
    const Reference< css::security::XCertificate >& Author ) throw (RuntimeException)
{
    SvtSecurityOptions aSecOpts;

    Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
        ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);

    SvtSecurityOptions::Certificate aNewCert( 3 );
    aNewCert[ 0 ] = Author->getIssuerName();
    aNewCert[ 1 ] = xSerialNumberAdapter->toString( Author->getSerialNumber() );

    rtl::OUStringBuffer aStrBuffer;
    SvXMLUnitConverter::encodeBase64(aStrBuffer, Author->getEncoded());
    aNewCert[ 2 ] = aStrBuffer.makeStringAndClear();


    Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = aSecOpts.GetTrustedAuthors();
    sal_Int32 nCnt = aTrustedAuthors.getLength();
    aTrustedAuthors.realloc( nCnt + 1 );
    aTrustedAuthors[ nCnt ] = aNewCert;

    aSecOpts.SetTrustedAuthors( aTrustedAuthors );
}

void DocumentDigitalSignatures::addLocationToTrustedSources( const ::rtl::OUString& Location ) throw (RuntimeException)
{
    SvtSecurityOptions aSecOpt;

	Sequence< ::rtl::OUString > aSecURLs = aSecOpt.GetSecureURLs();
    sal_Int32 nCnt = aSecURLs.getLength();
    aSecURLs.realloc( nCnt + 1 );
    aSecURLs[ nCnt ] = Location;

	aSecOpt.SetSecureURLs( aSecURLs );
}

rtl::OUString DocumentDigitalSignatures::GetImplementationName() throw (RuntimeException)
{
	return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) );
}

Sequence< rtl::OUString > DocumentDigitalSignatures::GetSupportedServiceNames() throw (cssu::RuntimeException)
{
	Sequence < rtl::OUString > aRet(1);
	rtl::OUString* pArray = aRet.getArray();
	pArray[0] =  rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) );
	return aRet;
}


Reference< XInterface > DocumentDigitalSignatures_CreateInstance(
	const Reference< XComponentContext >& rCtx) throw ( Exception )
{
	return (cppu::OWeakObject*) new DocumentDigitalSignatures( rCtx );
}
