/* * Copyright 2011 Vincent Sanders * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf 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 General Public License * along with this program. If not, see . */ #include "utils/config.h" #include #include #include #include #include #include #include "utils/utils.h" #include "utils/log.h" #include "utils/messages.h" #include "utils/filepath.h" #include "utils/file.h" #include "utils/nsurl.h" #include "utils/nsoption.h" #include "netsurf/url_db.h" #include "netsurf/cookie_db.h" #include "netsurf/browser_window.h" #include "netsurf/fetch.h" #include "netsurf/misc.h" #include "netsurf/netsurf.h" #include "windows/findfile.h" #include "windows/file.h" #include "windows/drawable.h" #include "windows/download.h" #include "windows/localhistory.h" #include "windows/window.h" #include "windows/schedule.h" #include "windows/font.h" #include "windows/filetype.h" #include "windows/pointers.h" #include "windows/bitmap.h" #include "windows/gui.h" static char **respaths; /** resource search path vector. */ char *nsw32_config_home; /* exported global defined in windows/gui.h */ /** * Get the path to the config directory. * * This ought to use SHGetKnownFolderPath(FOLDERID_RoamingAppData) and * PathCcpAppend() but uses depricated API because that is what mingw * supports. * * @param config_home_out Path to configuration directory. * @return NSERROR_OK on sucess and \a config_home_out updated else error code. */ static nserror get_config_home(char **config_home_out) { TCHAR adPath[MAX_PATH]; /* appdata path */ char nsdir[] = "NetSurf"; HRESULT hres; hres = SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, adPath); if (hres != S_OK) { return NSERROR_INVALID; } if (PathAppend(adPath, nsdir) == false) { return NSERROR_NOT_FOUND; } /* ensure netsurf directory exists */ if (CreateDirectory(adPath, NULL) == 0) { DWORD dw; dw = GetLastError(); if (dw != ERROR_ALREADY_EXISTS) { return NSERROR_NOT_DIRECTORY; } } *config_home_out = strdup(adPath); LOG("using config path \"%s\"", *config_home_out); return NSERROR_OK; } /** * Cause an abnormal program termination. * * \note This never returns and is intended to terminate without any cleanup. * * \param error The message to display to the user. */ static void die(const char *error) { exit(1); } static nsurl *gui_get_resource_url(const char *path) { char buf[PATH_MAX]; nsurl *url = NULL; netsurf_path_to_nsurl(filepath_sfind(respaths, buf, path), &url); return url; } /** * Ensures output logging stream is available */ static bool nslog_ensure(FILE *fptr) { /* mwindows compile flag normally invalidates standard io unless * already redirected */ if (_get_osfhandle(fileno(fptr)) == -1) { AllocConsole(); freopen("CONOUT$", "w", fptr); } return true; } /** * Set option defaults for windows frontend * * @param defaults The option table to update. * @return error status. */ static nserror set_defaults(struct nsoption_s *defaults) { /* Set defaults for absent option strings */ /* locate CA bundle and set as default, cannot rely on curl * compiled in default on windows. */ DWORD res_len; DWORD buf_tchar_size = PATH_MAX + 1; DWORD buf_bytes_size = sizeof(TCHAR) * buf_tchar_size; char *ptr = NULL; char *buf; char *fname; HRESULT hres; char dldir[] = "Downloads"; buf = malloc(buf_bytes_size); if (buf== NULL) { return NSERROR_NOMEM; } buf[0] = '\0'; /* locate certificate bundle */ res_len = SearchPathA(NULL, "ca-bundle.crt", NULL, buf_tchar_size, buf, &ptr); if (res_len > 0) { nsoption_setnull_charp(ca_bundle, strdup(buf)); } /* download directory default * * unfortunately SHGetKnownFolderPath(FOLDERID_Downloads) is * not available so use the obsolete method of user prodile * with downloads suffixed */ buf[0] = '\0'; hres = SHGetFolderPath(NULL, CSIDL_PROFILE | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, buf); if (hres == S_OK) { if (PathAppend(buf, dldir)) { nsoption_setnull_charp(downloads_directory, strdup(buf)); } } free(buf); /* ensure homepage option has a default */ nsoption_setnull_charp(homepage_url, strdup(NETSURF_HOMEPAGE)); /* cookie file default */ fname = NULL; netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "Cookies"); if (fname != NULL) { nsoption_setnull_charp(cookie_file, fname); } /* cookie jar default */ fname = NULL; netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "Cookies"); if (fname != NULL) { nsoption_setnull_charp(cookie_jar, fname); } /* url database default */ fname = NULL; netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "URLs"); if (fname != NULL) { nsoption_setnull_charp(url_file, fname); } /* bookmark database default */ fname = NULL; netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "Hotlist"); if (fname != NULL) { nsoption_setnull_charp(hotlist_path, fname); } return NSERROR_OK; } /** * Initialise user options location and contents */ static nserror nsw32_option_init(int *pargc, char** argv) { nserror ret; char *choices = NULL; /* user options setup */ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); if (ret != NSERROR_OK) { return ret; } /* Attempt to load the user choices */ ret = netsurf_mkpath(&choices, NULL, 2, nsw32_config_home, "Choices"); if (ret == NSERROR_OK) { nsoption_read(choices, nsoptions); free(choices); } /* overide loaded options with those from commandline */ nsoption_commandline(pargc, argv, nsoptions); return NSERROR_OK; } static struct gui_misc_table win32_misc_table = { .schedule = win32_schedule, .warning = win32_warning, }; /** * Entry point from windows **/ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd) { char **argv = NULL; int argc = 0, argctemp = 0; size_t len; LPWSTR *argvw; char *messages; nserror ret; const char *addr; nsurl *url; struct netsurf_table win32_table = { .misc = &win32_misc_table, .window = win32_window_table, .clipboard = win32_clipboard_table, .download = win32_download_table, .fetch = win32_fetch_table, .file = win32_file_table, .utf8 = win32_utf8_table, .bitmap = win32_bitmap_table, .layout = win32_layout_table, }; win32_fetch_table->get_resource_url = gui_get_resource_url; ret = netsurf_register(&win32_table); if (ret != NSERROR_OK) { die("NetSurf operation table registration failed"); } /* Save the application-instance handle. */ hinst = hInstance; setbuf(stderr, NULL); /* Construct a unix style argc/argv */ if (SLEN(lpcli) > 0) { argvw = CommandLineToArgvW(GetCommandLineW(), &argc); } argv = malloc(sizeof(char *) * argc); while (argctemp < argc) { len = wcstombs(NULL, argvw[argctemp], 0) + 1; if (len > 0) { argv[argctemp] = malloc(len); } if (argv[argctemp] != NULL) { wcstombs(argv[argctemp], argvw[argctemp], len); /* alter windows-style forward slash flags to * hyphen flags. */ if (argv[argctemp][0] == '/') argv[argctemp][0] = '-'; } argctemp++; } /* initialise logging - not fatal if it fails but not much we * can do about it */ nslog_init(nslog_ensure, &argc, argv); /* Locate the correct user configuration directory path */ ret = get_config_home(&nsw32_config_home); if (ret != NSERROR_OK) { LOG("Unable to locate a configuration directory."); nsw32_config_home = NULL; } /* Initialise user options */ ret = nsw32_option_init(&argc, argv); if (ret != NSERROR_OK) { LOG("Options failed to initialise (%s)\n", messages_get_errorcode(ret)); return 1; } respaths = nsws_init_resource("${APPDATA}\\NetSurf:${HOME}\\.netsurf:${NETSURFRES}:${PROGRAMFILES}\\NetSurf\\NetSurf\\:"NETSURF_WINDOWS_RESPATH); /* message init */ messages = filepath_find(respaths, "messages"); messages_add_from_file(messages); free(messages); /* common initialisation */ ret = netsurf_init(NULL); if (ret != NSERROR_OK) { LOG("NetSurf failed to initialise"); return 1; } urldb_load(nsoption_charp(url_file)); urldb_load_cookies(nsoption_charp(cookie_file)); ret = nsws_create_main_class(hInstance); ret = nsws_create_drawable_class(hInstance); ret = nsws_create_localhistory_class(hInstance); nsoption_set_bool(target_blank, false); nsws_window_init_pointers(hInstance); /* If there is a url specified on the command line use it */ if (argc > 1) { addr = argv[1]; } else if (nsoption_charp(homepage_url) != NULL) { addr = nsoption_charp(homepage_url); } else { addr = NETSURF_HOMEPAGE; } LOG("calling browser_window_create"); ret = nsurl_create(addr, &url); if (ret == NSERROR_OK) { ret = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL); nsurl_unref(url); } if (ret != NSERROR_OK) { win32_warning(messages_get_errorcode(ret), 0); } else { win32_run(); } urldb_save_cookies(nsoption_charp(cookie_jar)); urldb_save(nsoption_charp(url_file)); netsurf_exit(); /* finalise options */ nsoption_finalise(nsoptions, nsoptions_default); return 0; }