NetSurf
main.c
Go to the documentation of this file.
1/*
2 * Copyright 2011 Vincent Sanders <vince@simtec.co.uk>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "utils/config.h"
20
21#include <limits.h>
22#include <stdbool.h>
23#include <windows.h>
24#include <shlobj.h>
25#include <shlwapi.h>
26#include <io.h>
27
28#include "utils/utils.h"
29#include "utils/log.h"
30#include "utils/messages.h"
31#include "utils/filepath.h"
32#include "utils/file.h"
33#include "utils/nsurl.h"
34#include "utils/nsoption.h"
35#include "netsurf/url_db.h"
36#include "netsurf/cookie_db.h"
37#include "netsurf/browser.h"
39#include "netsurf/fetch.h"
40#include "netsurf/misc.h"
41#include "netsurf/netsurf.h"
42#include "desktop/hotlist.h"
43
44#include "windows/findfile.h"
45#include "windows/file.h"
46#include "windows/cookies.h"
47#include "windows/drawable.h"
48#include "windows/corewindow.h"
49#include "windows/download.h"
51#include "windows/window.h"
52#include "windows/schedule.h"
53#include "windows/font.h"
54#include "windows/fetch.h"
55#include "windows/pointers.h"
56#include "windows/bitmap.h"
57#include "windows/clipboard.h"
58#include "windows/gui.h"
59
60
61/**
62 * Obtain the DPI of the display.
63 *
64 * \return The DPI of the device the window is displayed on.
65 */
66static int get_screen_dpi(void)
67{
68 HDC screendc = GetDC(0);
69 int dpi = GetDeviceCaps(screendc, LOGPIXELSY);
70 ReleaseDC(0, screendc);
71
72 if (dpi <= 10) {
73 dpi = 96; /* 96DPI is the default */
74 }
75
76 NSLOG(netsurf, INFO, "FIX DPI %d", dpi);
77
78 return dpi;
79}
80
81/**
82 * Get the path to the config directory.
83 *
84 * This ought to use SHGetKnownFolderPath(FOLDERID_RoamingAppData) and
85 * PathCcpAppend() but uses depricated API because that is what mingw
86 * supports.
87 *
88 * @param config_home_out Path to configuration directory.
89 * @return NSERROR_OK on sucess and \a config_home_out updated else error code.
90 */
91static nserror get_config_home(char **config_home_out)
92{
93 TCHAR adPath[MAX_PATH]; /* appdata path */
94 char nsdir[] = "NetSurf";
95 HRESULT hres;
96
97 hres = SHGetFolderPath(NULL,
98 CSIDL_APPDATA | CSIDL_FLAG_CREATE,
99 NULL,
100 SHGFP_TYPE_CURRENT,
101 adPath);
102 if (hres != S_OK) {
103 return NSERROR_INVALID;
104 }
105
106 if (PathAppend(adPath, nsdir) == false) {
107 return NSERROR_NOT_FOUND;
108 }
109
110 /* ensure netsurf directory exists */
111 if (CreateDirectory(adPath, NULL) == 0) {
112 DWORD dw;
113 dw = GetLastError();
114 if (dw != ERROR_ALREADY_EXISTS) {
116 }
117 }
118
119 *config_home_out = strdup(adPath);
120
121 NSLOG(netsurf, INFO, "using config path \"%s\"", *config_home_out);
122
123 return NSERROR_OK;
124}
125
126
127/**
128 * Cause an abnormal program termination.
129 *
130 * \note This never returns and is intended to terminate without any cleanup.
131 *
132 * \param error The message to display to the user.
133 */
134static void die(const char *error)
135{
136 exit(1);
137}
138
139
140
141/**
142 * Ensures output logging stream is available
143 */
144static bool nslog_ensure(FILE *fptr)
145{
146 /* mwindows compile flag normally invalidates standard io unless
147 * already redirected
148 */
149 if (_get_osfhandle(fileno(fptr)) == -1) {
150 AllocConsole();
151 freopen("CONOUT$", "w", fptr);
152 }
153 return true;
154}
155
156/**
157 * Set option defaults for windows frontend
158 *
159 * @param defaults The option table to update.
160 * @return error status.
161 */
163{
164 /* Set defaults for absent option strings */
165
166 /* locate CA bundle and set as default, cannot rely on curl
167 * compiled in default on windows.
168 */
169 DWORD res_len;
170 DWORD buf_tchar_size = PATH_MAX + 1;
171 DWORD buf_bytes_size = sizeof(TCHAR) * buf_tchar_size;
172 char *ptr = NULL;
173 char *buf;
174 char *fname;
175 HRESULT hres;
176 char dldir[] = "Downloads";
177
178 buf = malloc(buf_bytes_size);
179 if (buf== NULL) {
180 return NSERROR_NOMEM;
181 }
182 buf[0] = '\0';
183
184 /* locate certificate bundle */
185 res_len = SearchPathA(NULL,
186 "ca-bundle.crt",
187 NULL,
188 buf_tchar_size,
189 buf,
190 &ptr);
191 if (res_len > 0) {
192 nsoption_setnull_charp(ca_bundle, strdup(buf));
193 } else {
194 ptr = filepath_sfind(G_resource_pathv, buf, "ca-bundle.crt");
195 if (ptr != NULL) {
196 nsoption_setnull_charp(ca_bundle, strdup(buf));
197 }
198 }
199
200
201 /* download directory default
202 *
203 * unfortunately SHGetKnownFolderPath(FOLDERID_Downloads) is
204 * not available so use the obsolete method of user prodile
205 * with downloads suffixed
206 */
207 buf[0] = '\0';
208
209 hres = SHGetFolderPath(NULL,
210 CSIDL_PROFILE | CSIDL_FLAG_CREATE,
211 NULL,
212 SHGFP_TYPE_CURRENT,
213 buf);
214 if (hres == S_OK) {
215 if (PathAppend(buf, dldir)) {
216 nsoption_setnull_charp(downloads_directory,
217 strdup(buf));
218
219 }
220 }
221
222 free(buf);
223
224 /* ensure homepage option has a default */
225 nsoption_setnull_charp(homepage_url, strdup(NETSURF_HOMEPAGE));
226
227 /* cookie file default */
228 fname = NULL;
229 netsurf_mkpath(&fname, NULL, 2, G_config_path, "Cookies");
230 if (fname != NULL) {
231 nsoption_setnull_charp(cookie_file, fname);
232 }
233
234 /* cookie jar default */
235 fname = NULL;
236 netsurf_mkpath(&fname, NULL, 2, G_config_path, "Cookies");
237 if (fname != NULL) {
238 nsoption_setnull_charp(cookie_jar, fname);
239 }
240
241 /* url database default */
242 fname = NULL;
243 netsurf_mkpath(&fname, NULL, 2, G_config_path, "URLs");
244 if (fname != NULL) {
245 nsoption_setnull_charp(url_file, fname);
246 }
247
248 /* bookmark database default */
249 fname = NULL;
250 netsurf_mkpath(&fname, NULL, 2, G_config_path, "Hotlist");
251 if (fname != NULL) {
252 nsoption_setnull_charp(hotlist_path, fname);
253 }
254
255 return NSERROR_OK;
256}
257
258
259/**
260 * Initialise user options location and contents
261 */
262static nserror
263nsw32_option_init(int *pargc, char** argv, char **respaths, char *config_path)
264{
265 nserror ret;
266 char *choices = NULL;
267
268 /* set the globals that will be used in the set_defaults() callback */
270 G_config_path = config_path;
271
272 /* user options setup */
274 if (ret != NSERROR_OK) {
275 return ret;
276 }
277
278 /* Attempt to load the user choices */
279 ret = netsurf_mkpath(&choices, NULL, 2, config_path, "Choices");
280 if (ret == NSERROR_OK) {
281 nsoption_read(choices, nsoptions);
282 free(choices);
283 }
284
285 /* overide loaded options with those from commandline */
286 nsoption_commandline(pargc, argv, nsoptions);
287
288 return NSERROR_OK;
289}
290
291/**
292 * Initialise messages
293 */
295{
296 char *messages;
297 nserror res;
298 const uint8_t *data;
299 size_t data_size;
300
301 res = nsw32_get_resource_data("messages", &data, &data_size);
302 if (res == NSERROR_OK) {
303 res = messages_add_from_inline(data, data_size);
304 } else {
305 /* Obtain path to messages */
306 messages = filepath_find(respaths, "messages");
307 if (messages == NULL) {
308 res = NSERROR_NOT_FOUND;
309 } else {
310 res = messages_add_from_file(messages);
311 free(messages);
312 }
313 }
314
315 return res;
316}
317
318
319/**
320 * Construct a unix style argc/argv
321 *
322 * \param argc_out number of commandline arguments
323 * \param argv_out string vector of command line arguments
324 * \return NSERROR_OK on success else error code
325 */
326static nserror win32_to_unix_commandline(int *argc_out, char ***argv_out)
327{
328 int argc = 0;
329 char **argv;
330 int cura;
331 LPWSTR *argvw;
332 size_t len;
333
334 argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
335 if (argvw == NULL) {
336 return NSERROR_INVALID;
337 }
338
339 argv = malloc(sizeof(char *) * argc);
340 if (argv == NULL) {
341 return NSERROR_NOMEM;
342 }
343
344 for (cura = 0; cura < argc; cura++) {
345
346 len = wcstombs(NULL, argvw[cura], 0) + 1;
347 if (len > 0) {
348 argv[cura] = malloc(len);
349 if (argv[cura] == NULL) {
350 free(argv);
351 return NSERROR_NOMEM;
352 }
353 } else {
354 free(argv);
355 return NSERROR_INVALID;
356 }
357
358 wcstombs(argv[cura], argvw[cura], len);
359 /* alter windows-style forward slash flags to hyphen flags. */
360 if (argv[cura][0] == '/') {
361 argv[cura][0] = '-';
362 }
363 }
364
365 *argc_out = argc;
366 *argv_out = argv;
367
368 return NSERROR_OK;
369}
370
371
374 .present_cookies = nsw32_cookies_present,
375};
376
377/**
378 * Entry point from windows
379 **/
380int WINAPI
381WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
382{
383 int argc;
384 char **argv;
385 char **respaths;
386 char *nsw32_config_home = NULL;
387 nserror ret;
388 const char *addr;
389 nsurl *url;
390 struct netsurf_table win32_table = {
392 .window = win32_window_table,
393 .corewindow = win32_core_window_table,
394 .clipboard = win32_clipboard_table,
395 .download = win32_download_table,
396 .fetch = win32_fetch_table,
397 .file = win32_file_table,
398 .utf8 = win32_utf8_table,
399 .bitmap = win32_bitmap_table,
400 .layout = win32_layout_table,
401 };
402
403 ret = netsurf_register(&win32_table);
404 if (ret != NSERROR_OK) {
405 die("NetSurf operation table registration failed");
406 }
407
408 /* Save the application-instance handle. */
409 hinst = hInstance;
410
411 setbuf(stderr, NULL);
412
413 ret = win32_to_unix_commandline(&argc, &argv);
414 if (ret != NSERROR_OK) {
415 /* no log as logging requires this for initialisation */
416 return 1;
417 }
418
419 /* initialise logging - not fatal if it fails but not much we
420 * can do about it
421 */
422 nslog_init(nslog_ensure, &argc, argv);
423
424 /* build resource path string vector */
425 respaths = nsws_init_resource("${APPDATA}\\NetSurf:${PROGRAMFILES}\\NetSurf\\NetSurf\\:"NETSURF_WINDOWS_RESPATH);
426
427 /* Locate the correct user configuration directory path */
428 ret = get_config_home(&nsw32_config_home);
429 if (ret != NSERROR_OK) {
430 NSLOG(netsurf, INFO,
431 "Unable to locate a configuration directory.");
432 }
433
434 /* Initialise user options */
435 ret = nsw32_option_init(&argc, argv, respaths, nsw32_config_home);
436 if (ret != NSERROR_OK) {
437 NSLOG(netsurf, ERROR, "Options failed to initialise (%s)\n",
439 return 1;
440 }
441
442 /* Initialise translated messages */
444 if (ret != NSERROR_OK) {
445 fprintf(stderr, "Unable to load translated messages (%s)\n",
447 NSLOG(netsurf, INFO, "Unable to load translated messages");
448 /** \todo decide if message load faliure should be fatal */
449 }
450
451 /* common initialisation */
452 ret = netsurf_init(NULL);
453 if (ret != NSERROR_OK) {
454 NSLOG(netsurf, INFO, "NetSurf failed to initialise");
455 return 1;
456 }
457
459
460 urldb_load(nsoption_charp(url_file));
462 hotlist_init(nsoption_charp(hotlist_path),
463 nsoption_charp(hotlist_path));
464
465 ret = nsws_create_main_class(hInstance);
466 ret = nsws_create_drawable_class(hInstance);
467 ret = nsw32_create_corewindow_class(hInstance);
468
469 nsoption_set_bool(target_blank, false);
470
471 nsws_window_init_pointers(hInstance);
472
473 /* If there is a url specified on the command line use it */
474 if (argc > 1) {
475 addr = argv[1];
476 } else if (nsoption_charp(homepage_url) != NULL) {
477 addr = nsoption_charp(homepage_url);
478 } else {
479 addr = NETSURF_HOMEPAGE;
480 }
481
482 NSLOG(netsurf, INFO, "calling browser_window_create");
483
484 ret = nsurl_create(addr, &url);
485 if (ret == NSERROR_OK) {
487 url,
488 NULL,
489 NULL,
490 NULL);
491 nsurl_unref(url);
492
493 }
494 if (ret != NSERROR_OK) {
496 } else {
497 win32_run();
498 }
499
501 urldb_save(nsoption_charp(url_file));
502
503 netsurf_exit();
504
505 /* finalise options */
507
508 /* finalise logging */
510
511 return 0;
512}
#define PATH_MAX
Definition: gui.h:31
Browser window creation and manipulation interface.
nserror browser_window_create(enum browser_window_create_flags flags, struct nsurl *url, struct nsurl *referrer, struct browser_window *existing, struct browser_window **bw)
Create and open a new root browser window with the given page.
@ BW_CREATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
Unified cookie database public interface.
void urldb_save_cookies(const char *filename)
Save persistent cookies to file.
Definition: urldb.c:4448
void urldb_load_cookies(const char *filename)
Load a cookie file into the database.
Definition: urldb.c:4281
nserror hotlist_init(const char *load_path, const char *save_path)
Initialise the hotlist.
Definition: hotlist.c:1290
nserror nsws_create_drawable_class(HINSTANCE hinstance)
Create the drawable window class.
Definition: drawable.c:707
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_NOT_DIRECTORY
Missing directory.
Definition: errors.h:35
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
char * filepath_sfind(char **respathv, char *filepath, const char *filename)
Searches an array of resource paths for a file.
Definition: filepath.c:109
char * filepath_find(char **respathv, const char *filename)
Searches an array of resource paths for a file.
Definition: filepath.c:129
Utility routines to obtain paths to file resources.
struct gui_bitmap_table * win32_bitmap_table
Definition: bitmap.c:338
struct gui_download_table * win32_download_table
Definition: download.c:353
nserror nsw32_get_resource_data(const char *path, const uint8_t **data_out, size_t *data_len_out)
Translate resource to win32 resource data.
Definition: fetch.c:90
struct gui_fetch_table * win32_fetch_table
win32 API fetch operation table
Definition: fetch.c:133
struct gui_file_table * win32_file_table
Definition: file.c:305
Windows file operation table interface.
struct gui_utf8_table * win32_utf8_table
Definition: font.c:360
struct gui_layout_table * win32_layout_table
Definition: font.c:352
The interface to the win32 font and utf8 handling.
Interface to win32 local history manager using nsw32 core window.
Browser interfaces.
nserror browser_set_dpi(int dpi)
Set the DPI of the browser.
Definition: browser.c:32
Interface to platform-specific fetcher operations.
Interface to platform-specific miscellaneous browser operation table.
nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
Initialise the logging system.
Definition: log.c:190
void nslog_finalise(void)
Shut down the logging system.
Definition: log.c:299
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
nserror messages_add_from_inline(const uint8_t *data, size_t size)
Read keys and values from inline message data into the standard Messages hash.
Definition: messages.c:190
nserror messages_add_from_file(const char *path)
Read keys and values from messages file into the standard Messages hash.
Definition: messages.c:177
const char * messages_get_errorcode(nserror code)
lookup of a message by errorcode from the standard Messages hash.
Definition: messages.c:248
Localised message support (interface).
char ** respaths
resource search path vector
Definition: main.c:59
NetSurf core interface registration, construction and destruction.
void netsurf_exit(void)
Finalise NetSurf core.
Definition: netsurf.c:232
nserror netsurf_init(const char *store_path)
Initialise netsurf core.
Definition: netsurf.c:107
nserror netsurf_register(struct netsurf_table *table)
Register operation table.
Definition: gui_factory.c:777
NetSurf URL handling (interface).
nserror nsurl_create(const char *const url_s, nsurl **url)
Create a NetSurf URL object from a URL string.
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
void nsws_window_init_pointers(HINSTANCE hinstance)
initialise the list of mouse cursors
Definition: pointers.c:58
Windows mouse cursor interface.
Graphical user interface browser misc function table.
Definition: misc.h:39
nserror(* schedule)(int t, void(*callback)(void *p), void *p)
Schedule a callback.
Definition: misc.h:58
NetSurf operation function table.
Definition: gui_table.h:48
struct gui_misc_table * misc
Browser table.
Definition: gui_table.h:57
Unified URL information database public interface.
nserror urldb_save(const char *filename)
Export the current database to file.
Definition: urldb.c:3094
nserror urldb_load(const char *filename)
Import an URL database from file, replacing any existing database.
Definition: urldb.c:2876
nserror netsurf_mkpath(char **str, size_t *size, size_t nelm,...)
Generate a path from one or more component elemnts.
Definition: file.c:288
Default operations table for files.
struct nsoption_s * nsoptions_default
global default option table.
Definition: nsoption.c:46
static struct nsoption_s defaults[]
The table of compiled in default options.
Definition: nsoption.c:64
nserror nsoption_read(const char *path, struct nsoption_s *opts)
Read choices file and set them in the passed table.
Definition: nsoption.c:696
struct nsoption_s * nsoptions
global active option table.
Definition: nsoption.c:45
nserror nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts)
Process commandline and set options approriately.
Definition: nsoption.c:856
nserror nsoption_init(nsoption_set_default_t *set_defaults, struct nsoption_s **popts, struct nsoption_s **pdefs)
Initialise option system.
Definition: nsoption.c:608
nserror nsoption_finalise(struct nsoption_s *opts, struct nsoption_s *defs)
Finalise option system.
Definition: nsoption.c:663
Option reading and saving interface.
#define nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:331
#define nsoption_setnull_charp(OPTION, VALUE)
set string option in default table if currently unset
Definition: nsoption.h:376
#define nsoption_set_bool(OPTION, VALUE)
set a boolean option in the default table
Definition: nsoption.h:344
Interface to a number of general purpose functionality.
struct gui_clipboard_table * win32_clipboard_table
The clipboard operation function table for win32.
Definition: clipboard.c:131
nserror nsw32_cookies_present(const char *search_term)
make the cookie window visible.
Definition: cookies.c:173
Interface to win32 cookie viewing using nsw32 core windows.
nserror nsw32_create_corewindow_class(HINSTANCE hInstance)
Definition: corewindow.c:584
struct core_window_table * win32_core_window_table
Definition: corewindow.c:515
char ** nsws_init_resource(const char *resource_path)
Create an array of valid paths to search for resources.
Definition: findfile.c:44
char ** G_resource_pathv
resource search path vector.
Definition: gui.c:48
char * G_config_path
path to where all user config files are held.
Definition: gui.c:51
nserror win32_warning(const char *warning, const char *detail)
Warn the user of an event.
Definition: gui.c:173
void win32_run(void)
Run the win32 message loop with scheduling.
Definition: gui.c:130
HINSTANCE hinst
win32 application instance handle.
Definition: gui.c:45
static bool nslog_ensure(FILE *fptr)
Ensures output logging stream is available.
Definition: main.c:144
static nserror set_defaults(struct nsoption_s *defaults)
Set option defaults for windows frontend.
Definition: main.c:162
static nserror nsw32_option_init(int *pargc, char **argv, char **respaths, char *config_path)
Initialise user options location and contents.
Definition: main.c:263
static void die(const char *error)
Cause an abnormal program termination.
Definition: main.c:134
static struct gui_misc_table win32_misc_table
Definition: main.c:372
static nserror win32_to_unix_commandline(int *argc_out, char ***argv_out)
Construct a unix style argc/argv.
Definition: main.c:326
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
Entry point from windows.
Definition: main.c:381
static nserror nsw32_messages_init(char **respaths)
Initialise messages.
Definition: main.c:294
static int get_screen_dpi(void)
Obtain the DPI of the display.
Definition: main.c:66
static nserror get_config_home(char **config_home_out)
Get the path to the config directory.
Definition: main.c:91
nserror win32_schedule(int ival, void(*callback)(void *p), void *p)
Schedule a callback.
Definition: schedule.c:99
struct gui_window_table * win32_window_table
The window operation function table for win32.
Definition: window.c:1921
nserror nsws_create_main_class(HINSTANCE hinstance)
Create the main browser window class.
Definition: window.c:2083