home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
share
/
YaST2
/
modules
/
SourceManagerSLP.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
13KB
|
485 lines
/**
* File: modules/SourceManagerSLP.ycp
* Package: SLP Source Management
* Summary: SLP-related SourceManager settings
* Authors: Lukas Ocilka <locilka@suse.cz>
* Status: Work in Progress
*
* $Id:$
*
* This module provides a complete set of functions that allows you to search
* and select a new SLP source.
*/
{
import "SLP";
import "Wizard";
import "Directory";
import "Stage";
import "SuSEFirewall";
import "Report";
import "Label";
// import "IP";
// import "String";
// import "FileUtils";
textdomain "packager";
module "SourceManagerSLP";
term Icon (string icon_name) {
map ui_info = UI::GetDisplayInfo();
if ((boolean) ui_info["HasLocalImageSupport"]:false == false) return `Empty();
return `Image (
sformat (
"%1/current/icons/22x22/apps/%2.png",
Directory::themedir,
icon_name
),
"[x]"
);
}
void CreateSearchUI () {
UI::OpenDialog (
`VBox (
`HBox (
`HSquash (`MarginBox (0.5, 0.2, Icon ("yast-you_server"))),
// translators: popup heading (progress popup)
`Left (`Heading(`id(`search_heading), _("SLP Search")))
),
`Left (
`ReplacePoint(`id(`search_rp), `Empty())
)
)
);
}
void CloseSearchUI () {
UI::CloseDialog ();
}
void SetSearchUI (term content) {
UI::ReplaceWidget(`id(`search_rp), content);
}
void SearchForSLPServices (list <map> & services) {
// progress information
SetSearchUI (`Label (_("Scanning network for installation services...")));
y2milestone("scanning network: SLP::FindSrvs(\"install.suse\", \"\")");
services = SLP::FindSrvs ("install.suse", "");
y2milestone("Done, found %1 sources", size(services));
}
void CreateSLPListFoundDialog (list <map> & services) {
term filter_dialog = `Empty();
boolean show_filter = false;
// Show filter only for bigger amount of services
if (size(services) > 15) {
show_filter = true;
filter_dialog = `MarginBox (0.5, 0.5, `Frame (
// frame label
_("Filter Form"),
`VSquash (`HBox (
// Only some characters are valid 'A-Z a-z 0-9 .*-'
`HSquash(`TextEntry (`id (`filter_text), "")),
// push button
`PushButton(`id(`filter), `opt(`default), _("&Filter")),
`HStretch()
))
));
}
// bugzilla #209426
// window size (in ncurses) based on currently available space
map display_info = UI::GetDisplayInfo();
integer min_size_x = 76;
integer min_size_y = 19;
if (display_info["TextMode"]:true) {
min_size_x = tointeger(display_info["Width"]:80) * 3 / 4;
min_size_y = tointeger(display_info["Height"]:25) * 2 / 3 - 5;
if (min_size_x < 76) min_size_x = 76;
if (min_size_y < 18) min_size_y = 18;
y2milestone("X/x Y/y %1/%2 %3/%4",
display_info["Width"]:80, min_size_x,
display_info["Height"]:25, min_size_y);
}
UI::OpenDialog (
`VBox (
`HBox (
`HSquash (`MarginBox (0.5, 0.2, Icon ("yast-you_server"))),
// translators: popup heading
`Left (`Heading(`id(`search_heading), _("Choose SLP Catalog")))
),
filter_dialog,
`MarginBox (0.5, 0, `MinSize(
min_size_x, min_size_y,
`Tree (
`id (`tree_of_services),
`opt (`notify),
// tree label (tree of available products)
_("Available Installation Products"),
[]
)
)),
`PushButton(`id(`details), _("Details...")),
`VSpacing (1),
`HBox (
`PushButton (`id (`ok), `opt(`default), Label::SelectButton ()),
`VSpacing (1),
`PushButton (`id (`cancel), Label::CancelButton ())
)
)
);
if (show_filter) {
UI::SetFocus(`filter_text);
}
}
void InitDetailsButton () {
integer current = (integer) UI::QueryWidget(`id(`tree_of_services), `CurrentItem);
if (current == nil || current < 0) {
UI::ChangeWidget(`id(`details), `Enabled, false);
} else {
UI::ChangeWidget(`id(`details), `Enabled, true);
}
}
void ShowDetailsDialog (list <map> & services) {
integer current = (integer) UI::QueryWidget(`id(`tree_of_services), `CurrentItem);
if (current == nil || current < 0) {
y2error("No service selected, no details");
// error popup
Report::Error(_("No details are available."));
} else {
map service_details = services[current]:$[];
if (service_details == $[]) {
// message popup
Report::Message(_("No details are available."));
} else {
list <term> details = [];
foreach (any key, any value, service_details, {
details = add (details, `item (`id(nil), tostring (key), tostring (value)));
});
UI::OpenDialog (
`VBox (
`Left (`Heading(`id(`details_heading), _("Catalog Details"))),
`MinSize (
60, 16,
`Table (
`header(
// table header item
_("Key"),
// table header item
_("Value")
),
details
)
),
`VSpacing (1),
`PushButton (`id(`ok), Label::OKButton())
)
);
UI::UserInput();
UI::CloseDialog();
}
}
}
/**
* Initializes the listed SLP services.
*
* @param list <map> services (reference)
* @param string regexp for services that should be visible (nil or "" for all)
*/
void InitSLPListFoundDialog (list <map> & services, string regexp_string) {
if (regexp_string == "") regexp_string = nil;
map <string, list <integer> > inst_products = $[];
string service_label = nil;
// index in the list of 'services'
integer service_counter = -1;
foreach (map one_service, services, {
// always increase the service ID, must be consistent for all turns
service_counter = service_counter + 1;
service_label = one_service["label"]:"";
// bugzilla #219759
// service label can be empty (not defined)
if (service_label == "") {
if (one_service["srvurl"]:"" != "") {
service_label = sformat (
"%1: %2",
_("Catalog URL"),
substring (one_service["srvurl"]:"", 21)
);
} else {
y2error ("Wrong service definition: %1, key \"srvurl\" must not be empty.", one_service);
}
}
// search works in "label" or in "srvurl" as a fallback
if (regexp_string != nil) {
// filter out all services that don't match the regexp
if (! regexpmatch (service_label, regexp_string)) return;
}
// define an empty list if it is not defined at all
if (inst_products[service_label]:nil == nil) inst_products[service_label] = [];
inst_products[service_label] = add (inst_products[service_label]:[], service_counter);
});
list <term> tree_of_services = [];
list <term> urls_for_product = nil;
integer product_counter = -1;
string service_url = nil;
// "SUSE Linux 10.2 x86_64":[10, 195]
foreach (string one_product, list <integer> service_ids, inst_products, {
product_counter = product_counter + 1;
if (size(service_ids) == 1) {
integer service_id = service_ids[0]:nil;
tree_of_services[product_counter] = `item (`id(service_id), one_product);
} else {
urls_for_product = [];
foreach (integer service_id, service_ids, {
// removing "install.suse..."
service_url = substring(services[service_id, "srvurl"]:"", 21);
urls_for_product = add (
urls_for_product,
`item (`id (service_id), service_url)
);
});
// -1 for a product name without url (URLs are hidden below)
tree_of_services[product_counter] = `item (`id (-1), one_product, urls_for_product);
}
});
UI::ChangeWidget (`id(`tree_of_services), `Items, tree_of_services);
InitDetailsButton ();
}
string GetCurrentlySelectedURL (list <map> & services) {
integer current = (integer) UI::QueryWidget(`id(`tree_of_services), `CurrentItem);
if (current == nil || current < 0) {
// message popup
Report::Message (_("Please, select one of offered options.
This product has more installation sources available."));
return nil;
} else {
string service_url = substring (services[current, "srvurl"]:"", 21);
if (service_url == nil || service_url == "") {
y2error(
"An internal error occurred, service ID %1, %2 has no URL!",
current, services[current]:$[]
);
// popup error
Report::Error (_("An internal error occurred.
The selected source has no URL."));
return nil;
} else {
return service_url;
}
}
}
string EscapeChars(string input, string escape)
{
string ret = input;
if (escape != nil && size(escape) > 0)
{
integer i = 0;
integer sz = size(escape);
while(i < sz)
{
string ch = substring(escape, i, 1);
y2debug("Escaping %1", ch);
ret = mergestring(splitstring(ret, ch), "\\" + ch);
i = i + 1;
};
}
return ret;
}
string HandleSLPListDialog (list <map> & services) {
InitSLPListFoundDialog (services, nil);
string dialog_ret = nil;
any ret = nil;
while (true) {
ret = UI::UserInput();
if (ret == `cancel) {
dialog_ret = nil;
break;
} else if (ret == `ok) {
dialog_ret = GetCurrentlySelectedURL (services);
y2milestone("Selected URL: '%1'", dialog_ret);
if (dialog_ret != "" && dialog_ret != nil) {
break;
}
} else if (ret == `tree_of_services) {
InitDetailsButton();
} else if (ret == `filter) {
string regexp_string = (string) UI::QueryWidget (`id(`filter_text), `Value);
y2milestone("original regexp_string: %1", regexp_string);
// escape special character in the input string
// \ must be the first character!
regexp_string = EscapeChars(regexp_string, "\\(){}[]+^$|");
y2milestone("escaped regexp_string: %1", regexp_string);
InitSLPListFoundDialog (services, regexp_string);
} else if (ret == `details) {
ShowDetailsDialog (services);
} else {
y2error("Unknown ret: %1", ret);
}
}
return dialog_ret;
}
void CloseSLPListFoundDialog () {
UI::CloseDialog();
}
void SearchForSLPServicesInfo (list <map> & services) {
integer number_of_services = size (services);
SetSearchUI (`Label (sformat (
// progress information, %1 stands for number of services
_("Collecting information of %1 services found..."),
number_of_services
)));
y2milestone("Collecting data about %1 services", number_of_services);
list <map> new_services = [];
map<string,string> dns_cache = $[];
integer counter = -1;
foreach (map slp_service, services, {
counter = counter + 1;
string server_ip = slp_service["ip"]:"";
string service_url = slp_service["srvurl"]:"";
// bugzilla #219759
// /usr/bin/host not in inst-sys
// Anyway, it's not needed - key "ip" defines the server which has sent this reply
//
// if (!IP::Check4(server_ip))
// {
// if (haskey(dns_cache, server_ip))
// {
// server_ip = dns_cache[server_ip]:"";
// }
// else if (FileUtils::Exists ("/usr/bin/host"))
// {
// string server_ip_quoted = "'" + String::Quote (server_ip) + "'";
// y2milestone ("Resolving host %1...", server_ip_quoted);
// map m = (map)SCR::Execute (.target.bash_output, sformat ("/usr/bin/host %1 | /bin/grep address", server_ip_quoted));
//
// if (m["exit"]:0 == 0)
// {
// string out = m["stdout"]:"";
// string ip = regexpsub (out, "has address (.*)$", "\\1");
// if (ip != nil)
// {
// y2milestone("...resolved to %1", ip);
// // cache the IP address
// dns_cache[server_ip] = ip;
//
// server_ip = ip;
// }
// }
// }
// }
// empty server_ip
if (service_url != "" && server_ip != "") {
map attrs = SLP::GetUnicastAttrMap (service_url, server_ip);
if (attrs != nil && attrs != $[]) {
slp_service = union (slp_service, attrs);
}
}
new_services[counter] = slp_service;
});
y2milestone("Done");
services = new_services;
}
/**
* Function searches the SLP services on the current network.
* If there are some SLP services, opens up a dialog containing
* them and user has to select one or cancel the operation.
* Selected URL is returned as string, otherwise a nil is returned.
*
* @return string service_URL
*/
global string SelectOneSLPService () {
CreateSearchUI();
list <map> slp_services_found = [];
SearchForSLPServices (slp_services_found);
if (slp_services_found == nil || size(slp_services_found) == 0) {
y2warning("No SLP catalogs found");
} else {
SearchForSLPServicesInfo(slp_services_found);
}
CloseSearchUI();
// no servers found
if (slp_services_found == nil || size(slp_services_found) == 0) {
y2warning ("No SLP catalogs were found");
if ((! Stage::initial ()) && SuSEFirewall::IsStarted ()) {
Report::Message (
// error popup
_("No SLP catalogs have been found on your network.
This could be caused by a running SuSEfirewall2,
which probably blocks the network scanning.")
);
} else {
Report::Message (
// error popup
_("No SLP catalogs have been found on your network.")
);
}
return nil;
}
CreateSLPListFoundDialog (slp_services_found);
string selected_service = HandleSLPListDialog (slp_services_found);
CloseSLPListFoundDialog ();
return selected_service;
}
/* EOF */
}