collabora-online/bundled/include/LibreOfficeKit/LibreOfficeKitInit.h

294 lines
7.7 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.h"
#ifdef __cplusplus
extern "C"
{
#endif
#if defined(__linux__) || defined (__FreeBSD_kernel__) || defined(_AIX) ||\
defined(_WIN32) || defined(__APPLE__) || defined (__NetBSD__) ||\
defined (__sun) || defined(__OpenBSD__)
#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 '/'
inline void *lok_loadlib(const char *pFN)
{
return dlopen(pFN, RTLD_LAZY
#if defined LOK_LOADLIB_GLOBAL
| RTLD_GLOBAL
#endif
);
}
#ifndef __OBJC__
inline
#endif
char *lok_dlerror(void)
{
return dlerror();
}
#ifndef __OBJC__
inline
#endif
void *lok_dlsym(void *Hnd, const char *pName)
{
return dlsym(Hnd, pName);
}
#ifndef __OBJC__
inline
#endif
int lok_dlclose(void *Hnd)
{
return dlclose(Hnd);
}
#ifndef __OBJC__
inline
#endif
void extendUnoPath(const char *pPath)
{
(void)pPath;
}
#else
#include <windows.h>
#define TARGET_LIB "sofficeapp" ".dll"
#define TARGET_MERGED_LIB "mergedlo" ".dll"
#define SEPARATOR '\\'
#define UNOPATH "\\..\\URE\\bin"
void *lok_loadlib(const char *pFN)
{
return (void *) LoadLibraryA(pFN);
}
char *lok_dlerror(void)
{
LPSTR buf = NULL;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, reinterpret_cast<LPSTR>(&buf), 0, NULL);
return buf;
}
void *lok_dlsym(void *Hnd, const char *pName)
{
return reinterpret_cast<void *>(GetProcAddress((HINSTANCE) Hnd, pName));
}
int lok_dlclose(void *Hnd)
{
return FreeLibrary((HINSTANCE) Hnd);
}
void extendUnoPath(const char *pPath)
{
if (!pPath)
return;
char* sEnvPath = NULL;
DWORD cChars = GetEnvironmentVariableA("PATH", sEnvPath, 0);
if (cChars > 0)
{
sEnvPath = new char[cChars];
cChars = GetEnvironmentVariableA("PATH", sEnvPath, cChars);
//If PATH is not set then it is no error
if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
{
delete[] sEnvPath;
return;
}
}
//prepare the new PATH. Add the Ure/bin directory at the front.
//note also adding ';'
char * sNewPath = new char[strlen(sEnvPath) + strlen(pPath) * 2 + strlen(UNOPATH) + 4];
sNewPath[0] = L'\0';
strcat(sNewPath, pPath); // program to PATH
strcat(sNewPath, ";");
strcat(sNewPath, UNOPATH); // UNO to PATH
if (strlen(sEnvPath))
{
strcat(sNewPath, ";");
strcat(sNewPath, sEnvPath);
}
SetEnvironmentVariableA("PATH", sNewPath);
delete[] sEnvPath;
delete[] sNewPath;
}
#endif
static void *lok_dlopen( const char *install_path, char ** _imp_lib )
{
char *imp_lib;
void *dlhandle;
*_imp_lib = NULL;
#if !(defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)))
size_t partial_length;
if (!install_path)
return NULL;
struct stat dir_st;
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);
size_t 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;
}
strncpy(imp_lib, install_path, imp_lib_size);
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)
{
fprintf(stderr, "failed to open library '%s': %s\n",
imp_lib, lok_dlerror());
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)
{
fprintf(stderr, "failed to open library '%s': %s\n",
imp_lib, lok_dlerror());
free(imp_lib);
return NULL;
}
}
#else
imp_lib = strdup("the app executable");
dlhandle = RTLD_MAIN_ONLY;
#endif
*_imp_lib = imp_lib;
return dlhandle;
}
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 );
static LibreOfficeKit *lok_init_2( const char *install_path, const char *user_profile_url )
{
char *imp_lib;
void *dlhandle;
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]
return pSym( install_path );
}
free( imp_lib );
// dlhandle is "leaked"
// coverity[leaked_storage]
return pSym2( install_path, user_profile_url );
}
static
#if defined __GNUC__ || defined __clang__
__attribute__((used))
#endif
LibreOfficeKit *lok_init( const char *install_path )
{
return lok_init_2( install_path, NULL );
}
#undef SEPARATOR // It is used at least in enum class MenuItemType
#endif // defined(__linux__) || defined (__FreeBSD_kernel__) || defined(_AIX) || defined(_WIN32) || defined(__APPLE__)
#ifdef __cplusplus
}
#endif
#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */