summaryrefslogtreecommitdiffstats
path: root/include/LibreOfficeKit/LibreOfficeKitInit.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/LibreOfficeKit/LibreOfficeKitInit.h')
-rw-r--r--include/LibreOfficeKit/LibreOfficeKitInit.h363
1 files changed, 363 insertions, 0 deletions
diff --git a/include/LibreOfficeKit/LibreOfficeKitInit.h b/include/LibreOfficeKit/LibreOfficeKitInit.h
new file mode 100644
index 0000000000..695784d279
--- /dev/null
+++ b/include/LibreOfficeKit/LibreOfficeKitInit.h
@@ -0,0 +1,363 @@
+/* -*- 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(_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 __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(_WIN32) || defined(__APPLE__)
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKITINIT_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */