plover/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri Jul 08 08:26:29 2016 +0100 (2016-07-08)
changeset 59 296eac3183bc
parent 38 a29623b68ca2
child 61 31fb35727621
permissions -rw-r--r--
Second steps towards adding updatez
ali@0
     1
/*
ali@31
     2
 * Copyright (C) 2009, 2011, 2014, 2015  J. Ali Harlow <ali@juiblex.co.uk>
ali@0
     3
 *
ali@0
     4
 * This program is free software; you can redistribute it and/or modify
ali@0
     5
 * it under the terms of the GNU General Public License as published by
ali@0
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@0
     7
 * (at your option) any later version.
ali@0
     8
 *
ali@0
     9
 * This program is distributed in the hope that it will be useful,
ali@0
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@0
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@0
    12
 * GNU General Public License for more details.
ali@0
    13
 *
ali@0
    14
 * You should have received a copy of the GNU General Public License along
ali@0
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@0
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@0
    17
 */
ali@0
    18
ali@0
    19
#include <stdlib.h>
ali@0
    20
#include <stdarg.h>
ali@0
    21
#include <string.h>
ali@3
    22
#include <limits.h>
ali@3
    23
#ifdef WIN32
ali@3
    24
#include <windows.h>
ali@3
    25
#include <shlobj.h>
ali@3
    26
#endif
ali@31
    27
#include <glib.h>
ali@31
    28
#include <glib/gstdio.h>
ali@0
    29
#include "config.h"
ali@0
    30
#include "plover.h"
ali@0
    31
ali@24
    32
gchar *plover_default_prefix_for_vendor(const char *vendor)
ali@3
    33
{
ali@3
    34
#ifdef WIN32
ali@13
    35
    /*
ali@13
    36
     * We want to sidestep any redirecting that MS-Windows may
ali@13
    37
     * introduce since this will be based on the architecture
ali@13
    38
     * of the installer whereas the architecture that actually
ali@13
    39
     * matters is of the packages (checked elsewhere).
ali@13
    40
     */
ali@13
    41
    BOOL is_wow64=FALSE;
ali@13
    42
    typedef BOOL (WINAPI *is_wow64_process_t)(HANDLE,PBOOL);
ali@13
    43
    is_wow64_process_t is_wow64_process;
ali@13
    44
    char *program_files=NULL;
ali@13
    45
    char buf[PATH_MAX];
ali@13
    46
    is_wow64_process=(is_wow64_process_t)
ali@13
    47
      GetProcAddress(GetModuleHandleA("kernel32"),"IsWow64Process");
ali@13
    48
    if (is_wow64_process)
ali@13
    49
	is_wow64_process(GetCurrentProcess(),&is_wow64);
ali@13
    50
    if (is_wow64)
ali@13
    51
	program_files=getenv("ProgramW6432");
ali@13
    52
    if (!program_files)
ali@13
    53
    {
ali@13
    54
	SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES|CSIDL_FLAG_DONT_VERIFY,NULL,0,
ali@13
    55
	  buf);
ali@13
    56
	program_files=buf;
ali@13
    57
    }
ali@24
    58
    return g_strconcat(program_files,"\\",vendor?vendor:"Plover",NULL);
ali@3
    59
#else
ali@38
    60
    const char *vendor_prefix;
ali@38
    61
    vendor_prefix=g_getenv("PLOVER_VENDOR_PREFIX");
ali@38
    62
    if (!vendor_prefix)
ali@38
    63
	return NULL;
ali@38
    64
    else
ali@38
    65
	return g_build_filename(vendor_prefix,vendor?vendor:"Plover",NULL);
ali@3
    66
#endif
ali@3
    67
}
ali@3
    68
ali@24
    69
