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


#include "dp_misc.h"
#include "dp_version.hxx"
#include "dp_interact.h"
#include "rtl/uri.hxx"
#include "rtl/digest.h"
#include "rtl/random.h"
#include "rtl/bootstrap.hxx"
#include "unotools/bootstrap.hxx"
#include "osl/file.hxx"
#include "osl/pipe.hxx"
#include "osl/security.hxx"
#include "osl/thread.hxx"
#include "osl/mutex.hxx"
#include "com/sun/star/ucb/CommandAbortedException.hpp"
#include "com/sun/star/task/XInteractionHandler.hpp"
#include "com/sun/star/bridge/UnoUrlResolver.hpp"
#include "com/sun/star/bridge/XUnoUrlResolver.hpp"
#include "com/sun/star/deployment/ExtensionManager.hpp"
#include "com/sun/star/task/XRestartManager.hpp"
#include "boost/scoped_array.hpp"
#include "boost/shared_ptr.hpp"
#include <comphelper/processfactory.hxx>
 
#ifdef WNT
//#include "tools/prewin.h"
#define UNICODE
#define _UNICODE
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
//#include "tools/postwin.h"
#endif

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;
using ::rtl::OString;


#define SOFFICE1 "soffice.exe"
#define SOFFICE2 "soffice.bin"
#define SBASE "sbase.exe"
#define SCALC "scalc.exe"
#define SDRAW "sdraw.exe"
#define SIMPRESS "simpress.exe"
#define SWRITER "swriter.exe"

namespace dp_misc {
namespace {

struct UnoRc : public rtl::StaticWithInit<
    const boost::shared_ptr<rtl::Bootstrap>, UnoRc> {
    const boost::shared_ptr<rtl::Bootstrap> operator () () {
        OUString unorc( RTL_CONSTASCII_USTRINGPARAM(
                            "$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")) );
        ::rtl::Bootstrap::expandMacros( unorc );
        ::boost::shared_ptr< ::rtl::Bootstrap > ret(
            new ::rtl::Bootstrap( unorc ) );
        OSL_ASSERT( ret->getHandle() != 0 );
        return ret;
    }
};

struct OfficePipeId : public rtl::StaticWithInit<const OUString, OfficePipeId> {
    const OUString operator () ();
};

const OUString OfficePipeId::operator () ()
{
    OUString userPath;
	::utl::Bootstrap::PathStatus aLocateResult =
	::utl::Bootstrap::locateUserInstallation( userPath );
	if (!(aLocateResult == ::utl::Bootstrap::PATH_EXISTS || 
		aLocateResult == ::utl::Bootstrap::PATH_VALID))
	{
		throw Exception(OUSTR("Extension Manager: Could not obtain path for UserInstallation."), 0);
	}
    
    rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
    if (digest <= 0) {
        throw RuntimeException(
            OUSTR("cannot get digest rtl_Digest_AlgorithmMD5!"), 0 );
    }
    
    sal_uInt8 const * data =
        reinterpret_cast<sal_uInt8 const *>(userPath.getStr());
    sal_Size size = (userPath.getLength() * sizeof (sal_Unicode));
    sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
    ::boost::scoped_array<sal_uInt8> md5_buf( new sal_uInt8 [ md5_key_len ] );
    
    rtl_digest_init( digest, data, static_cast<sal_uInt32>(size) );
    rtl_digest_update( digest, data, static_cast<sal_uInt32>(size) );
    rtl_digest_get( digest, md5_buf.get(), md5_key_len );
    rtl_digest_destroy( digest );
    
    // create hex-value string from the MD5 value to keep
    // the string size minimal
    ::rtl::OUStringBuffer buf;
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("SingleOfficeIPC_") );
    for ( sal_uInt32 i = 0; i < md5_key_len; ++i ) {
        buf.append( static_cast<sal_Int32>(md5_buf[ i ]), 0x10 );
    }
    return buf.makeStringAndClear();
}

bool existsOfficePipe()
{
    OUString const & pipeId = OfficePipeId::get();
    if (pipeId.getLength() == 0)
        return false;
    ::osl::Security sec;
    ::osl::Pipe pipe( pipeId, osl_Pipe_OPEN, sec );
    return pipe.is();
}


