]> cygwin.com Git - cygwin-apps/setup.git/blob - localdir.cc
Restructure how we try keys in order for signature checking
[cygwin-apps/setup.git] / localdir.cc
1 /*
2 * Copyright (c) 2000, Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Andrej Borsenkow <Andrej.Borsenkow@mow.siemens.ru>
13 * based on work and suggestions of DJ Delorie
14 *
15 */
16
17 /* The purpose of this file is to ask the user where they want the
18 * locally downloaded package files to be cached
19 */
20
21 #include "localdir.h"
22
23 #include "LogSingleton.h"
24 #include "LogFile.h"
25 #include "win32.h"
26 #include "filemanip.h"
27
28 #include <shlobj.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32
33 #include "ini.h"
34 #include "dialog.h"
35 #include "resource.h"
36 #include "state.h"
37 #include "msg.h"
38 #include "mount.h"
39 #include "io_stream.h"
40 #include "mkdir.h"
41
42 #include "UserSettings.h"
43
44 #include "getopt++/StringOption.h"
45
46 #include "threebar.h"
47 extern ThreeBarProgressPage Progress;
48
49 static StringOption LocalDirOption ("", 'l', "local-package-dir", "Local package directory", false);
50
51 static ControlAdjuster::ControlInfo LocaldirControlsInfo[] = {
52 { IDC_LOCALDIR_GRP, CP_STRETCH, CP_TOP },
53 { IDC_LOCAL_DIR, CP_STRETCH, CP_TOP },
54 { IDC_LOCAL_DIR_BROWSE, CP_RIGHT, CP_TOP },
55 {0, CP_LEFT, CP_TOP}
56 };
57
58 LocalDirSetting::LocalDirSetting ()
59 {
60 const char *fg_ret;
61 if (std::string (LocalDirOption).size ())
62 local_dir = std::string (LocalDirOption);
63 else if ((fg_ret = UserSettings::instance().get ("last-cache")))
64 local_dir = std::string (fg_ret);
65 }
66
67 void
68 LocalDirSetting::save ()
69 {
70 UserSettings::instance().set ("last-cache", local_dir);
71 if (source == IDC_SOURCE_DOWNLOAD || !get_root_dir ().size())
72 {
73 const char *sep = isdirsep (local_dir[local_dir.size () - 1]) ? "" : "\\";
74 Logger ().clearFiles();
75 Logger ().setFile (LOG_BABBLE, local_dir + sep + "setup.log.full", false);
76 Logger ().setFile (0, local_dir + sep + "setup.log", true);
77 }
78 else
79 {
80 Logger ().clearFiles();
81 mkdir_p (1, cygpath ("/var/log").c_str (), 01777);
82 Logger ().setFile (LOG_BABBLE, cygpath ("/var/log/setup.log.full"),
83 false);
84 Logger ().setFile (0, cygpath ("/var/log/setup.log"), true);
85 }
86 }
87
88 static void
89 check_if_enable_next (HWND h)
90 {
91 EnableWindow (GetDlgItem (h, IDOK), local_dir.size() != 0);
92 }
93
94 static void
95 load_dialog (HWND h)
96 {
97 char descText[1000];
98 if (source != IDC_SOURCE_LOCALDIR)
99 {
100 LoadString (hinstance, IDS_LOCAL_DIR_DOWNLOAD, descText, sizeof (descText));
101 }
102 else
103 {
104 LoadString (hinstance, IDS_LOCAL_DIR_INSTALL, descText, sizeof (descText));
105 }
106 eset (h, IDC_LOCAL_DIR_DESC, descText);
107 eset (h, IDC_LOCAL_DIR, local_dir);
108 check_if_enable_next (h);
109 }
110
111 static void
112 save_dialog (HWND h)
113 {
114 local_dir = egetString (h, IDC_LOCAL_DIR);
115 }
116
117 // returns non-zero if refused or error, 0 if accepted and created ok.
118 static int
119 offer_to_create (HWND h, const char *dirname)
120 {
121 if (!dirname || !*dirname)
122 return -1;
123
124 if (!unattended_mode)
125 {
126 char msgText[MAX_PATH + 100];
127 char fmtString[100];
128 DWORD ret;
129
130 LoadString (hinstance, IDS_MAYBE_MKDIR, fmtString, sizeof fmtString);
131 snprintf (msgText, sizeof msgText, fmtString, dirname);
132
133 ret = MessageBox (h, msgText, 0, MB_ICONSTOP | MB_YESNO);
134 if (ret == IDNO)
135 return -1;
136 }
137
138 int rv = mkdir_p (true, dirname, 0);
139
140 if (rv)
141 note (h, IDS_CANT_MKDIR, dirname);
142
143 return rv;
144 }
145
146 static int CALLBACK
147 browse_cb (HWND h, UINT msg, LPARAM lp, LPARAM data)
148 {
149 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
150 static CHAR dirname[MAX_PATH];
151 switch (msg)
152 {
153 case BFFM_INITIALIZED:
154 if (local_dir.size())
155 SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM) local_dir.c_str());
156 break;
157 case BFFM_SELCHANGED:
158 {
159 // Make a note of each new dir we successfully select, so that
160 // we know where to create the new directory if an invalid name
161 // is entered in the text box.
162 LPITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(lp);
163 SHGetPathFromIDList (pidl, dirname);
164 break;
165 }
166 case BFFM_VALIDATEFAILED:
167 // See if user wants to create a dir in the last successfully-selected.
168 CHAR tempname[MAX_PATH];
169 snprintf (tempname, sizeof tempname, "%s\\%s", dirname, reinterpret_cast<LPTSTR>(lp));
170 if (!offer_to_create (h, tempname))
171 {
172 SendMessage (h, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(tempname));
173 return -1;
174 }
175 // Reset to original directory instead.
176 SendMessage (h, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(dirname));
177 return -1;
178 }
179 return 0;
180 }
181
182 static void
183 browse (HWND h)
184 {
185 BROWSEINFO bi;
186 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
187 CHAR name[MAX_PATH];
188 LPITEMIDLIST pidl;
189 memset (&bi, 0, sizeof (bi));
190 bi.hwndOwner = h;
191 bi.pszDisplayName = name;
192 bi.lpszTitle = (source != IDC_SOURCE_LOCALDIR) ? "Select download directory"
193 : "Select local package directory";
194 bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE
195 | ((source != IDC_SOURCE_LOCALDIR) ? (BIF_EDITBOX | BIF_VALIDATE)
196 : 0);
197 bi.lpfn = browse_cb;
198 pidl = SHBrowseForFolder (&bi);
199 if (pidl)
200 {
201 if (SHGetPathFromIDList (pidl, name))
202 eset (h, IDC_LOCAL_DIR, name);
203 }
204 }
205
206 static BOOL
207 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
208 {
209 switch (id)
210 {
211
212 case IDC_LOCAL_DIR:
213 save_dialog (h);
214 check_if_enable_next (h);
215 break;
216
217 case IDC_LOCAL_DIR_BROWSE:
218 browse (h);
219 break;
220 }
221 return 0;
222 }
223
224 LocalDirPage::LocalDirPage ()
225 {
226 sizeProcessor.AddControlInfo (LocaldirControlsInfo);
227 }
228
229 bool
230 LocalDirPage::Create ()
231 {
232 return PropertyPage::Create (NULL, dialog_cmd, IDD_LOCAL_DIR);
233 }
234
235 void
236 LocalDirPage::OnActivate ()
237 {
238 load_dialog (GetHWND ());
239 }
240
241 long
242 LocalDirPage::OnNext ()
243 {
244 HWND h = GetHWND ();
245
246 save_dialog (h);
247 while (local_dir[local_dir.size() - 1] == '\\' || local_dir[local_dir.size() - 1] == '/')
248 local_dir.erase (local_dir.size() - 1, 1);
249 LocalDirSetting::save ();
250 Log (LOG_PLAIN) << "Selected local directory: " << local_dir << endLog;
251
252 bool tryLocalDir = true;
253 while (tryLocalDir)
254 {
255 tryLocalDir = false;
256 /* FIXME: As for almost any other string, we should store local_dir
257 as UNICODE string to avoid the whole conversion mess.
258 We call GetFileAttributesW because our own version implies
259 FILE_OPEN_FOR_BACKUP_INTENT. We don't try to change CWD for
260 the same reason. */
261 size_t len = local_dir.size () + 7;
262 WCHAR wlocal[len];
263 mklongpath (wlocal, local_dir.c_str (), len);
264 DWORD attr = GetFileAttributesW (wlocal);
265 if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
266 {
267 if (source == IDC_SOURCE_LOCALDIR)
268 {
269 do_from_local_dir (GetInstance (), GetHWND (), local_dir);
270 Progress.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD);
271 return IDD_INSTATUS;
272 }
273 }
274 else if (attr == INVALID_FILE_ATTRIBUTES
275 && (GetLastError () == ERROR_FILE_NOT_FOUND
276 || GetLastError () == ERROR_PATH_NOT_FOUND))
277 {
278 if (source == IDC_SOURCE_LOCALDIR)
279 {
280 if (!unattended_mode)
281 {
282 // Check the user really wants only to uninstall.
283 char msgText[1000];
284 LoadString (hinstance, IDS_NO_LOCALDIR, msgText,
285 sizeof (msgText));
286 char msg[1000 + local_dir.size ()];
287 snprintf (msg, sizeof (msg), msgText, local_dir.c_str (),
288 is_64bit ? "x86_64" : "x86");
289 int ret = MessageBox (h, msg, 0, MB_ICONEXCLAMATION | MB_OKCANCEL);
290 if (ret == IDCANCEL)
291 return -1;
292 }
293 Progress.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD);
294 return IDD_INSTATUS;
295 }
296 else if (offer_to_create (GetHWND (), local_dir.c_str ()))
297 return -1;
298 tryLocalDir = true;
299 }
300 else
301 {
302 DWORD err = GetLastError ();
303 char msgText[1000];
304 LoadString (hinstance, IDS_ERR_CHDIR, msgText, sizeof (msgText));
305 char* buf;
306 char msg[1000];
307 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
308 FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, err, LANG_NEUTRAL,
309 (LPSTR)&buf, 0, 0) != 0)
310 {
311 snprintf (msg, sizeof (msg), msgText, local_dir.c_str(),
312 buf, err);
313 LocalFree (buf);
314 }
315 else
316 snprintf (msg, sizeof (msg), msgText, local_dir.c_str(),
317 "(unknown error)", err);
318 Log (LOG_PLAIN) << msg << endLog;
319 int ret = MessageBox (h, msg, 0, MB_ICONEXCLAMATION |
320 MB_ABORTRETRYIGNORE);
321
322 if ((ret == IDABORT) || (ret == IDCANCEL))
323 return -1;
324 else
325 tryLocalDir = (ret == IDRETRY);
326 // XXX: On IDIGNORE we drop through to IDD_NET, which is wrong in
327 // the source == IDC_SOURCE_LOCALDIR case?
328 }
329 }
330
331 return 0; // IDD_NET
332 }
333
334 long
335 LocalDirPage::OnBack ()
336 {
337 save_dialog (GetHWND ());
338 return 0;
339 }
This page took 0.050436 seconds and 5 git commands to generate.