gchar *plover_pre_install_prefix(void)
ali@24
    70
{
ali@24
    71
#ifdef WIN32
ali@24
    72
    {
ali@24
    73
	HRESULT result;
ali@24
    74
	HKEY key;
ali@24
    75
	DWORD type,nb;
ali@24
    76
	int len;
ali@24
    77
	gunichar2 *str2;
ali@24
    78
	gchar *root=NULL;
ali@24
    79
	result=RegOpenKeyW(HKEY_LOCAL_MACHINE,L"Software\\Plover",&key);
ali@24
    80
	if (result==ERROR_SUCCESS)
ali@24
    81
	{
ali@24
    82
	    result=RegQueryValueExW(key,L"Root",0,&type,0,&nb);
ali@24
    83
	    if (result==ERROR_SUCCESS && type==REG_SZ)
ali@24
    84
	    {
ali@24
    85
		str2=malloc(nb);
ali@24
    86
		result=RegQueryValueExW(key,L"Root",0,NULL,(void *)str2,&nb);
ali@24
    87
		len=nb/2;
ali@24
    88
		if (!str2[len-1])       /* Cope with unterminated strings */
ali@24
    89
		    len--;
ali@24
    90
		root=g_utf16_to_utf8(str2,len,NULL,NULL,NULL);
ali@24
    91
		free(str2);
ali@24
    92
	    }
ali@24
    93
	    RegCloseKey(key);
ali@24
    94
	}
ali@24
    95
	if (!root)
ali@24
    96
	{
ali@24
    97
	    root=plover_default_prefix_for_vendor("Plover Root");
ali@24
    98
	    result=RegCreateKeyExW(HKEY_LOCAL_MACHINE,L"Software\\Plover",0,
ali@24
    99
	      NULL,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&key,NULL);
ali@24
   100
	    if (result==ERROR_SUCCESS)
ali@24
   101
	    {
ali@24
   102
		str2=g_utf8_to_utf16(root,-1,NULL,NULL,NULL);
ali@24
   103
		RegSetValueExW(key,L"Root",0,REG_SZ,(void *)str2,
ali@24
   104
		  (strlen(root)+1)*sizeof(gunichar2));
ali@24
   105
		g_free(str2);
ali@24
   106
		RegCloseKey(key);
ali@24
   107
	    }
ali@24
   108
	}
ali@24
   109
	return root;
ali@24
   110
    }
ali@24
   111
#else
ali@24
   112
    return g_strdup("/var/lib/plover/root");
ali@24
   113
#endif
ali@24
   114
}
ali@24
   115
ali@31
   116
#define MAX_REPORTS     12
ali@31
   117
ali@31
   118
struct plover_util_file {
ali@31
   119
    gchar *name;
ali@31
   120
    time_t mtime;
ali@31
   121
};
ali@31
   122
ali@31
   123
static int plover_util_compare_files(gconstpointer a,gconstpointer b)
ali@31
   124
{
ali@31
   125
    struct plover_util_file *fa=(struct plover_util_file *)a;
ali@31
   126
    struct plover_util_file *fb=(struct plover_util_file *)b;
ali@31
   127
    return fa->mtime-fb->mtime;
ali@31
   128
}
ali@31
   129
ali@31
   130
/*
ali@31
   131
 * Limit the number of reports to MAX_REPORTS
ali@31
   132
 */
ali@31
   133
ali@31
   134
void plover_purge_reports(const char *path)
ali@31
   135
{
ali@31
   136
    const char *name;
ali@31
   137
    GStatBuf sbuf;
ali@31
   138
    int count=0;
ali@31
   139
    GDir *d;
ali@31
   140
    GError *err=NULL;
ali@31
   141
    GList *files=NULL;
ali@31
   142
    struct plover_util_file *file;
ali@31
   143
    d=g_dir_open(path,0,&err);
ali@31
   144
    if (!d)
ali@31
   145
    {
ali@31
   146
	if (g_error_matches(err,G_FILE_ERROR,G_FILE_ERROR_NOENT))
ali@31
   147
	    g_mkdir_with_parents(path,0777);
ali@31
   148
	return;
ali@31
   149
    }
ali@31
   150
    while(count<=MAX_REPORTS && g_dir_read_name(d))
ali@31
   151
	count++;
ali@31
   152
    if (count>MAX_REPORTS)
ali@31
   153
    {
ali@31
   154
	g_dir_rewind(d);
ali@31
   155
	while((name=g_dir_read_name(d)))
ali@31
   156
	{
ali@31
   157
	    file=g_new(struct plover_util_file,1);
ali@31
   158
	    file->name=g_build_filename(path,name,NULL);
ali@31
   159
	    if (!g_stat(file->name,&sbuf))
ali@31
   160
		file->mtime=sbuf.st_mtime;
ali@31
   161
	    else
ali@31
   162
		file->mtime=0;
ali@31
   163
	    files=g_list_prepend(files,file);
ali@31
   164
	}
ali@31
   165
	files=g_list_sort(files,plover_util_compare_files);
ali@31
   166
	while(files)
ali@31
   167
	{
ali@31
   168
	    file=(struct plover_util_file *)files->data;
ali@31
   169
	    if (count>MAX_REPORTS)
ali@31
   170
	    {
ali@31
   171
		count--;
ali@31
   172
		g_remove(file->name);
ali@31
   173
	    }
ali@31
   174
	    g_free(file->name);
ali@31
   175
	    g_free(file);
ali@31
   176
	    files=g_list_delete_link(files,files);
ali@31
   177
	}
ali@31
   178
    }
ali@31
   179
    g_dir_close(d);
ali@31
   180
}
ali@31
   181