//Returns true if the Folder was more recently modified then
//the lastsynchronized file. That is the repository needs to
//be synchronized.
bool compareExtensionFolderWithLastSynchronizedFile(
    OUString const & folderURL, OUString const & fileURL)
{
    bool bNeedsSync = false;
    ::osl::DirectoryItem itemExtFolder;
    ::osl::File::RC err1 =
          ::osl::DirectoryItem::get(folderURL, itemExtFolder);
    //If it does not exist, then there is nothing to be done
    if (err1 == ::osl::File::E_NOENT)
    {
        return false;
    }
    else if (err1 != ::osl::File::E_None)
    {
        OSL_ENSURE(0, "Cannot access extension folder");
        return true; //sync just in case
    }

    //If last synchronized does not exist, then OOo is started for the first time
    ::osl::DirectoryItem itemFile;
    ::osl::File::RC err2 = ::osl::DirectoryItem::get(fileURL, itemFile);
    if (err2 == ::osl::File::E_NOENT)
    {
        return true;
        
    }
    else if (err2 != ::osl::File::E_None)
    {
        OSL_ENSURE(0, "Cannot access file lastsynchronized");
        return true; //sync just in case
    }
    
    //compare the modification time of the extension folder and the last
    //modified file
    ::osl::FileStatus statFolder(FileStatusMask_ModifyTime);
    ::osl::FileStatus statFile(FileStatusMask_ModifyTime);
    if (itemExtFolder.getFileStatus(statFolder) == ::osl::File::E_None)
    {
        if (itemFile.getFileStatus(statFile) == ::osl::File::E_None)
        {
            TimeValue timeFolder = statFolder.getModifyTime();
            TimeValue timeFile = statFile.getModifyTime();

            if (timeFile.Seconds < timeFolder.Seconds)
                bNeedsSync = true;
        }
        else
        {
            OSL_ASSERT(0);
            bNeedsSync = true; 
        }
    }
    else
    {
        OSL_ASSERT(0);
        bNeedsSync = true;
    }
    return bNeedsSync;    
}

bool needToSyncRepostitory(OUString const & name)
{
    OUString folder;
    OUString file;
    if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled"))))
    {
        folder = OUString(
            RTL_CONSTASCII_USTRINGPARAM("$BUNDLED_EXTENSIONS"));
        file = OUString (
            RTL_CONSTASCII_USTRINGPARAM(
                "$BUNDLED_EXTENSIONS_USER/lastsynchronized"));
    }
    else if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("shared"))))
    {
        folder = OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "$UNO_SHARED_PACKAGES_CACHE/uno_packages"));
        file = OUString (
            RTL_CONSTASCII_USTRINGPARAM(
                "$SHARED_EXTENSIONS_USER/lastsynchronized"));
    }
    else
    {
        OSL_ASSERT(0);
        return true;
    }    
    ::rtl::Bootstrap::expandMacros(folder);
    ::rtl::Bootstrap::expandMacros(file);
    return compareExtensionFolderWithLastSynchronizedFile(
        folder, file);
}


} // anon namespace

//==============================================================================

namespace {
inline OUString encodeForRcFile( OUString const & str )
{
    // escape $\{} (=> rtl bootstrap files)
    ::rtl::OUStringBuffer buf;
    sal_Int32 pos = 0;
    const sal_Int32 len = str.getLength();
    for ( ; pos < len; ++pos ) {
        sal_Unicode c = str[ pos ];
        switch (c) {
        case '$':
        case '\\':
        case '{':
        case '}':
            buf.append( static_cast<sal_Unicode>('\\') );
            break;
        }
        buf.append( c );
    }
    return buf.makeStringAndClear();
}
}

//==============================================================================
OUString makeURL( OUString const & baseURL, OUString const & relPath_ )
{
    ::rtl::OUStringBuffer buf;
    if (baseURL.getLength() > 1 && baseURL[ baseURL.getLength() - 1 ] == '/')
        buf.append( baseURL.copy( 0, baseURL.getLength() - 1 ) );
    else
        buf.append( baseURL );
    OUString relPath(relPath_);
    if (relPath.getLength() > 0 && relPath[ 0 ] == '/')
        relPath = relPath.copy( 1 );
    if (relPath.getLength() > 0)
    {
        buf.append( static_cast<sal_Unicode>('/') );
        if (baseURL.matchAsciiL(
                RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) {
            // encode for macro expansion: relPath is supposed to have no
            // macros, so encode $, {} \ (bootstrap mimic)
            relPath = encodeForRcFile(relPath);
            
            // encode once more for vnd.sun.star.expand schema:
            // vnd.sun.star.expand:$UNO_...
            // will expand to file-url
            relPath = ::rtl::Uri::encode( relPath, rtl_UriCharClassUric,
                                          rtl_UriEncodeIgnoreEscapes,
                                          RTL_TEXTENCODING_UTF8 );
        }
        buf.append( relPath );
    }
    return buf.makeStringAndClear();
}

OUString makeURLAppendSysPathSegment( OUString const & baseURL, OUString const & relPath_ )
{
    OUString segment = relPath_;
    OSL_ASSERT(segment.indexOf(static_cast<sal_Unicode>('/')) == -1);
    
    ::rtl::Uri::encode(
        segment, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
        RTL_TEXTENCODING_UTF8);
    return makeURL(baseURL, segment);
}



//==============================================================================
OUString expandUnoRcTerm( OUString const & term_ )
{
    OUString term(term_);
    UnoRc::get()->expandMacrosFrom( term );
    return term;
}

OUString makeRcTerm( OUString const & url )
{
    OSL_ASSERT( url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM(
                                     "vnd.sun.star.expand:") ) );
    if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) {
        // cut protocol:
        OUString rcterm( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) );
        // decode uric class chars:
        rcterm = ::rtl::Uri::decode(
            rcterm, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
        return rcterm;
    }
    else
        return url;
}

