diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6294cea6c..0e67ef745 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,221 +1,222 @@ # target_include_directories does not handle empty include paths include_directories(${GPGME_INCLUDES}) add_definitions(-DTRANSLATION_DOMAIN=\"libkleopatra\") #add_definitions( -DQT_NO_CAST_FROM_ASCII ) #add_definitions( -DQT_NO_CAST_TO_ASCII ) kde_enable_exceptions() add_definitions( -DGPGMEPP_ERR_SOURCE_DEFAULT=13 ) # 13 is GPG_ERR_SOURCE_KLEO, even if gpg-error's too old to know about add_subdirectory( pics ) if (BUILD_TESTING) add_subdirectory( tests ) endif() ########### next target ############### set(libkleo_core_SRCS kleo/checksumdefinition.cpp kleo/defaultkeyfilter.cpp kleo/defaultkeygenerationjob.cpp kleo/dn.cpp kleo/enum.cpp kleo/exception.cpp kleo/kconfigbasedkeyfilter.cpp kleo/keyfiltermanager.cpp kleo/keyresolver.cpp models/keycache.cpp models/keylistmodel.cpp models/keylistsortfilterproxymodel.cpp models/keyrearrangecolumnsproxymodel.cpp models/subkeylistmodel.cpp models/useridlistmodel.cpp utils/filesystemwatcher.cpp utils/formatting.cpp utils/classify.cpp utils/gnupg.cpp + utils/gnupg-registry.c utils/hex.cpp ) ecm_qt_declare_logging_category(libkleo_core_SRCS HEADER libkleo_debug.h IDENTIFIER LIBKLEO_LOG CATEGORY_NAME org.kde.pim.libkleo DESCRIPTION "libkleo (kleo_core)" EXPORT LIBKLEO ) set(libkleo_ui_common_SRCS ui/dnattributeorderconfigwidget.cpp ui/kdhorizontalline.cpp ui/filenamerequester.cpp ui/messagebox.cpp ui/cryptoconfigmodule.cpp ui/cryptoconfigdialog.cpp ui/directoryserviceswidget.cpp ui/progressbar.cpp ui/progressdialog.cpp ui/auditlogviewer.cpp ) ecm_qt_declare_logging_category(libkleo_ui_common_SRCS HEADER kleo_ui_debug.h IDENTIFIER KLEO_UI_LOG CATEGORY_NAME org.kde.pim.kleo_ui DESCRIPTION "libkleo (kleo_ui)" OLD_CATEGORY_NAMES log_kleo_ui EXPORT LIBKLEO ) set(libkleo_ui_SRCS # make this a separate lib. ui/keylistview.cpp ui/keyselectiondialog.cpp ui/keyrequester.cpp ui/keyapprovaldialog.cpp ui/newkeyapprovaldialog.cpp ui/keyselectioncombo.cpp ) ki18n_wrap_ui(libkleo_ui_common_SRCS ui/directoryserviceswidget.ui ) set(kleo_LIB_SRCS ${libkleo_core_SRCS} ${libkleo_ui_SRCS} ${libkleo_ui_common_SRCS}) set(kleo_LIB_LIBS PUBLIC QGpgme Gpgmepp PRIVATE Qt5::Widgets KF5::I18n KF5::Completion KF5::ConfigCore KF5::CoreAddons KF5::WidgetsAddons KF5::ItemModels KF5::Codecs) if (KF5PimTextEdit_FOUND) add_definitions(-DHAVE_PIMTEXTEDIT) set(kleo_LIB_LIBS ${kleo_LIB_LIBS} PRIVATE KF5::PimTextEdit) endif() add_library(KF5Libkleo ${kleo_LIB_SRCS}) generate_export_header(KF5Libkleo BASE_NAME kleo) add_library(KF5::Libkleo ALIAS KF5Libkleo) if(WIN32) target_link_libraries(KF5Libkleo ${kleo_LIB_LIBS} ${GPGME_VANILLA_LIBRARIES} ) else() target_link_libraries(KF5Libkleo ${kleo_LIB_LIBS} ) endif() set_target_properties(KF5Libkleo PROPERTIES VERSION ${LIBKLEO_VERSION_STRING} SOVERSION ${LIBKLEO_SOVERSION} EXPORT_NAME Libkleo ) install(TARGETS KF5Libkleo EXPORT KF5LibkleoTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS} ${LIBRARY_NAMELINK} ) target_include_directories(KF5Libkleo PUBLIC "$") target_include_directories(KF5Libkleo INTERFACE "$") ecm_generate_headers(libkleo_CamelCase_HEADERS HEADER_NAMES ChecksumDefinition DefaultKeyFilter DefaultKeyGenerationJob Dn Enum Exception KConfigBasedKeyFilter KeyFilter KeyFilterManager KeyResolver OidMap Predicates Stl_Util REQUIRED_HEADERS libkleo_HEADERS PREFIX Libkleo RELATIVE kleo ) ecm_generate_headers(libkleo_CamelCase_models_HEADERS HEADER_NAMES KeyCache KeyListModel KeyListModelInterface KeyListSortFilterProxyModel KeyRearrangeColumnsProxyModel SubkeyListModel UserIDListModel REQUIRED_HEADERS libkleo_models_HEADERS PREFIX Libkleo RELATIVE models ) ecm_generate_headers(libkleo_CamelCase_utils_HEADERS HEADER_NAMES Classify FileSystemWatcher Formatting GnuPG REQUIRED_HEADERS libkleo_utils_HEADERS PREFIX Libkleo RELATIVE utils ) ecm_generate_headers(libkleo_CamelCase_ui_HEADERS HEADER_NAMES CryptoConfigDialog CryptoConfigModule DNAttributeOrderConfigWidget DirectoryServicesWidget FileNameRequester KDHorizontalLine KeyApprovalDialog NewKeyApprovalDialog KeyRequester KeySelectionCombo KeySelectionDialog MessageBox ProgressDialog REQUIRED_HEADERS libkleo_ui_HEADERS PREFIX Libkleo RELATIVE ui ) ecm_generate_pri_file(BASE_NAME Libkleo LIB_NAME KF5Libkleo DEPS "QGpgme" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/Libkleo ) install(FILES ${libkleo_CamelCase_HEADERS} ${libkleo_CamelCase_models_HEADERS} ${libkleo_CamelCase_ui_HEADERS} ${libkleo_CamelCase_utils_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/Libkleo COMPONENT Devel ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kleo_export.h ${libkleo_HEADERS} ${libkleo_models_HEADERS} ${libkleo_ui_HEADERS} ${libkleo_utils_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/libkleo COMPONENT Devel ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) if ( WIN32 ) install ( FILES libkleopatrarc-win32.desktop DESTINATION ${KDE_INSTALL_CONFDIR} RENAME libkleopatrarc ) else () install ( FILES libkleopatrarc.desktop DESTINATION ${KDE_INSTALL_CONFDIR} RENAME libkleopatrarc ) endif () diff --git a/src/utils/gnupg-registry.c b/src/utils/gnupg-registry.c new file mode 100644 index 000000000..84c0acf11 --- /dev/null +++ b/src/utils/gnupg-registry.c @@ -0,0 +1,274 @@ +/* registry.c - Registry routines + Copyright (C) 2005, 2007 g10 Code GmbH + + This file is part of GpgEX. + + GpgEX is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 + of the License, or (at your option) any later version. + + GpgEX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* keep this in sync with svn://cvs.gnupg.org/gpgex/trunk/src/registry.c (last checked against rev. 32) */ + +#ifdef _WIN32 + +#include +#include + +#include +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a +#endif +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif +#ifndef CSIDL_FLAG_CREATE +#define CSIDL_FLAG_CREATE 0x8000 +#endif + +#include "gnupg-registry.h" + +/* This is a helper function to load a Windows function from either of + one DLLs. */ +HRESULT +w32_shgetfolderpath(HWND a, int b, HANDLE c, DWORD d, LPSTR e) +{ + static int initialized; + static HRESULT(WINAPI * func)(HWND, int, HANDLE, DWORD, LPSTR); + + if (!initialized) { + static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL }; + void *handle; + int i; + + initialized = 1; + + for (i = 0, handle = NULL; !handle && dllnames[i]; i++) { + handle = LoadLibraryA(dllnames[i]); + if (handle) { + func = (HRESULT(WINAPI *)(HWND, int, HANDLE, DWORD, LPSTR)) + GetProcAddress(handle, "SHGetFolderPathA"); + if (!func) { + FreeLibrary(handle); + handle = NULL; + } + } + } + } + + if (func) { + return func(a, b, c, d, e); + } else { + return -1; + } +} + +/* Helper for read_w32_registry_string(). */ +static HKEY +get_root_key(const char *root) +{ + HKEY root_key; + + if (!root) { + root_key = HKEY_CURRENT_USER; + } else if (!strcmp(root, "HKEY_CLASSES_ROOT")) { + root_key = HKEY_CLASSES_ROOT; + } else if (!strcmp(root, "HKEY_CURRENT_USER")) { + root_key = HKEY_CURRENT_USER; + } else if (!strcmp(root, "HKEY_LOCAL_MACHINE")) { + root_key = HKEY_LOCAL_MACHINE; + } else if (!strcmp(root, "HKEY_USERS")) { + root_key = HKEY_USERS; + } else if (!strcmp(root, "HKEY_PERFORMANCE_DATA")) { + root_key = HKEY_PERFORMANCE_DATA; + } else if (!strcmp(root, "HKEY_CURRENT_CONFIG")) { + root_key = HKEY_CURRENT_CONFIG; + } else { + return NULL; + } + return root_key; +} + +/* Return a string from the Win32 Registry or NULL in case of error. + Caller must release the return value. A NULL for root is an alias + for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */ +char * +read_w32_registry_string(const char *root, const char *dir, const char *name) +{ + HKEY root_key, key_handle; + DWORD n1, nbytes, type; + char *result = NULL; + + if (!(root_key = get_root_key(root))) { + return NULL; + } + + if (RegOpenKeyExA(root_key, dir, 0, KEY_READ, &key_handle)) { + if (root) { + return NULL; /* no need for a RegClose, so return direct */ + } + /* It seems to be common practice to fall back to HKLM. */ + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle)) { + return NULL; /* still no need for a RegClose, so return direct */ + } + } + + nbytes = 1; + if (RegQueryValueExA(key_handle, name, 0, NULL, NULL, &nbytes)) { + if (root) { + goto leave; + } + /* Try to fallback to HKLM also vor a missing value. */ + RegCloseKey(key_handle); + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle)) { + return NULL; /* Nope. */ + } + if (RegQueryValueExA(key_handle, name, 0, NULL, NULL, &nbytes)) { + goto leave; + } + } + result = malloc((n1 = nbytes + 1)); + if (!result) { + goto leave; + } + if (RegQueryValueExA(key_handle, name, 0, &type, result, &n1)) { + free(result); result = NULL; + goto leave; + } + result[nbytes] = 0; /* make sure it is really a string */ + if (type == REG_EXPAND_SZ && strchr(result, '%')) { + char *tmp; + + n1 += 1000; + tmp = malloc(n1 + 1); + if (!tmp) { + goto leave; + } + nbytes = ExpandEnvironmentStringsA(result, tmp, n1); + if (nbytes && nbytes > n1) { + free(tmp); + n1 = nbytes; + tmp = malloc(n1 + 1); + if (!tmp) { + goto leave; + } + nbytes = ExpandEnvironmentStringsA(result, tmp, n1); + if (nbytes && nbytes > n1) { + free(tmp); /* oops - truncated, better don't expand at all */ + goto leave; + } + tmp[nbytes] = 0; + free(result); + result = tmp; + } else if (nbytes) { /* okay, reduce the length */ + tmp[nbytes] = 0; + free(result); + result = malloc(strlen(tmp) + 1); + if (!result) { + result = tmp; + } else { + strcpy(result, tmp); + free(tmp); + } + } else { /* error - don't expand */ + free(tmp); + } + } + +leave: + RegCloseKey(key_handle); + return result; +} + +/* Get the standard home directory. In general this function should + not be used as it does not consider a registry value (under W32) or + the GNUPGHOME encironment variable. It is better to use + default_homedir(). */ +static char * +standard_homedir(void) +{ + static char *dir; + + if (!dir) { + char path[MAX_PATH]; + + /* It might be better to use LOCAL_APPDATA because this is + defined as "non roaming" and thus more likely to be kept + locally. For private keys this is desired. However, given + that many users copy private keys anyway forth and back, + using a system roaming services might be better than to let + them do it manually. A security conscious user will anyway + use the registry entry to have better control. */ + if (w32_shgetfolderpath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, + NULL, 0, path) >= 0) { + char *tmp = malloc(strlen(path) + 6 + 1); + + if (!tmp) { + dir = strdup ("C:\\gnupg"); + return dir; + } + + strcpy(tmp, path); + strcat(tmp, "\\gnupg"); + + dir = tmp; + + /* Try to create the directory if it does not yet exists. */ + if (access(dir, F_OK)) { + CreateDirectoryA(dir, NULL); + } + } else { + dir = strdup("C:\\gnupg"); + } + } + return dir; +} + +/* Retrieve the default home directory. */ +char * +default_homedir(void) +{ + char *dir; + + dir = getenv("GNUPGHOME"); + if (!dir || !*dir) { + static char *saved_dir; + + if (!saved_dir) { + if (!dir || !*dir) { + char *tmp; + + tmp = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "HomeDir"); + if (tmp && !*tmp) { + free(tmp); + tmp = NULL; + } + if (tmp) { + saved_dir = tmp; + } + } + + if (!saved_dir) { + saved_dir = standard_homedir(); + } + } + dir = saved_dir; + } + if (!dir || !*dir) { + dir = strdup("C:\\gnupg"); + } + + return dir; +} +#endif //_WIN32 diff --git a/src/utils/gnupg-registry.h b/src/utils/gnupg-registry.h new file mode 100644 index 000000000..14e90aae6 --- /dev/null +++ b/src/utils/gnupg-registry.h @@ -0,0 +1,55 @@ +/* registry.h - registry prototypes + Copyright (C) 2006, 2007 g10 Code GmbH + + This file is part of GpgEX. + + GpgEX is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GpgEX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* keep this in sync with svn://cvs.gnupg.org/gpgex/trunk/src/registry.h (last checked against rev. 19) */ + +#ifndef REGISTRY_H +#define REGISTRY_H + +#include + +#ifdef __cplusplus +extern "C" { +#if 0 +} +#endif +#endif + +/* This is a helper function to load a Windows function from either of + one DLLs. */ +HRESULT w32_shgetfolderpath(HWND a, int b, HANDLE c, DWORD d, LPSTR e); + +/* Return a string from the Win32 Registry or NULL in case of error. + Caller must release the return value. A NULL for root is an alias + for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */ +char *read_w32_registry_string(const char *root, const char *dir, + const char *name); + +/* Retrieve the default home directory. */ +char *default_homedir(void); + +#ifdef __cplusplus +#if 0 +{ +#endif +} +#endif + +#endif /* ! REGISTRY_H */