1 /* AbiSource Application Framework
2 * Copyright (C) 1998-2000 AbiSource, Inc.
3 * Copyright (C) 2004 Hubert Figuiere
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program 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, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA.
19 */
20
21
22 #include <windows.h>
23 #include <winreg.h>
24
25 #include "xap_Win32AppImpl.h"
26 #include "ut_string_class.h"
27 #include "ut_path.h"
28 #include "xap_Frame.h"
29 #include "xap_App.h"
30 #include "xap_Win32FrameImpl.h"
31
32 #include "ut_Win32LocaleString.h"
33
openURL(const char * szURL)34 bool XAP_Win32AppImpl::openURL(const char * szURL)
35 {
36 // NOTE: could get finer control over browser window via DDE
37 // NOTE: may need to fallback to WinExec for old NSCP versions
38
39 UT_String sURL = szURL;
40
41 // If this is a file:// URL, strip off file:// and make it backslashed
42 if (sURL.substr(0, 7) == "file://")
43 {
44 sURL = sURL.substr(7, sURL.size() - 7);
45
46 // View as WebPage likes to throw in an extra /\ just for fun, strip it off
47 if (sURL.substr(0, 2) == "/\\")
48 sURL = sURL.substr(2, sURL.size() - 2);
49
50 if (sURL.substr(0, 1) == "/")
51 sURL = sURL.substr(1, sURL.size() - 1);
52
53 // Convert all forwardslashes to backslashes
54 for (unsigned int i=0; i<sURL.length();i++)
55 if (sURL[i]=='/')
56 sURL[i]='\\';
57
58 // Convert from longpath to 8.3 shortpath, in case of spaces in the path
59 char* longpath = NULL;
60 char* shortpath = NULL;
61 longpath = new char[PATH_MAX];
62 shortpath = new char[PATH_MAX];
63 strcpy(longpath, sURL.c_str());
64 DWORD retval = GetShortPathName(longpath, shortpath, PATH_MAX);
65 if((retval == 0) || (retval > PATH_MAX))
66 {
67 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
68 DELETEP(longpath);
69 DELETEP(shortpath);
70 return false;
71 }
72 sURL = shortpath;
73 DELETEP(longpath);
74 DELETEP(shortpath);
75 }
76
77 // Query the registry for the default browser so we can directly invoke it
78 UT_String sBrowser;
79 HKEY hKey;
80 unsigned long lType;
81 DWORD dwSize;
82 LPWSTR szValue = NULL;
83 UT_Win32LocaleString str,str2;
84 UT_UTF8String utf8;
85
86 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
87 {
88 if(RegQueryValueExW(hKey, NULL, NULL, &lType, NULL, &dwSize) == ERROR_SUCCESS)
89 {
90 szValue = new WCHAR[dwSize + 1];
91 RegQueryValueExW(hKey, NULL, NULL, &lType, (LPBYTE) szValue, &dwSize);
92 str.fromLocale(szValue);
93 utf8=str.utf8_str();
94 sBrowser = utf8.utf8_str();
95 DELETEP(szValue);
96 }
97 RegCloseKey(hKey);
98 }
99
100 /* Now that we have sBrowser from the registry, we need to parse it out.
101 * If the first character is a double-quote, everything up to and including
102 * the next double-quote is the sBrowser command. Everything after the
103 * double-quote is appended to the parameters.
104 * If the first character is NOT a double-quote, we assume
105 * everything up to the first whitespace is the command and anything after
106 * is appended to the parameters.
107 */
108
109 int iDelimiter;
110 if (sBrowser.substr(0, 1) == "\"")
111 iDelimiter = UT_String_findCh(sBrowser.substr(1, sBrowser.length()-1), '"')+2;
112 else
113 iDelimiter = UT_String_findCh(sBrowser.substr(0, sBrowser.length()), ' ');
114
115 // Store params into a separate UT_String before we butcher sBrowser
116 UT_String sParams = sBrowser.substr(iDelimiter+1, sBrowser.length()-iDelimiter+1);
117 // Cut params off of sBrowser so all we're left with is the broweser path & executable
118 sBrowser = sBrowser.substr(0, iDelimiter);
119
120 // Check for a %1 passed in from the registry. If we find it,
121 // substitute our URL for %1. Otherwise, just append sURL to params.
122 const char *pdest = strstr(sParams.c_str(), "%1");
123 if (pdest != NULL)
124 {
125 int i = pdest - sParams.c_str() + 1;
126 sParams = sParams.substr(0, i-1) + sURL + sParams.substr(i+1, sParams.length()-i+1);
127 }
128 else
129 {
130 sParams = sParams + " " + sURL;
131 }
132
133 XAP_Frame * pFrame = XAP_App::getApp()->getLastFocussedFrame();
134 UT_return_val_if_fail(pFrame, false);
135 XAP_Win32FrameImpl *pFImp = (XAP_Win32FrameImpl *) pFrame->getFrameImpl();
136 UT_return_val_if_fail(pFImp, false);
137
138 str.fromUTF8(sBrowser.c_str());
139 str2.fromUTF8(sParams.c_str());
140
141 intptr_t res = (intptr_t) ShellExecuteW(pFImp->getTopLevelWindow() /*(HWND)*/,
142 L"open", str.c_str(), str2.c_str(), NULL, SW_SHOW );
143
144 // TODO: localized error messages
145 // added more specific error messages as documented in http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes.asp
146 if (res <= 32)
147 {
148 UT_String errMsg;
149 switch (res)
150 {
151 case ERROR_FILE_NOT_FOUND:
152 {
153 errMsg = "Error (";
154 errMsg += UT_String_sprintf("%d", res);
155 errMsg += ") displaying URL: The system cannot find the file specified.\n";
156 errMsg += " [ "; errMsg += sURL; errMsg += " ] ";
157 }
158 break;
159
160 case ERROR_PATH_NOT_FOUND:
161 {
162 errMsg = "Error (";
163 errMsg += UT_String_sprintf("%d", res);
164 errMsg += ") displaying URL: The system cannot find the path specified.\n";
165 errMsg += " [ "; errMsg += sURL; errMsg += " ] ";
166 }
167 break;
168
169 case SE_ERR_ACCESSDENIED:
170 {
171 errMsg = "Error (";
172 errMsg += UT_String_sprintf("%d", res);
173 errMsg += ") displaying URL: Access is denied.\n";
174 errMsg += " [ "; errMsg += sURL; errMsg += " ] ";
175 }
176 break;
177
178 default:
179 {
180 errMsg = "Error (";
181 errMsg += UT_String_sprintf("%d", res);
182 errMsg += ") displaying URL: \n";
183 errMsg += " [ "; errMsg += sURL; errMsg += " ] ";
184 }
185 break;
186 } /* switch (res) */
187 if (errMsg[0]) {
188 str.fromUTF8(errMsg.c_str());
189 MessageBoxW(pFImp->getTopLevelWindow(),str.c_str(),
190 L"Error displaying URL", MB_OK|MB_ICONEXCLAMATION);
191 }
192 } /* if (res <= 32) */
193
194 return (res>32);
195 }
196
197