//==============================================================================
OUString expandUnoRcUrl( OUString const & url )
{
    if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) {
        // cut protocol:
        OUString rcurl( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) );
        // decode uric class chars:
        rcurl = ::rtl::Uri::decode(
            rcurl, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
        // expand macro string:
        UnoRc::get()->expandMacrosFrom( rcurl );
        return rcurl;
    }
    else {
        return url;
    }
}

//==============================================================================
bool office_is_running()
{
    //We need to check if we run within the office process. Then we must not use the pipe, because
    //this could cause a deadlock. This is actually a workaround for i82778
    OUString sFile;
    oslProcessError err = osl_getExecutableFile(& sFile.pData);
    bool ret = false;
    if (osl_Process_E_None == err)
    {
        sFile = sFile.copy(sFile.lastIndexOf('/') + 1);
        if (
#if defined UNIX            
            sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2)))
#elif defined WNT || defined OS2
            //osl_getExecutableFile should deliver "soffice.bin" on windows
            //even if swriter.exe, scalc.exe etc. was started. This is a bug
            //in osl_getExecutableFile
            sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE1)))
            || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2)))
            || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SBASE)))
            || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SCALC)))
            || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SDRAW)))
            || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SIMPRESS)))
            || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SWRITER)))
#else
#error "Unsupported platform"
#endif            
            
            )
            ret = true;
        else
            ret = existsOfficePipe();
    }
    else
    {
        OSL_ENSURE(0, "NOT osl_Process_E_None ");
        //if osl_getExecutable file than we take the risk of creating a pipe
        ret =  existsOfficePipe();  
    }
    return ret;
}

//==============================================================================
oslProcess raiseProcess(
    OUString const & appURL, Sequence<OUString> const & args )
{
    ::osl::Security sec;
    oslProcess hProcess = 0;
    oslProcessError rc = osl_executeProcess(
        appURL.pData,
        reinterpret_cast<rtl_uString **>(
            const_cast<OUString *>(args.getConstArray()) ),
        args.getLength(),
        osl_Process_DETACHED,
        sec.getHandle(),
        0, // => current working dir
        0, 0, // => no env vars
        &hProcess );
    
    switch (rc) {
    case osl_Process_E_None:
        break;
    case osl_Process_E_NotFound:
        throw RuntimeException( OUSTR("image not found!"), 0 );
    case osl_Process_E_TimedOut:
        throw RuntimeException( OUSTR("timout occurred!"), 0 );
    case osl_Process_E_NoPermission:
        throw RuntimeException( OUSTR("permission denied!"), 0 );
    case osl_Process_E_Unknown:
        throw RuntimeException( OUSTR("unknown error!"), 0 );
    case osl_Process_E_InvalidError:
    default:
        throw RuntimeException( OUSTR("unmapped error!"), 0 );
    }
    
    return hProcess;
}

//==============================================================================
OUString generateRandomPipeId()
{
    // compute some good pipe id:
    static rtlRandomPool s_hPool = rtl_random_createPool();
    if (s_hPool == 0)
        throw RuntimeException( OUSTR("cannot create random pool!?"), 0 );
    sal_uInt8 bytes[ 32 ];
    if (rtl_random_getBytes(
            s_hPool, bytes, ARLEN(bytes) ) != rtl_Random_E_None) {
        throw RuntimeException( OUSTR("random pool error!?"), 0 );
    }
    ::rtl::OUStringBuffer buf;
    for ( sal_uInt32 i = 0; i < ARLEN(bytes); ++i ) {
        buf.append( static_cast<sal_Int32>(bytes[ i ]), 0x10 );
    }
    return buf.makeStringAndClear();
}

