1e421b30e2
Change-Id: I5b2556d1be61fa3a1d7996ce8d61958fbe7984c6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144002 Tested-by: Jenkins Reviewed-by: Tor Lillqvist <tml@collabora.com>
366 lines
10 KiB
C
366 lines
10 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
|
|
#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
|
|
|
|
#include <LibreOfficeKit/LibreOfficeKit.h>
|
|
|
|
#if defined __GNUC__ || defined __clang__
|
|
# define LOK_TOLERATE_UNUSED __attribute__((used))
|
|
#else
|
|
# define LOK_TOLERATE_UNUSED
|
|
#endif
|
|
|
|
#if defined(__linux__) || defined (__FreeBSD__) || defined(_AIX) ||\
|
|
defined(_WIN32) || defined(__APPLE__) || defined (__NetBSD__) ||\
|
|
defined (__sun) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
|
|
#ifndef _WIN32
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#ifdef _AIX
|
|
# include <sys/ldr.h>
|
|
#endif
|
|
#ifdef __APPLE__
|
|
#define TARGET_LIB "lib" "sofficeapp" ".dylib"
|
|
#define TARGET_MERGED_LIB "lib" "mergedlo" ".dylib"
|
|
#else
|
|
#define TARGET_LIB "lib" "sofficeapp" ".so"
|
|
#define TARGET_MERGED_LIB "lib" "mergedlo" ".so"
|
|
#endif
|
|
#define SEPARATOR '/'
|
|
|
|
#else
|
|
|
|
#if !defined WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#define TARGET_LIB "sofficeapp" ".dll"
|
|
#define TARGET_MERGED_LIB "mergedlo" ".dll"
|
|
#define SEPARATOR '\\'
|
|
#define UNOPATH "\\..\\URE\\bin"
|
|
|
|
#undef DELETE
|
|
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
|
|
|
#if !defined(IOS)
|
|
static void *lok_loadlib(const char *pFN)
|
|
{
|
|
return dlopen(pFN, RTLD_LAZY
|
|
#if defined LOK_LOADLIB_GLOBAL
|
|
| RTLD_GLOBAL
|
|
#endif
|
|
);
|
|
}
|
|
|
|
static char *lok_dlerror(void)
|
|
{
|
|
return dlerror();
|
|
}
|
|
|
|
// This function must be called to release memory allocated by lok_dlerror()
|
|
static void lok_dlerror_free(char *pErrMessage)
|
|
{
|
|
(void)pErrMessage;
|
|
// Do nothing for return of dlerror()
|
|
}
|
|
|
|
static void extendUnoPath(const char *pPath)
|
|
{
|
|
(void)pPath;
|
|
}
|
|
|
|
static void *lok_dlsym(void *Hnd, const char *pName)
|
|
{
|
|
return dlsym(Hnd, pName);
|
|
}
|
|
|
|
static int lok_dlclose(void *Hnd)
|
|
{
|
|
return dlclose(Hnd);
|
|
}
|
|
#endif // IOS
|
|
|
|
|
|
#else
|
|
static void *lok_loadlib(const char *pFN)
|
|
{
|
|
return (void *) LoadLibraryA(pFN);
|
|
}
|
|
|
|
static char *lok_dlerror(void)
|
|
{
|
|
LPSTR buf = NULL;
|
|
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, GetLastError(), 0, reinterpret_cast<LPSTR>(&buf), 0, NULL);
|
|
return buf;
|
|
}
|
|
|
|
// This function must be called to release memory allocated by lok_dlerror()
|
|
static void lok_dlerror_free(char *pErrMessage)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pErrMessage);
|
|
}
|
|
|
|
static void *lok_dlsym(void *Hnd, const char *pName)
|
|
{
|
|
return reinterpret_cast<void *>(GetProcAddress((HINSTANCE) Hnd, pName));
|
|
}
|
|
|
|
static int lok_dlclose(void *Hnd)
|
|
{
|
|
return FreeLibrary((HINSTANCE) Hnd);
|
|
}
|
|
|
|
static void extendUnoPath(const char *pPath)
|
|
{
|
|
char *sNewPath = NULL, *sEnvPath = NULL;
|
|
size_t size_sEnvPath = 0, buffer_size = 0;
|
|
DWORD cChars;
|
|
|
|
if (!pPath)
|
|
return;
|
|
|
|
cChars = GetEnvironmentVariableA("PATH", sEnvPath, 0);
|
|
if (cChars > 0)
|
|
{
|
|
sEnvPath = (char *) malloc(cChars);
|
|
cChars = GetEnvironmentVariableA("PATH", sEnvPath, cChars);
|
|
//If PATH is not set then it is no error
|
|
if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
|
|
{
|
|
free(sEnvPath);
|
|
return;
|
|
}
|
|
}
|
|
//prepare the new PATH. Add the Ure/bin directory at the front.
|
|
//note also adding ';'
|
|
if(sEnvPath)
|
|
size_sEnvPath = strlen(sEnvPath);
|
|
buffer_size = size_sEnvPath + 2*strlen(pPath) + strlen(UNOPATH) + 4;
|
|
sNewPath = (char *) malloc(buffer_size);
|
|
sNewPath[0] = L'\0';
|
|
strcat_s(sNewPath, buffer_size, pPath); // program to PATH
|
|
strcat_s(sNewPath, buffer_size, ";");
|
|
strcat_s(sNewPath, buffer_size, UNOPATH); // UNO to PATH
|
|
if (size_sEnvPath > 0)
|
|
{
|
|
strcat_s(sNewPath, buffer_size, ";");
|
|
strcat_s(sNewPath, buffer_size, sEnvPath);
|
|
}
|
|
|
|
SetEnvironmentVariableA("PATH", sNewPath);
|
|
|
|
free(sNewPath);
|
|
free(sEnvPath);
|
|
}
|
|
#endif
|
|
|
|
#if !defined(IOS)
|
|
static void *lok_dlopen( const char *install_path, char ** _imp_lib )
|
|
{
|
|
char *imp_lib;
|
|
void *dlhandle;
|
|
|
|
size_t partial_length, imp_lib_size;
|
|
struct stat dir_st;
|
|
|
|
*_imp_lib = NULL;
|
|
|
|
if (!install_path)
|
|
return NULL;
|
|
|
|
if (stat(install_path, &dir_st) != 0)
|
|
{
|
|
fprintf(stderr, "installation path \"%s\" does not exist\n", install_path);
|
|
return NULL;
|
|
}
|
|
|
|
// allocate large enough buffer
|
|
partial_length = strlen(install_path);
|
|
imp_lib_size = partial_length + sizeof(TARGET_LIB) + sizeof(TARGET_MERGED_LIB) + 2;
|
|
imp_lib = (char *) malloc(imp_lib_size);
|
|
if (!imp_lib)
|
|
{
|
|
fprintf( stderr, "failed to open library : not enough memory\n");
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(imp_lib, install_path, partial_length);
|
|
|
|
extendUnoPath(install_path);
|
|
|
|
imp_lib[partial_length++] = SEPARATOR;
|
|
strncpy(imp_lib + partial_length, TARGET_LIB, imp_lib_size - partial_length);
|
|
|
|
dlhandle = lok_loadlib(imp_lib);
|
|
if (!dlhandle)
|
|
{
|
|
// If TARGET_LIB exists, and likely is a real library (not a
|
|
// small one-line text stub as in the --enable-mergedlib
|
|
// case), but dlopen failed for some reason, don't try
|
|
// TARGET_MERGED_LIB.
|
|
struct stat st;
|
|
if (stat(imp_lib, &st) == 0 && st.st_size > 100)
|
|
{
|
|
char *pErrMessage = lok_dlerror();
|
|
fprintf(stderr, "failed to open library '%s': %s\n",
|
|
imp_lib, pErrMessage);
|
|
lok_dlerror_free(pErrMessage);
|
|
free(imp_lib);
|
|
return NULL;
|
|
}
|
|
|
|
strncpy(imp_lib + partial_length, TARGET_MERGED_LIB, imp_lib_size - partial_length);
|
|
|
|
dlhandle = lok_loadlib(imp_lib);
|
|
if (!dlhandle)
|
|
{
|
|
char *pErrMessage = lok_dlerror();
|
|
fprintf(stderr, "failed to open library '%s': %s\n",
|
|
imp_lib, pErrMessage);
|
|
lok_dlerror_free(pErrMessage);
|
|
free(imp_lib);
|
|
return NULL;
|
|
}
|
|
}
|
|
*_imp_lib = imp_lib;
|
|
return dlhandle;
|
|
}
|
|
#endif
|
|
|
|
typedef LibreOfficeKit *(LokHookFunction)( const char *install_path);
|
|
|
|
typedef LibreOfficeKit *(LokHookFunction2)( const char *install_path, const char *user_profile_url );
|
|
|
|
typedef int (LokHookPreInit) ( const char *install_path, const char *user_profile_url );
|
|
|
|
typedef int (LokHookPreInit2) ( const char *install_path, const char *user_profile_url, LibreOfficeKit** kit);
|
|
|
|
#if defined(IOS) || defined(ANDROID) || defined(__EMSCRIPTEN__)
|
|
LibreOfficeKit *libreofficekit_hook_2(const char* install_path, const char* user_profile_path);
|
|
#endif
|
|
|
|
static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_profile_url )
|
|
{
|
|
#if !defined(IOS) && !defined(ANDROID) && !defined(__EMSCRIPTEN__)
|
|
void *dlhandle;
|
|
char *imp_lib;
|
|
LokHookFunction *pSym;
|
|
LokHookFunction2 *pSym2;
|
|
|
|
dlhandle = lok_dlopen(install_path, &imp_lib);
|
|
if (!dlhandle)
|
|
return NULL;
|
|
|
|
pSym2 = (LokHookFunction2 *) lok_dlsym(dlhandle, "libreofficekit_hook_2");
|
|
if (!pSym2)
|
|
{
|
|
if (user_profile_url != NULL)
|
|
{
|
|
fprintf( stderr, "the LibreOffice version in '%s' does not support passing a user profile to the hook function\n",
|
|
imp_lib );
|
|
lok_dlclose( dlhandle );
|
|
free( imp_lib );
|
|
return NULL;
|
|
}
|
|
pSym = (LokHookFunction *) lok_dlsym( dlhandle, "libreofficekit_hook" );
|
|
if (!pSym)
|
|
{
|
|
fprintf( stderr, "failed to find hook in library '%s'\n", imp_lib );
|
|
lok_dlclose( dlhandle );
|
|
free( imp_lib );
|
|
return NULL;
|
|
}
|
|
free( imp_lib );
|
|
// dlhandle is "leaked"
|
|
// coverity[leaked_storage] - on purpose
|
|
return pSym( install_path );
|
|
}
|
|
|
|
if (user_profile_url != NULL && user_profile_url[0] == '/')
|
|
{
|
|
// It should be either a file: URL or a vnd.sun.star.pathname: URL.
|
|
fprintf( stderr, "second parameter to lok_init_2 '%s' should be a URL, not a pathname\n", user_profile_url );
|
|
lok_dlclose( dlhandle );
|
|
free( imp_lib );
|
|
return NULL;
|
|
}
|
|
|
|
free( imp_lib );
|
|
// dlhandle is "leaked"
|
|
// coverity[leaked_storage] - on purpose
|
|
return pSym2( install_path, user_profile_url );
|
|
#else
|
|
return libreofficekit_hook_2( install_path, user_profile_url );
|
|
#endif
|
|
}
|
|
|
|
static LOK_TOLERATE_UNUSED
|
|
LibreOfficeKit *lok_init( const char *install_path )
|
|
{
|
|
return lok_init_2( install_path, NULL );
|
|
}
|
|
|
|
#if !defined(IOS)
|
|
static LOK_TOLERATE_UNUSED
|
|
int lok_preinit( const char *install_path, const char *user_profile_url )
|
|
{
|
|
void *dlhandle;
|
|
char *imp_lib;
|
|
LokHookPreInit *pSym;
|
|
|
|
dlhandle = lok_dlopen(install_path, &imp_lib);
|
|
if (!dlhandle)
|
|
return -1;
|
|
|
|
pSym = (LokHookPreInit *) lok_dlsym(dlhandle, "lok_preinit");
|
|
if (!pSym)
|
|
{
|
|
fprintf( stderr, "failed to find pre-init hook in library '%s'\n", imp_lib );
|
|
lok_dlclose( dlhandle );
|
|
free( imp_lib );
|
|
return -1;
|
|
}
|
|
|
|
free( imp_lib );
|
|
|
|
// dlhandle is "leaked"
|
|
// coverity[leaked_storage] - on purpose
|
|
return pSym( install_path, user_profile_url );
|
|
}
|
|
#endif
|
|
|
|
#undef SEPARATOR // It is used at least in enum class MenuItemType
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // defined(__linux__) || defined (__FreeBSD__) || defined(_AIX) || defined(_WIN32) || defined(__APPLE__)
|
|
|
|
#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|