ali@31
   182
gchar *plover_get_reports_directory(void)
ali@31
   183
{
ali@31
   184
    gchar *path=NULL;
ali@31
   185
#ifdef WIN32
ali@31
   186
    HKEY key;
ali@31
   187
    DWORD rtype,nb;
ali@31
   188
    int len;
ali@31
   189
    long retval;
ali@31
   190
    gunichar2 *str2;
ali@31
   191
    char *dir;
ali@31
   192
    retval=RegOpenKeyW(HKEY_LOCAL_MACHINE,L"Software\\Plover",&key);
ali@31
   193
    if (SUCCEEDED(retval))
ali@31
   194
    {
ali@31
   195
	nb=200;
ali@31
   196
	str2=malloc(nb);
ali@31
   197
	retval=RegQueryValueExW(key,L"Reports",0,&rtype,(void *)str2,&nb);
ali@31
   198
	if (retval==ERROR_MORE_DATA)
ali@31
   199
	{
ali@31
   200
	    g_free(str2);
ali@31
   201
	    str2=malloc(nb);
ali@31
   202
	    retval=RegQueryValueExW(key,L"Reports",0,NULL,(void *)str2,&nb);
ali@31
   203
	}
ali@31
   204
	if (SUCCEEDED(retval) && rtype==REG_SZ)
ali@31
   205
	{
ali@31
   206
	    len=nb/2;
ali@31
   207
	    if (!str2[len-1])       /* Cope with unterminated strings */
ali@31
   208
		len--;
ali@31
   209
	    path=g_utf16_to_utf8(str2,len,NULL,NULL,NULL);
ali@31
   210
	}
ali@31
   211
	RegCloseKey(key);
ali@31
   212
	g_free(str2);
ali@31
   213
    }
ali@31
   214
    if (!path)
ali@31
   215
    {
ali@31
   216
	WCHAR wpath[MAX_PATH];
ali@31
   217
	retval=SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,
ali@31
   218
	SHGFP_TYPE_CURRENT,wpath);
ali@31
   219
	if (SUCCEEDED(retval))
ali@31
   220
	    dir=g_utf16_to_utf8((const gunichar2 *)wpath,-1,NULL,NULL,NULL);
ali@31
   221
	else
ali@31
   222
	    dir=g_strdup(
ali@31
   223
	      "C:\\Documents and Settings\\All Users\\Application Data");
ali@31
   224
	path=g_build_filename(dir,"plover","reports",NULL);
ali@31
   225
	g_free(dir);
ali@31
   226
    }
ali@31
   227
#else
ali@31
   228
    path=g_strdup("/var/lib/plover/reports");
ali@31
   229
#endif
ali@31
   230
    plover_purge_reports(path);
ali@31
   231
    return path;
ali@31
   232
}
ali@31
   233
ali@59
   234
char *plover_get_program(const char *argv0)
ali@59
   235
{
ali@59
   236
#ifdef WIN32
ali@59
   237
    char path[PATH_MAX];
ali@59
   238
    GetModuleFileName(NULL,path,sizeof(path));
ali@59
   239
    return strdup(path);
ali@59
   240
#else
ali@59
   241
    return strdup(argv0);
ali@59
   242
#endif
ali@59
   243
}
ali@59
   244
ali@3
   245
/*
ali@3
   246
 * Get the directory containing the program executable.
ali@3
   247
 */
ali@3
   248
ali@3
   249
char *plover_get_program_directory(const char *argv0)
ali@3
   250
{
ali@3
   251
    char *s;
ali@3
   252
#ifdef WIN32
ali@3
   253
    char path[PATH_MAX],*t;
ali@3
   254
    GetModuleFileName(NULL,path,sizeof(path));
ali@3
   255
    s=strrchr(path,'/');
ali@3
   256
    if (s)
ali@3
   257
    {
ali@3
   258
	t=strrchr(s,'\\');
ali@3
   259
	if (t)
ali@3
   260
	    s=t;
ali@3
   261
    }
ali@3
   262
    else
ali@3
   263
	s=strrchr(path,'\\');
ali@3
   264
    if (s)
ali@3
   265
	*s='\0';
ali@3
   266
    return strdup(path);
ali@3
   267
#else
ali@3
   268
    s=argv0?strrchr(argv0,'/'):NULL;
ali@3
   269
    if (s)
ali@3
   270
	return strndup(argv0,s-argv0);
ali@3
   271
    else
ali@3
   272
	return strdup(".");
ali@3
   273
#endif
ali@3
   274
}
ali@24
   275