//==============================================================================
Reference<XInterface> resolveUnoURL(
    OUString const & connectString,
    Reference<XComponentContext> const & xLocalContext,
    AbortChannel * abortChannel )
{
    Reference<bridge::XUnoUrlResolver> xUnoUrlResolver(
        bridge::UnoUrlResolver::create( xLocalContext ) );
    
    for (;;)
    {
        if (abortChannel != 0 && abortChannel->isAborted()) {
            throw ucb::CommandAbortedException(
                OUSTR("abort!"), Reference<XInterface>() );
        }
        try {
            return xUnoUrlResolver->resolve( connectString );
        }
        catch (connection::NoConnectException &) {
            TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ };
            ::osl::Thread::wait( tv );
        }
    }
}

#ifdef WNT
void writeConsoleWithStream(::rtl::OUString const & sText, HANDLE stream)
{
    DWORD nWrittenChars = 0;
    WriteFile(stream, sText.getStr(), 
        sText.getLength() * 2, &nWrittenChars, NULL);
}
#else
void writeConsoleWithStream(::rtl::OUString const & sText, FILE * stream)
{
    OString s = OUStringToOString(sText, osl_getThreadTextEncoding());
    fprintf(stream, "%s", s.getStr());
    fflush(stream);
}
#endif

#ifdef WNT
void writeConsoleWithStream(::rtl::OString const & sText, HANDLE stream)
{
    writeConsoleWithStream(OStringToOUString(
        sText, RTL_TEXTENCODING_UTF8), stream);
}
#else
void writeConsoleWithStream(::rtl::OString const & sText, FILE * stream)
{
    fprintf(stream, "%s", sText.getStr());
    fflush(stream);
}
#endif

void writeConsole(::rtl::OUString const & sText)
{
#ifdef WNT
    writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE));
#else
    writeConsoleWithStream(sText, stdout);
#endif
}

void writeConsole(::rtl::OString const & sText)
{
#ifdef WNT
    writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE));
#else
    writeConsoleWithStream(sText, stdout);
#endif
}

void writeConsoleError(::rtl::OUString const & sText)
{
#ifdef WNT
    writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE));
#else
    writeConsoleWithStream(sText, stderr);
#endif
}


void writeConsoleError(::rtl::OString const & sText)
{
#ifdef WNT
    writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE));
#else
    writeConsoleWithStream(sText, stderr);
#endif
}



OUString readConsole()
{
#ifdef WNT
    sal_Unicode aBuffer[1024];
	DWORD	dwRead = 0;
    //unopkg.com feeds unopkg.exe with wchar_t|s
    if (ReadFile( GetStdHandle(STD_INPUT_HANDLE), &aBuffer, sizeof(aBuffer), &dwRead, NULL ) )
	{
        OSL_ASSERT((dwRead % 2) == 0);
        OUString value( aBuffer, dwRead / 2);
        return value.trim();
	}
#else
	char buf[1024];
	rtl_zeroMemory(buf, 1024);
	// read one char less so that the last char in buf is always zero
	if (fgets(buf, 1024, stdin) != NULL)
    {
        OUString value = ::rtl::OStringToOUString(::rtl::OString(buf), osl_getThreadTextEncoding());
        return value.trim();
    }
#endif
    return OUString();
}

void TRACE(::rtl::OUString const & sText)
{
    (void) sText;
#if OSL_DEBUG_LEVEL > 1
    writeConsole(sText);
#endif
}

void TRACE(::rtl::OString const & sText)
{
    (void) sText;
#if OSL_DEBUG_LEVEL > 1
    writeConsole(sText);
#endif
}

void syncRepositories(Reference<ucb::XCommandEnvironment> const & xCmdEnv)
{
    OUString sDisable;
    ::rtl::Bootstrap::get( OUSTR( "DISABLE_EXTENSION_SYNCHRONIZATION" ), sDisable, OUString() );
    if (sDisable.getLength() > 0)
        return;

    Reference<deployment::XExtensionManager> xExtensionManager;
    //synchronize shared before bundled otherewise there are
    //more revoke and registration calls.
    sal_Bool bModified = false;
    if (needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("shared")))
        || needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled"))))
    {
        xExtensionManager =          
            deployment::ExtensionManager::get(
                comphelper_getProcessComponentContext());

        if (xExtensionManager.is())
        {
            bModified = xExtensionManager->synchronize(
                Reference<task::XAbortChannel>(), xCmdEnv);
        }
    }

    if (bModified)
    {
        Reference<task::XRestartManager> restarter(
            comphelper_getProcessComponentContext()->getValueByName(
                OUSTR( "/singletons/com.sun.star.task.OfficeRestartManager") ), UNO_QUERY );
        if (restarter.is())
        {
            restarter->requestRestart(xCmdEnv.is() == sal_True ? xCmdEnv->getInteractionHandler() :
                                      Reference<task::XInteractionHandler>());
        }
     }
}



}
