|
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 |
}
|