ali@24
   276
G_DEFINE_QUARK(plover-razor-error-quark,plover_razor_error)
ali@24
   277
G_DEFINE_QUARK(plover-mswin-error-quark,plover_mswin_error)
ali@24
   278
G_DEFINE_QUARK(plover-posix-error-quark,plover_posix_error)
ali@24
   279
G_DEFINE_QUARK(plover-zlib-error-quark,plover_zlib_error)
ali@24
   280
ali@24
   281
void plover_propagate_razor_error_dup(GError **dest,struct razor_error *src)
ali@24
   282
{
ali@24
   283
    GQuark domain;
ali@24
   284
    int code;
ali@24
   285
    if (dest)
ali@24
   286
    {
ali@24
   287
	code=razor_error_get_code(src);
ali@24
   288
	switch(razor_error_get_domain(src))
ali@24
   289
	{
ali@24
   290
	    case RAZOR_GENERAL_ERROR:
ali@24
   291
		domain=PLOVER_RAZOR_ERROR;
ali@24
   292
		break;
ali@24
   293
	    case RAZOR_POSIX_ERROR:
ali@24
   294
		domain=PLOVER_POSIX_ERROR;
ali@24
   295
		break;
ali@24
   296
	    case RAZOR_MSWIN_ERROR:
ali@24
   297
		domain=PLOVER_MSWIN_ERROR;
ali@24
   298
		break;
ali@24
   299
	    case RAZOR_ZLIB_ERROR:
ali@24
   300
		domain=PLOVER_ZLIB_ERROR;
ali@24
   301
		break;
ali@24
   302
	    case PLOVER_GENERAL_ERROR:
ali@24
   303
		if (code==PLOVER_GENERAL_ERROR_CANCELLED)
ali@24
   304
		{
ali@24
   305
		    domain=G_IO_ERROR;
ali@24
   306
		    code=G_IO_ERROR_CANCELLED;
ali@24
   307
		    break;
ali@24
   308
		}
ali@24
   309
		/* else fall though */
ali@24
   310
	    default:
ali@24
   311
		domain=PLOVER_RAZOR_ERROR;
ali@24
   312
		code=RAZOR_GENERAL_ERROR_FAILED;
ali@24
   313
	}
ali@24
   314
	*dest=g_error_new_literal(domain,code,razor_error_get_msg(src));
ali@24
   315
    }
ali@24
   316
}
ali@24
   317
ali@24
   318
void plover_propagate_razor_error(GError **dest,struct razor_error *src)
ali@24
   319
{
ali@24
   320
    plover_propagate_razor_error_dup(dest,src);
ali@24
   321
    razor_error_free(src);
ali@24
   322
}
ali@24
   323
ali@24
   324
void plover_propagate_g_error(struct razor_error **dest,GError *src)
ali@24
   325
{
ali@24
   326
    int domain,code;
ali@24
   327
    if (dest)
ali@24
   328
    {
ali@24
   329
	code=src->code;
ali@24
   330
	if (src->domain==PLOVER_RAZOR_ERROR)
ali@24
   331
	    domain=RAZOR_GENERAL_ERROR;
ali@24
   332
	else if (src->domain==PLOVER_POSIX_ERROR)
ali@24
   333
	    domain=RAZOR_POSIX_ERROR;
ali@24
   334
	else if (src->domain==PLOVER_MSWIN_ERROR)
ali@24
   335
	    domain=RAZOR_MSWIN_ERROR;
ali@24
   336
	else if (src->domain==PLOVER_ZLIB_ERROR)
ali@24
   337
	    domain=RAZOR_ZLIB_ERROR;
ali@24
   338
	else if (src->domain==G_IO_ERROR && code==G_IO_ERROR_CANCELLED)
ali@24
   339
	{
ali@24
   340
	    domain=PLOVER_GENERAL_ERROR;
ali@24
   341
	    code=PLOVER_GENERAL_ERROR_CANCELLED;
ali@24
   342
	}
ali@24
   343
	else
ali@24
   344
	{
ali@24
   345
	    domain=RAZOR_GENERAL_ERROR;
ali@24
   346
	    code=RAZOR_GENERAL_ERROR_FAILED;
ali@24
   347
	}
ali@24
   348
	*dest=razor_error_new_str(domain,code,NULL,src->message);
ali@24
   349
    }
ali@24
   350
    g_error_free(src);
ali@24
   351
}