2 * Copyright (c) 2000, Red Hat, Inc.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by DJ Delorie <dj@cygnus.com>
16 /* The purpose of this file is to get the list of mirror sites and ask
17 the user which mirror site they want to download from. */
20 static const char *cvsid
=
38 #include "LogSingleton.h"
39 #include "io_stream.h"
42 #include "propsheet.h"
45 #include "ControlAdjuster.h"
46 #include "Exception.h"
51 extern ThreeBarProgressPage Progress
;
55 What to do if dropped mirrors are selected.
59 CACHE_REJECT
, // Go back to re-select mirrors.
60 CACHE_ACCEPT_WARN
, // Go on. Warn again next time.
61 CACHE_ACCEPT_NOWARN
// Go on. Don't warn again.
67 static ControlAdjuster::ControlInfo SiteControlsInfo
[] = {
68 {IDC_URL_LIST
, CP_STRETCH
, CP_STRETCH
},
69 {IDC_EDIT_USER_URL
, CP_STRETCH
, CP_BOTTOM
},
70 {IDC_BUTTON_ADD_URL
, CP_RIGHT
, CP_BOTTOM
},
71 {IDC_SITE_USERURL
, CP_LEFT
, CP_BOTTOM
},
77 sizeProcessor
.AddControlInfo (SiteControlsInfo
);
80 #include "getopt++/StringOption.h"
81 #include "getopt++/BoolOption.h"
82 #include "UserSettings.h"
87 bool cache_needs_writing
;
88 string cache_warn_urls
;
93 /* Fresh mirrors + selected sites */
94 SiteList all_site_list
;
96 /* Previously fresh + cached before */
97 SiteList cached_site_list
;
99 /* Stale selected sites to warn about and add to cache */
100 SiteList dropped_site_list
;
102 StringOption
SiteOption("", 's', "site", "Download site", false);
104 BoolOption
OnlySiteOption(false, 'O', "only-site", "Ignore all sites except for -s");
106 SiteSetting::SiteSetting (): saved (false)
108 string SiteOptionString
= SiteOption
;
109 if (SiteOptionString
.size())
110 registerSavedSite (SiteOptionString
.c_str());
118 io_stream
*f
= UserSettings::instance().open ("last-mirror");
121 for (SiteList::const_iterator n
= site_list
.begin ();
122 n
!= site_list
.end (); ++n
)
129 SiteSetting::~SiteSetting ()
136 site_list_type::init (const string
&_url
, const string
&_servername
,
137 const string
&_area
, const string
&_location
)
140 servername
= _servername
;
142 location
= _location
;
143 displayed_url
= url
.substr (0, url
.find ("/", url
.find (".")));
146 string::size_type last_idx
= displayed_url
.length () - 1;
147 string::size_type idx
= url
.find_last_of("./", last_idx
);
148 if (last_idx
- idx
== 3)
150 /* Sort non-country TLDs (.com, .net, ...) together. */
155 key
+= url
.substr(idx
+ 1, last_idx
- idx
);
158 idx
= url
.find_last_of("./", last_idx
);
159 if (idx
== string::npos
)
165 site_list_type::site_list_type (const string
&_url
,
166 const string
&_servername
,
168 const string
&_location
)
170 init (_url
, _servername
, _area
, _location
);
173 site_list_type::site_list_type (site_list_type
const &rhs
)
177 servername
= rhs
.servername
;
179 location
= rhs
.location
;
180 displayed_url
= rhs
.displayed_url
;
184 site_list_type::operator= (site_list_type
const &rhs
)
188 servername
= rhs
.servername
;
190 location
= rhs
.location
;
191 displayed_url
= rhs
.displayed_url
;
196 site_list_type::operator == (site_list_type
const &rhs
) const
198 return stricmp (key
.c_str(), rhs
.key
.c_str()) == 0;
202 site_list_type::operator < (site_list_type
const &rhs
) const
204 return stricmp (key
.c_str(), rhs
.key
.c_str()) < 0;
210 // Remove anything that was previously in the selected site list.
213 HWND listbox
= GetDlgItem (h
, IDC_URL_LIST
);
214 int sel_count
= SendMessage (listbox
, LB_GETSELCOUNT
, 0, 0);
217 int sel_buffer
[sel_count
];
218 SendMessage (listbox
, LB_GETSELITEMS
, sel_count
, (LPARAM
) sel_buffer
);
219 for (int n
= 0; n
< sel_count
; n
++)
222 SendMessage (listbox
, LB_GETITEMDATA
, sel_buffer
[n
], 0);
223 site_list
.push_back (all_site_list
[mirror
]);
229 load_site_list (SiteList
& theSites
, char *theString
)
231 char *bol
, *eol
, *nl
;
237 for (eol
= bol
; *eol
&& *eol
!= '\n'; eol
++);
242 while (eol
> bol
&& eol
[-1] == '\r')
245 if (*bol
== '#' || !*bol
)
247 /* Accept only the URL schemes we can understand. */
248 if (strncmp(bol
, "http://", 7) == 0 ||
249 strncmp(bol
, "ftp://", 6) == 0)
251 char *semi
= strchr (bol
, ';');
258 semi2
= strchr (semi
, ';');
263 semi3
= strchr (semi2
, ';');
271 site_list_type
newsite (bol
, semi
, semi2
, semi3
);
272 SiteList::iterator i
= find (theSites
.begin(),
273 theSites
.end(), newsite
);
274 if (i
== theSites
.end())
277 merge (theSites
.begin(), theSites
.end(),
278 &newsite
, &newsite
+ 1,
279 inserter (result
, result
.begin()));
283 //TODO: remove and remerge
290 get_site_list (HINSTANCE h
, HWND owner
)
292 char mirror_url
[1000];
294 char *theMirrorString
, *theCachedString
;
295 const char *cached_mirrors
= OnlySiteOption
? NULL
: UserSettings::instance().get ("mirrors-lst");
298 log (LOG_BABBLE
) << "Loaded cached mirror list" << endLog
;
299 cache_is_usable
= true;
303 log (LOG_BABBLE
) << "Cached mirror list unavailable" << endLog
;
304 cache_is_usable
= false;
308 if (LoadString (h
, IDS_MIRROR_LST
, mirror_url
, sizeof (mirror_url
)) <= 0)
311 string mirrors
= OnlySiteOption
? string ("") : get_url_to_string (mirror_url
, owner
);
313 cache_needs_writing
= true;
316 if (!cached_mirrors
[0])
317 log (LOG_BABBLE
) << "Defaulting to empty mirror list" << endLog
;
320 mirrors
= cached_mirrors
;
321 log (LOG_BABBLE
) << "Using cached mirror list" << endLog
;
323 cache_is_usable
= false;
324 cache_needs_writing
= false;
326 theMirrorString
= new_cstr_char_array (mirrors
);
327 theCachedString
= new_cstr_char_array (cached_mirrors
);
329 load_site_list (all_site_list
, theMirrorString
);
330 load_site_list (cached_site_list
, theCachedString
);
332 delete[] theMirrorString
;
333 delete[] theCachedString
;
338 /* List of machines that should not be used by default when saved
340 #define NOSAVE1 "ftp://sourceware.org/"
341 #define NOSAVE1_LEN (sizeof (NOSAVE2) - 1)
342 #define NOSAVE2 "ftp://sources.redhat.com/"
343 #define NOSAVE2_LEN (sizeof (NOSAVE1) - 1)
344 #define NOSAVE3 "ftp://gcc.gnu.org/"
345 #define NOSAVE3_LEN (sizeof (NOSAVE3) - 1)
348 SiteSetting::registerSavedSite (const char * site
)
350 site_list_type
tempSite(site
, "", "", "");
351 SiteList::iterator i
= find (all_site_list
.begin(),
352 all_site_list
.end(), tempSite
);
353 if (i
== all_site_list
.end())
355 /* Don't default to certain machines if they suffer
356 from bandwidth limitations. */
357 if (strnicmp (site
, NOSAVE1
, NOSAVE1_LEN
) == 0
358 || strnicmp (site
, NOSAVE2
, NOSAVE2_LEN
) == 0
359 || strnicmp (site
, NOSAVE3
, NOSAVE3_LEN
) == 0)
362 merge (all_site_list
.begin(), all_site_list
.end(),
363 &tempSite
, &tempSite
+ 1,
364 inserter (result
, result
.begin()));
365 all_site_list
= result
;
366 site_list
.push_back (tempSite
);
369 site_list
.push_back (tempSite
);
373 SiteSetting::getSavedSites ()
375 const char *buf
= UserSettings::instance().get ("last-mirror");
378 char *fg_ret
= strdup (buf
);
379 for (char *site
= strtok (fg_ret
, "\n"); site
; site
= strtok (NULL
, "\n"))
380 registerSavedSite (site
);
385 do_download_site_info_thread (void *p
)
390 context
= (HANDLE
*) p
;
394 hinst
= (HINSTANCE
) (context
[0]);
395 h
= (HWND
) (context
[1]);
396 static bool downloaded
= false;
397 if (!downloaded
&& get_site_list (hinst
, h
))
399 // Error: Couldn't download the site info.
400 // Go back to the Net setup page.
401 MessageBox (h
, TEXT ("Can't get list of download sites.\n")
402 TEXT("Make sure your network settings are correct and try again."),
405 // Tell the progress page that we're done downloading
406 Progress
.PostMessage (WM_APP_SITE_INFO_DOWNLOAD_COMPLETE
, 0, IDD_NET
);
411 // Everything worked, go to the site select page
412 // Tell the progress page that we're done downloading
413 Progress
.PostMessage (WM_APP_SITE_INFO_DOWNLOAD_COMPLETE
, 0, IDD_SITE
);
416 TOPLEVEL_CATCH("site");
421 static HANDLE context
[2];
424 do_download_site_info (HINSTANCE hinst
, HWND owner
)
431 CreateThread (NULL
, 0, do_download_site_info_thread
, context
, 0, &threadID
);
435 drop_proc (HWND h
, UINT message
, WPARAM wParam
, LPARAM lParam
)
440 eset(h
, IDC_DROP_MIRRORS
, cache_warn_urls
);
441 /* Should this be set by default? */
442 // CheckDlgButton (h, IDC_DROP_NOWARN, BST_CHECKED);
443 SetFocus (GetDlgItem(h
, IDC_DROP_NOWARN
));
447 switch (LOWORD (wParam
))
450 if (IsDlgButtonChecked (h
, IDC_DROP_NOWARN
) == BST_CHECKED
)
451 EndDialog (h
, CACHE_ACCEPT_NOWARN
);
453 EndDialog (h
, CACHE_ACCEPT_WARN
);
457 EndDialog (h
, CACHE_REJECT
);
470 int check_dropped_mirrors (HWND h
)
472 cache_warn_urls
= "";
473 dropped_site_list
.clear ();
475 for (SiteList::const_iterator n
= site_list
.begin ();
476 n
!= site_list
.end (); ++n
)
478 SiteList::iterator i
= find (all_site_list
.begin(), all_site_list
.end(),
480 if (i
== all_site_list
.end() || !i
->servername
.size())
482 SiteList::iterator j
= find (cached_site_list
.begin(),
483 cached_site_list
.end(), *n
);
484 if (j
!= cached_site_list
.end())
486 log (LOG_PLAIN
) << "Dropped selected mirror: " << n
->url
488 dropped_site_list
.push_back (*j
);
489 if (cache_warn_urls
.size())
490 cache_warn_urls
+= "\r\n";
491 cache_warn_urls
+= i
->url
;
495 if (cache_warn_urls
.size())
498 return CACHE_ACCEPT_WARN
;
499 return DialogBox (hinstance
, MAKEINTRESOURCE (IDD_DROPPED
), h
,
502 return CACHE_ACCEPT_NOWARN
;
505 void write_cache_list (io_stream
*f
, const SiteList
& theSites
)
508 for (SiteList::const_iterator n
= theSites
.begin ();
509 n
!= theSites
.end (); ++n
)
510 if (n
->servername
.size())
511 *f
<< (n
->url
+ ";" + n
->servername
+ ";" + n
->area
+ ";"
515 void save_cache_file (int cache_action
)
518 io_stream
*f
= UserSettings::instance().open ("mirrors-lst");
521 write_cache_list (f
, all_site_list
);
522 if (cache_action
== CACHE_ACCEPT_WARN
)
524 log (LOG_PLAIN
) << "Adding dropped mirrors to cache to warn again."
526 *f
<< "# Following mirrors re-added by setup.exe to warn again about dropped urls.";
527 write_cache_list (f
, dropped_site_list
);
533 bool SitePage::Create ()
535 return PropertyPage::Create (IDD_SITE
);
542 int cache_action
= CACHE_ACCEPT_NOWARN
;
546 if (cache_is_usable
&& !(cache_action
= check_dropped_mirrors (h
)))
549 if (cache_needs_writing
)
550 save_cache_file (cache_action
);
552 // Log all the selected URLs from the list.
553 for (SiteList::const_iterator n
= site_list
.begin ();
554 n
!= site_list
.end (); ++n
)
555 log (LOG_PLAIN
) << "site: " << n
->url
<< endLog
;
557 Progress
.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD
);
570 // Go back to the net connection type page
575 SitePage::OnActivate ()
577 // Fill the list box with all known sites.
580 // Load the user URL box with nothing - it is in the list already.
581 eset (GetHWND (), IDC_EDIT_USER_URL
, "");
583 // Get the enabled/disabled states of the controls set accordingly.
584 CheckControlsAndDisableAccordingly ();
588 SitePage::OnUnattended ()
590 if (SendMessage (GetDlgItem (IDC_URL_LIST
), LB_GETSELCOUNT
, 0, 0) > 0)
597 SitePage::CheckControlsAndDisableAccordingly () const
599 DWORD ButtonFlags
= PSWIZB_BACK
;
601 // Check that at least one download site is selected.
602 if (SendMessage (GetDlgItem (IDC_URL_LIST
), LB_GETSELCOUNT
, 0, 0) > 0)
604 // At least one site selected, enable "Next".
605 ButtonFlags
|= PSWIZB_NEXT
;
607 GetOwner ()->SetButtons (ButtonFlags
);
611 SitePage::PopulateListBox ()
614 HWND listbox
= GetDlgItem (IDC_URL_LIST
);
616 // Populate the list box with the URLs.
617 SendMessage (listbox
, LB_RESETCONTENT
, 0, 0);
618 for (SiteList::const_iterator i
= all_site_list
.begin ();
619 i
!= all_site_list
.end (); ++i
)
621 j
= SendMessage (listbox
, LB_ADDSTRING
, 0,
622 (LPARAM
) i
->displayed_url
.c_str());
623 SendMessage (listbox
, LB_SETITEMDATA
, j
, j
);
626 // Select the selected ones.
627 for (SiteList::const_iterator n
= site_list
.begin ();
628 n
!= site_list
.end (); ++n
)
630 int index
= SendMessage (listbox
, LB_FINDSTRING
, (WPARAM
) - 1,
631 (LPARAM
) n
->displayed_url
.c_str());
634 // Highlight the selected item
635 SendMessage (listbox
, LB_SELITEMRANGE
, TRUE
, (index
<< 16) | index
);
636 // Make sure it's fully visible
637 SendMessage (listbox
, LB_SETCARETINDEX
, index
, FALSE
);
642 bool SitePage::OnMessageCmd (int id
, HWND hwndctl
, UINT code
)
646 case IDC_EDIT_USER_URL
:
648 // FIXME: Make Enter here cause an ADD, not a NEXT.
653 if (code
== LBN_SELCHANGE
)
655 CheckControlsAndDisableAccordingly ();
656 save_dialog (GetHWND ());
660 case IDC_BUTTON_ADD_URL
:
662 if (code
== BN_CLICKED
)
664 // User pushed the Add button.
665 std::string other_url
= egetString (GetHWND (), IDC_EDIT_USER_URL
);
666 if (other_url
.size())
668 site_list_type
newsite (other_url
, "", "", "");
669 SiteList::iterator i
= find (all_site_list
.begin(),
670 all_site_list
.end(), newsite
);
671 if (i
== all_site_list
.end())
673 all_site_list
.push_back (newsite
);
674 log (LOG_BABBLE
) << "Adding site: " << other_url
<< endLog
;
679 log (LOG_BABBLE
) << "Replacing site: " << other_url
<< endLog
;
682 // Assume the user wants to use it and select it for him.
683 site_list
.push_back (newsite
);
685 // Update the list box.
687 // And allow the user to continue
688 CheckControlsAndDisableAccordingly ();
689 eset (GetHWND (), IDC_EDIT_USER_URL
, "");
695 // Wasn't recognized or handled.
699 // Was handled since we never got to default above.