ACC SHELL
/**
* File: SourceDialogs.ycp
*
* Authors: Jiri Srain <jsrain@suse.cz>
* Klaus Kaempf <kkaempf@suse.de>
* Gabriele Strattner <gs@suse.de>
* Stefan Schubert <schubi@suse.de>
* Cornelius Schumacher <cschum@suse.de>
*
* Purpose:
* Displays possibilities to install from NFS, CD or partion
*
* $Id: inst_source_dialogs.ycp 31607 2006-06-22 07:02:01Z jsuchome $
*/
{
textdomain "packager";
module "SourceDialogs";
import "Label";
import "URL";
import "URLRecode";
import "Popup";
import "CWM";
import "SourceManager";
import "Message";
import "Report";
import "NetworkPopup";
import "String";
import "Hostname";
import "IP";
import "ProductControl";
import "ProductFeatures";
// common functions / data
/**
* URL to work with
*/
string _url = "";
/**
* The repo at _url is plaindir
*/
boolean _plaindir = false;
/**
* Repo name to work with
*/
string _repo_name = "";
// value of the "download" check box
boolean _download_metadata = true;
/**
* Allow HTTPS for next repository dialog?
*/
boolean _allow_https = true;
// CD/DVD device name to use (e.g. /dev/sr1) in case of multiple
// devices in the system. Empty string means use the default.
string cd_device_name = "";
/**
* Help text suffix for some types of the media
*/
string iso_help = _("<p>If the location is a file holding an ISO image
of the media, set <b>ISO Image</b>.</p>");
/**
* Help text suffix for some types of the media
*/
string multi_cd_help = _("<p>If the repository is on multiple media,
set the location of the first media of the set.</p>
");
/**
* Set the URL to work with
* @param url string URL to run the dialogs with
*/
global void SetURL (string url) {
_url = url;
map parsed = URL::Parse(_url);
// check if it's HDD or USB
// convert it to the internal representation
if (parsed["scheme"]:"" == "hd")
{
string query = parsed["query"]:"";
if (regexpmatch(query, "device=/dev/disk/by-id/usb-"))
{
parsed["scheme"] = "usb";
_url = URL::Build (parsed);
y2milestone("URL %1 is an USB device, changing the scheme to %2", URL::HidePassword(url), _url);
}
}
// reset the plaindir flag
_plaindir = false;
}
/**
* Set the URL to work with, set the plaindir flag (type of the repository)
* @param url string URL to run the dialogs with
* @param plaindir_type true if the repo type is plaindir
*/
global void SetURLType(string url, boolean plaindir_type)
{
SetURL(url);
// set the flag AFTER setting the URL!
// SetURL() resets the _plaindir flag
_plaindir = plaindir_type;
}
/**
* Return URL after the run of the dialog
* @return string the URL
*/
global string GetURL () {
map parsed = URL::Parse(_url);
// usb scheme is not valid, it's used only internally
// convert it for external clients
if (parsed["scheme"]:"" == "usb")
{
parsed["scheme"] = "hd";
if (parsed["path"]:"" == "")
{
parsed["path"] = "/";
}
string ret_url = URL::Build (parsed);
return ret_url;
}
else return _url;
}
/**
* Return the configured URL in the dialog, do not do any conversion (return the internal value)
* @return string raw internal URL
*/
global string GetRawURL()
{
return _url;
}
global boolean IsPlainDir()
{
return _plaindir;
}
/**
* Set the RepoName to work with
* @param repo_name string RepoName to run the dialogs with
*/
global void SetRepoName (string repo_name) {
_repo_name = repo_name;
}
/**
* Return RepoName after the run of the dialog
* @return string the RepoName
*/
global string GetRepoName () {
return _repo_name;
}
/**
* Postprocess URL of an ISO image
* @param url string URL in the original form
* @return string postprocessed URL
*/
string PosprocessISOURL (string url) {
y2milestone ("Updating ISO URL %1", URL::HidePassword(url));
integer last = findlastof (url, "/") + 1;
string onlydir = substring (url, 0, last);
url = "iso:///?iso=" + substring (url, last) + "&url=" + onlydir;
y2milestone ("Updated URL: %1", URL::HidePassword(url));
return url;
}
/**
* Check if URL is an ISO URL
* @param url string URL to check
* @return boolean true if URL is an ISO URL, false otherwise
*/
boolean IsISOURL (string url) {
boolean ret = substring (url, 0, 5) == "iso:/" &&
issubstring (url, "&url=");
y2milestone ("URL %1 is ISO: %2", URL::HidePassword(url), ret);
return ret;
}
/**
* Preprocess the ISO URL to be used in the dialogs
* @param url string URL to preprocess
* @return string preprocessed URL
*/
string PreprocessISOURL (string url) {
y2milestone ("Preprocessing ISO URL %1", URL::HidePassword(url));
integer url_pt = search (url, "&url=");
string serverpart = substring (url, url_pt + 5);
string isopart = substring (url, 0, url_pt);
url = serverpart + substring (isopart, search (isopart, "iso=") + 4);
y2milestone ("Updated URL: %1", URL::HidePassword(url));
return url;
}
/**
* check if given path points to ISO file
* @param url string URL to check
* @return boolean true if URL is ISO image
*/
boolean PathIsISO (string url) {
if (size (url) < 4) return false;
return substring (url, size (url) - 4, 4) == ".iso";
}
/**
* Add a slash to the part of url, if it is not already present
* @param urlpart string a part of the URL
* @return string urlpart with leading slash
*/
string Slashed (string urlpart) {
if ( substring( urlpart, 0, 1 ) == "/" )
return urlpart;
return "/" + urlpart;
}
/**
* Remove leading and trailing (and inner) spaces from the host name
* @param host string original host name
* @return string host without leading and trailing spaces
*/
string NormalizeHost (string host) {
host = deletechars (host, " \t");
return host;
}
/**
* Return an HBox with ok and cancel buttons for use by other dialogs.
* @return An HBox term for use in a CreateDialog call.
*/
term PopupButtons() {
return `HBox(
`PushButton( `id( `ok ), `opt( `default ), Label::OKButton() ),
`HSpacing(2),
`PushButton( `id( `cancel ), Label::CancelButton() )
);
}
/**
* Get scheme of a URL, also for ISO URL get scheme of the access protocol
* @param url string URL to get scheme for
* @return string URL scheme
*/
string URLScheme (string url) {
string scheme = "";
if (IsISOURL (url))
{
string tmp_url = PreprocessISOURL (url);
map parsed = URL::Parse (tmp_url);
scheme = parsed["scheme"]:"";
}
else
{
map parsed = URL::Parse (url);
scheme = parsed["scheme"]:"";
}
if (scheme == "" || scheme == nil)
scheme = "url";
y2milestone ("URL scheme for URL %1: %2", URL::HidePassword(url), scheme);
return scheme;
}
/**
* Init function of a widget
* @param key string widget key
*/
void RepoNameInit (string key) {
UI::ChangeWidget (`id (`repo_name), `Value, _repo_name);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void RepoNameStore (string key, map event) {
_repo_name = (string)UI::QueryWidget (`id (`repo_name), `Value);
}
boolean RepoNameValidate (string key, map event) {
string repo_name = (string)UI::QueryWidget (`id (`repo_name), `Value);
if (repo_name == "" && _repo_name != "") // do not fail on new repo creation
{
UI::SetFocus (`id (`repo_name));
// popup message
Popup::Message (_("The name of the repository cannot be empty."));
return false;
}
return true;
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> RepoNameWidget () {
return $[
"widget" : `custom,
"custom_widget" : `VBox (
// text entry
`InputField( `id( `repo_name ), `opt(`hstretch), _("&Repository Name") )
),
"init" : RepoNameInit,
"store" : RepoNameStore,
"validate_type" : `function,
// TODO FIXME: RepoName can be empty if the URL has been changed,
// yast will use the product name or the URL in this case (the repository is recreated)
"validate_function" : RepoNameValidate,
// help text
"help" : _("<p><big><b>Repository Name</b></big><br>
Use <b>Repository Name</b> to specify the name of the repository. If it is empty, YaST will use the product name (if available) or the URL as the name.</p>
")
];
}
map<string,any> ServiceNameWidget()
{
map<string,any> ret = RepoNameWidget();
ret["custom_widget"] = `VBox (
// text entry
`InputField( `id( `repo_name ), `opt(`hstretch), _("&Service Name") )
);
// help text
ret["help"] = _("<p><big><b>Service Name</b></big><br>
Use <b>Service Name</b> to specify the name of the service. If it is empty, YaST will use part of the service URL as the name.</p>
");
return ret;
}
// raw URL editation widget
/**
* Init function of a widget
* @param key string widget key
*/
void PlainURLInit (string key) {
UI::ChangeWidget (`id (`url), `Value, _url);
UI::SetFocus (`url);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void PlainURLStore (string key, map event) {
_url = (string)UI::QueryWidget (`id (`url), `Value);
}
boolean PlainURLValidate (string key, map event) {
string url = (string)UI::QueryWidget (`id (`url), `Value);
if (url == "")
{
UI::SetFocus (`id (`url));
// popup message
Popup::Message (_("URL cannot be empty."));
return false;
}
return true;
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> PlainURLWidget () {
return $[
"widget" : `custom,
"custom_widget" : `VBox (
// text entry
`InputField (`id (`url), `opt(`hstretch), _("&URL"))
),
"init" : PlainURLInit,
"store" : PlainURLStore,
"validate_type" : `function,
"validate_function" : PlainURLValidate,
// help text
"help" : _("<p><big><b>Repository URL</b></big><br>
Use <b>URL</b> to specify the URL of the repository.</p>") + multi_cd_help,
];
}
// NFS editation widget
term nfs_details_content =
`VBox(
`HBox(
// text entry
`InputField (`id (`server), `opt (`hstretch), _("&Server Name")),
`VBox(
`Label(""),
`PushButton(`id(`nfs_browse), Label::BrowseButton())
)
),
`HBox(
// text entry
`InputField (`id (`dir), `opt (`hstretch), _("&Path to Directory or ISO Image")),
`VBox(
`Label(""),
`PushButton(`id(`nfs_exports_browse), Label::BrowseButton())
)
),
// checkbox label
`Left (`CheckBox ( `id (`ch_iso), _("&ISO Image"))),
// checkbox label
`Left (`CheckBox ( `id (`ch_nfs4), _("N&FS v4 Protocol")))
);
term nfs_complete_content = `InputField(`id(`complete_url), `opt(`hstretch), _("URL of the Repository"));
/**
* Init function of a widget
* @param key string widget key
*/
void NFSInit (string key) {
// check the current edit type
symbol current_type = (symbol)UI::QueryWidget(`id(`edit_type), `Value);
y2debug("Current edit type: %1", current_type);
UI::ReplaceWidget(`id(`edit_content), (current_type == `edit_url_parts) ? nfs_details_content : nfs_complete_content);
if (current_type == `edit_url_parts)
{
boolean iso = IsISOURL (_url);
string repo_url = _url;
if (iso)
repo_url = PreprocessISOURL(repo_url);
map parsed = URL::Parse (repo_url);
UI::ChangeWidget (`id (`server), `Value, parsed["host"]:"");
UI::ChangeWidget (`id (`dir), `Value, parsed["path"]:"");
UI::ChangeWidget (`id (`ch_iso), `Value, iso);
UI::SetFocus (`server);
boolean nfs4 = tolower(parsed["scheme"]:"nfs") == "nfs4" ||
URL::MakeMapFromParams(parsed["query"]:"")["type"]:"" == "nfs4";
y2milestone("NFSv4: %1", nfs4);
UI::ChangeWidget (`id (`ch_nfs4), `Value, nfs4);
}
else
{
UI::ChangeWidget(`id(`complete_url), `Value, _url);
}
}
void NFSStoreParts()
{
map parsed = $[
"scheme" : "nfs",
"host" : NormalizeHost (
(string)UI::QueryWidget (`id (`server), `Value)),
"path" : (string)UI::QueryWidget (`id (`dir), `Value),
];
boolean nfs4 = (boolean)UI::QueryWidget (`id (`ch_nfs4), `Value);
if (nfs4)
{
// keep nfs4:// if it is used in the original URL
if (tolower(URL::Parse(_url)["scheme"]:"") == "nfs4")
{
parsed["scheme"] = "nfs4";
}
else
{
parsed["query"] = "type=nfs4";
}
}
_url = URL::Build (parsed);
boolean iso = (boolean)UI::QueryWidget (`id (`ch_iso), `Value);
// workaround: URL::Build does not accept numbers in scheme,
// for nfs4 scheme it returns URL with no scheme (like "://foo/bar")
if(!regexpmatch(_url, "^nfs"))
{
_url = "nfs4" + _url;
}
if (iso)
_url = PosprocessISOURL (_url);
}
void NFSStoreComplete()
{
_url = (string)UI::QueryWidget(`id(`complete_url), `Value);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void NFSStore (string key, map event) {
symbol current_type = (symbol)UI::QueryWidget(`id(`edit_type), `Value);
y2milestone("Current edit type: %1", current_type);
if (current_type == `edit_url_parts)
{
NFSStoreParts();
}
else
{
NFSStoreComplete();
}
}
/**
* Handle function of a widget
* @param key string widget key
* @param event map which caused settings being stored
* @return always nil
*/
symbol NFSHandle (string key, map event) {
y2debug("NFSHandle: key: %1, event: %2", key, event);
if (event["ID"]:nil == `nfs_browse)
{
string server = (string)UI::QueryWidget (`id (`server), `Value);
// dialog caption
string result = NetworkPopup::NFSServer(server);
if (result != nil)
{
UI::ChangeWidget (`id (`server), `Value, result);
}
}
else if (event["ID"]:nil == `nfs_exports_browse)
{
string server = (string)UI::QueryWidget (`id (`server), `Value);
string nfs_export = (string)UI::QueryWidget (`id (`dir), `Value);
// dialog caption
string result = NetworkPopup::NFSExport(server, nfs_export);
if (result != nil)
{
UI::ChangeWidget (`id (`dir), `Value, result);
}
}
else if ((event["ID"]:nil == `edit_url_parts || event["ID"]:nil == `edit_complete_url) && event["EventReason"]:"" == "ValueChanged")
{
y2milestone("Changing dialog type: %1", event["ID"]:nil);
// store the current settings
if (event["ID"]:nil == `edit_url_parts)
{
NFSStoreComplete();
}
else
{
NFSStoreParts();
}
// reinitialize the dialog (set the current values)
NFSInit(nil);
}
return nil;
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> NFSWidget () {
return $[
"widget" : `custom,
"custom_widget" : `VBox (
`RadioButtonGroup (`id (`edit_type),
`HBox (
`RadioButton(`id(`edit_url_parts), `opt(`notify), _("Edit Parts of the URL"), true),
`HSpacing(2),
`RadioButton(`id(`edit_complete_url), `opt(`notify), _("Edit Complete URL"))
)
),
`ReplacePoint(`id(`edit_content), `Empty())
),
"init" : NFSInit,
"store" : NFSStore,
"handle" : NFSHandle,
// help text
"help" : _("<p><big><b>NFS Server</b></big><br>
Use <b>Server Name</b> and <b>Path to Directory or ISO Image</b>
to specify the NFS server host name and path on the server.</p>")
+ multi_cd_help,
];
}
// CD/DVD repository widget
/**
* Init function of a widget
* @param key string widget key
*/
void CDInit (string key) {
map parsed = URL::Parse (_url);
string scheme = parsed["scheme"]:"";
if (scheme == "dvd")
UI::ChangeWidget (`id (`dvd), `Value, true);
else
UI::ChangeWidget (`id (`cd), `Value, true);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void CDStore (string key, map event) {
symbol device = (symbol)UI::QueryWidget (`id (`device), `CurrentButton);
map parsed = URL::Parse (_url);
string scheme = tolower(parsed["scheme"]:"");
// preserve other URL options, e.g. ?devices=/dev/sr0
// change the URL only when necessary
if (device == `cd && scheme != "cd")
_url = "cd:///";
else if (device == `dvd && scheme != "dvd")
_url = "dvd:///";
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> CDWidget () {
return $[
"widget" : `custom,
"custom_widget" : `RadioButtonGroup (`id (`device), `VBox (
// radio button
`Left (`RadioButton (`id (`cd), _("&CD-ROM"))),
// radio button
`Left (`RadioButton (`id (`dvd ), _("&DVD-ROM")))
)),
"init" : CDInit,
"store" : CDStore,
"help" : _("<p><big><b>CD or DVD Media</b></big><br>
Set <b>CD-ROM</b> or <b>DVD-ROM</b> to specify the type of media.</p>"),
];
}
// File / Directory repository widget
/**
* Init function of a widget
* @param key string widget key
*/
void DirInit (string key) {
map parsed = URL::Parse (_url);
UI::ChangeWidget (`id (`dir), `Value, parsed["path"]:"");
UI::SetFocus (`dir);
// is it a plain directory?
UI::ChangeWidget(`id(`ch_plain), `Value, _plaindir);
}
/**
* Init function of a widget
* @param key string widget key
*/
void IsoInit (string key) {
_url = PreprocessISOURL(_url);
map parsed = URL::Parse(_url);
UI::ChangeWidget(`id(`dir), `Value, parsed["path"]:"");
UI::SetFocus(`dir);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void DirStore (string key, map event) {
map parsed = $[
"scheme" : "dir",
"path" : (string)UI::QueryWidget (`id (`dir), `Value),
];
if ((boolean)UI::QueryWidget (`id (`ch_plain), `Value))
{
_plaindir = true;
}
_url = URL::Build (parsed);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void IsoStore (string key, map event) {
map parsed = $[
"scheme" : "file",
"path" : (string)UI::QueryWidget (`id (`dir), `Value),
];
_url = URL::Build(parsed);
_url = PosprocessISOURL(_url);
}
/**
* Handle function of a widget
* @param key string widget key
* @param event map which caused settings being stored
* @return always nil
*/
symbol DirHandle (string key, map event) {
string dir = (string)UI::QueryWidget (`id (`dir), `Value);
// dialog caption
string result = UI::AskForExistingDirectory (dir, _("Local Directory"));
if (result != nil)
{
UI::ChangeWidget (`id (`dir), `Value, result);
}
return nil;
}
/**
* Handle function of a widget
* @param key string widget key
* @param event map which caused settings being stored
* @return always nil
*/
symbol IsoHandle (string key, map event) {
string dir = (string)UI::QueryWidget(`id(`dir), `Value);
// dialog caption
string result = UI::AskForExistingFile(dir, "*", _("ISO Image File"));
if (result != nil)
{
UI::ChangeWidget(`id (`dir), `Value, result);
}
return nil;
}
boolean DirValidate(string key, map event) {
string s = (string)UI::QueryWidget(`id(`dir), `Value);
if (s == nil || s == "")
{
// error popup
Popup::Error(Message::RequiredItem());
UI::SetFocus(`id(`dir));
return false;
}
map stat = (map)SCR::Read(.target.stat, s);
y2milestone("stat %1: %2", s, stat);
if (!stat["isdir"]:false)
{
// error popup - the entered path is not a directory
Report::Error(_("The entered path is not a directory
or the directory does not exist.
"));
UI::SetFocus(`id(`dir));
return false;
}
return true;
}
boolean IsoValidate(string key, map event) {
string s = (string)UI::QueryWidget(`id(`dir), `Value);
if (s == nil || s == "")
{
// error popup
Popup::Error(Message::RequiredItem());
UI::SetFocus(`id(`dir));
return false;
}
map stat = (map)SCR::Read(.target.stat, s);
y2milestone("stat %1: %2", s, stat);
if (!stat["isreg"]:false)
{
// error popup - the entered path is not a regular file
Report::Error(_("The entered path is not a file
or the file does not exist.
"));
UI::SetFocus(`id(`dir));
return false;
}
string file = "/usr/bin/file";
// try to detect ISO image by file if it's present
if (SCR::Read(.target.size, file) > 0)
{
string command = file + " -b " + s;
map out = (map)SCR::Execute(.target.bash_output, command);
string stdout = out["stdout"]:"";
if (issubstring(stdout, "ISO 9660 CD-ROM filesystem"))
{
y2milestone("ISO 9660 image detected");
}
else
{
// continue/cancel popup, %1 is a file name
return Popup::ContinueCancel(sformat(_("File '%1'
does not seem to be an ISO image.
Use it anyway?
"), s));
}
}
return true;
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> DirWidget () {
return $[
"widget" : `custom,
"custom_widget" : `VBox(
`HBox(
// text entry
`InputField (`id (`dir), `opt (`hstretch), _("&Path to Directory")),
`VBox (
`Label (""),
// push button
`PushButton (`id (`browse), Label::BrowseButton())
)
),
// checkbox label
`Left (`CheckBox (`id (`ch_plain), _("&Plain RPM Directory")))
),
"init" : DirInit,
"store" : DirStore,
"handle" : DirHandle,
"handle_events" : [ `browse ],
"validate_type" : `function,
"validate_function" : DirValidate,
"help" : _("<p><big><b>Local Directory</b></big><br>
Use <b>Path to Directory</b> to specify the path to the
directory. If the directory contains just RPM packages without
any metadata (i.e. there is no product information) then check option
<b>Plain RPM Directory</b>.</p>")
+ multi_cd_help,
];
}
list<string> DetectPartitions(string disk_id)
{
string command = sformat("ls %1-part*", disk_id);
map out = (map)SCR::Execute(.target.bash_output, command);
if (out["exit"]:-1 != 0)
{
y2error("Command %1 failed", command);
return [];
}
list<string> ret = splitstring(out["stdout"]:"", "\n");
integer ret_size = size(ret);
// remove empty string at the end
if (ret_size > 0 && ret[ret_size - 1]:"dummy" == "")
{
ret = remove(ret, ret_size - 1);
}
return ret;
}
string GetDeviceID(list<string> devices)
{
string ret = "";
foreach(string dev, devices,
{
if (regexpmatch(dev, "^/dev/disk/by-id/"))
{
ret = dev;
}
}
);
return ret;
}
list<map<string,any> > DetectDisk(boolean usb_only)
{
y2milestone("Detecting %1USB disks", usb_only ? "" : "non-");
list<map> disks = (list<map>)SCR::Read(.probe.disk);
y2debug("Detected disks: %1", disks);
disks = filter(map disk, disks,
{
return ((disk["driver"]:"" == "usb-storage") && usb_only)
|| ((disk["driver"]:"" != "usb-storage") && !usb_only);
}
);
y2milestone("Found disks: %1", disks);
list<map<string,any> > ret = [];
foreach(map disk, disks,
{
string dev_id = GetDeviceID(disk["dev_names"]:[]);
ret = add(ret,
$[
"model" : disk["model"]:"",
// compute the size (number of sectors * size of sector)
"size" : (disk["resource","size",0,"x"]:0) * (disk["resource","size",0,"y"]:0),
"dev" : disk["dev_name"]:"",
"dev_by_id" : dev_id,
"partitions" : DetectPartitions(dev_id)
]
);
}
);
y2milestone("Disk configuration: %1", ret);
return ret;
}
list<map<string,any> > DetectUSBDisk()
{
return DetectDisk(true);
}
list<map<string,any> > DetectHardDisk()
{
return DetectDisk(false);
}
list<term> DiskSelectionList(list<map<string,any> > disks, string selected)
{
list<term> ret = [];
boolean found = false;
foreach(map<string,any> disk, disks,
{
string label = disk["model"]:"";
// add size if it's known and there is just one partition
// TODO detect size of each partition
integer sz = disk["size"]:0;
if (sz > 0 && size(disk["partitions"]:[]) == 1)
{
label = label + " - " + String::FormatSize(sz);
}
string dev = disk["dev"]:"";
foreach(string part, (list<string>)disk["partitions"]:[],
{
string partnum = regexpsub(part, ".*-part([0-9])*$", "\\1");
string disk_label = label + sformat(" (%1%2)", dev, partnum);
found = found || (part == selected);
ret = add(ret, `item(`id(part), disk_label, part == selected));
}
);
}
);
if (!found && regexpmatch(selected, "^/dev/disk/by-id/usb-"))
{
y2milestone("USB disk %1 is not currently attached, adding the raw device to the list", selected);
// remove the /dev prefix
string dev_name = regexpsub(selected, "^/dev/disk/by-id/usb-(.*)", "\\1");
ret = add(ret, `item(`id(selected), dev_name, true));
}
return ret;
}
void SetFileSystems(string selected_fs)
{
list<string> fs_list = ["auto", "vfat", "ntfs", "ntfs-3g", "ext2", "ext3", "ext4", "reiserfs", "xfs", "jfs", "iso9660"];
list<term> items = maplist(string fs, fs_list,
{
return `item(`id(fs), fs, fs == selected_fs);
}
);
UI::ChangeWidget(`id(`fs), `Items, items);
}
// common code for USBInit() and DiskInit()
void InitDiskWidget(list<map<string,any> > disks)
{
map parsed = URL::Parse(_url);
map<string,string> query = URL::MakeMapFromParams(parsed["query"]:"");
UI::ChangeWidget(`id(`disk), `Items, DiskSelectionList(disks, query["device"]:""));
SetFileSystems(query["filesystem"]:"auto");
UI::ChangeWidget(`id(`dir), `Value, parsed["path"]:"");
// is it a plain directory?
UI::ChangeWidget(`id(`ch_plain), `Value, _plaindir);
UI::SetFocus (`disk);
}
/**
* Init function of a widget
* @param key string widget key
*/
void USBInit (string key) {
// detect disks
list<map<string,any> > usb_disks = DetectUSBDisk();
InitDiskWidget(usb_disks);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void USBStore (string key, map event) {
// build URL like this: usb:///openSUSE?device=/dev/sdb8&filesystem=auto
string query = sformat("device=%1&filesystem=%2",
(string)UI::QueryWidget (`id (`disk), `Value),
(string)UI::QueryWidget (`id (`fs), `Value));
string dir = (string)UI::QueryWidget (`id (`dir), `Value);
_plaindir = (boolean)UI::QueryWidget(`id(`ch_plain), `Value);
map parsed = $[
"scheme" : "usb",
"path" : dir,
"query" : query
];
_url = URL::Build (parsed);
y2milestone("New USB url: %1", URL::HidePassword(_url));
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> USBWidget ()
{
return $[
"widget" : `custom,
"custom_widget" : `VBox(
// combobox title
`Left(`ComboBox(`id (`disk), /*`opt(`hstretch),*/ _("&USB Mass Storage Device")
// the spacing is added to make the widget wider
+ " ")),
`Left(`ComboBox(`id (`fs), `opt(`editable), _("&File System"))),
`Left(`InputField(`id(`dir), _("Dire&ctory"))),
`Left(`CheckBox(`id(`ch_plain), _("&Plain RPM Directory")))
),
"init" : USBInit,
"store" : USBStore,
"help" : _("<p><big><b>USB Stick or Disk</b></big><br>
Select the USB device where the repository is located.
Use <b>Path to Directory</b> to specify the directory of the repository.
If the path is omitted the system will use the root directory of the disk.
If the directory contains just RPM packages without
any metadata (i.e. there is no product information) then check option
<b>Plain RPM Directory</b>.</p>")
// 'auto' is a value in the combo box widget, do not translate it!
+ _("<p>The file system which is used on the device will be automatically
detected if file system 'auto' is selected. If the detection fails or you
want to use a certain file system then select it from the list.</p>")
];
}
/**
* Init function of a widget
* @param key string widget key
*/
void DiskInit (string key) {
// refresh the cache
list<map<string,any> > disks = DetectHardDisk();
InitDiskWidget(disks);
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void DiskStore (string key, map event) {
// build URL like this: usb:///openSUSE?device=/dev/sdb8&filesystem=auto
string query = sformat("device=%1&filesystem=%2",
(string)UI::QueryWidget (`id (`disk), `Value),
(string)UI::QueryWidget (`id (`fs), `Value));
string dir = (string)UI::QueryWidget (`id (`dir), `Value);
_plaindir = (boolean)UI::QueryWidget(`id(`ch_plain), `Value);
map parsed = $[
"scheme" : "hd",
"path" : dir,
"query" : query
];
_url = URL::Build (parsed);
y2milestone("New Disk url: %1", URL::HidePassword(_url));
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> DiskWidget ()
{
return $[
"widget" : `custom,
"custom_widget" : `VBox(
// combobox title
`ComboBox(`id (`disk), `opt(`hstretch), _("&Disk Device")),
`ComboBox(`id (`fs), `opt(`editable), _("&File System")),
`InputField(`id(`dir), _("Dire&ctory")),
`Left(`CheckBox(`id(`ch_plain), _("&Plain RPM Directory")))
),
"init" : DiskInit,
"store" : DiskStore,
"help" : _("<p><big><b>Disk</b></big><br>
Select the disk where the repository is located.
Use <b>Path to Directory</b> to specify the directory of the repository.
If the path is omitted the system will use the root directory of the disk.
If the directory contains just RPM packages without
any metadata (i.e. there is no product information) then check option
<b>Plain RPM Directory</b>.</p>")
// 'auto' is a value in the combo box widget, do not translate it!
+ _("<p>The file system which is used on the device will be automatically
detected if file system 'auto' is selected. If the detection fails or you
want to use a certain file system then select it from the list.</p>")
];
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> IsoWidget () {
return $[
"widget" : `custom,
"custom_widget" : `VBox(
`HBox(
// text entry
`InputField (`id (`dir), `opt (`hstretch), _("&Path to ISO Image")),
`VBox (
`Label (""),
// push button
`PushButton (`id (`browse), Label::BrowseButton())
)
)
),
"init" : IsoInit,
"store" : IsoStore,
"handle" : IsoHandle,
"handle_events" : [ `browse ],
"validate_type" : `function,
"validate_function" : IsoValidate,
"help" : _("<p><big><b>Local ISO Image</b></big><br>
Use <b>Path to ISO Image</b> to specify the path to the
ISO image file.</p>")
];
}
void InitFocusServerInit (symbol server_type) {
switch (server_type) {
case (`ftp) : UI::SetFocus (`server);
break;
case (`http) : UI::SetFocus (`server);
break;
case (`https) : UI::SetFocus (`server);
break;
case (`samba) : UI::SetFocus (`server);
break;
}
}
// HTTP(s)/FTP/SMB/CIFS repository widget
// forward declarations
void ServerInit (string key);
void ServerStore (string key, map event);
// dialog contents for different views
term details_content =
`VBox(
`HBox (
`HSpacing (0.5),
// frame
`Frame (_("P&rotocol"), `ReplacePoint (`id (`rb_type_rp),
`Empty ())
),
`HSpacing( 0.5 )
),
`ReplacePoint (`id (`server_rp), `Empty ())
);
// input field label
term complete_content = `InputField(`id(`complete_url), `opt(`hstretch), _("&URL of the Repository"));
void ServerStoreParts()
{
symbol type = (symbol) UI::QueryWidget( `id( `rb_type), `CurrentButton );
map parsed = $[];
if ( type == `ftp )
parsed["scheme"] = "ftp";
else if ( type == `http )
parsed["scheme"] = "http";
else if ( type == `https )
parsed["scheme"] = "https";
else if ( type == `samba )
parsed["scheme"] = "smb";
boolean anonymous = (boolean)UI::QueryWidget (`id (`anonymous), `Value);
if ( !anonymous ) {
string user = (string)UI::QueryWidget (`id (`username), `Value);
string pass = (string)UI::QueryWidget (`id (`password ), `Value);
if (size (user) != 0)
parsed["user"] = user;
if (size (pass) != 0)
parsed["pass"] = pass;
}
string host = NormalizeHost((string)UI::QueryWidget (`id (`server), `Value));
string directory = (string)UI::QueryWidget (`id (`dir), `Value);
// is / in the host name?
integer pos = findfirstof(host, "/");
if (pos != nil)
{
// update the hostname and the directory,
// URL::Build return empty URL when the hostname is not valid
y2milestone("The hostname contains a path: %1", host);
string dir = substring(host, pos);
if (substring(dir, size(dir) - 1, 1) != "/" && substring(directory, 0, 1) != "/")
{
dir = dir + "/";
}
directory = dir + directory;
host = substring(host, 0, pos);
y2milestone("Updated hostname: %1, directory: %2", host, directory);
}
parsed["host"] = host;
if (type == `samba)
{
string share = (string)UI::QueryWidget (`id (`share), `Value);
directory = Slashed (share) + Slashed (directory);
}
else if (type != `ftp)
// FTP needs to distinguish absolute and relative path
{
// do not add the slash if host and directory is empty
// (avoid e.g. http:// -> http:/// when switching from the parts to the complete view)
if (host != "" || directory != "")
directory = Slashed (directory);
}
if (UI::WidgetExists (`id (`workgroup)))
{
string workgroup = (string)UI::QueryWidget (`id (`workgroup), `Value);
if (type == `samba && size (workgroup) > 0)
parsed["domain"] = workgroup;
}
parsed["path"] = directory;
// set HTTP/HTTPS port
if (type == `http || type == `https)
{
parsed["port"] = (string)UI::QueryWidget(`id(`port), `Value);
}
// do not log the entered password
y2milestone("Entered URL: %1", URL::HidePasswordToken(parsed));
_url = URL::Build (parsed);
y2milestone("URL::Build: %1", URL::HidePassword(_url));
if (UI::WidgetExists (`id (`ch_iso)))
{
boolean iso = (boolean)UI::QueryWidget (`id (`ch_iso), `Value);
if (iso)
_url = PosprocessISOURL (_url);
}
}
void ServerStoreComplete()
{
_url = (string)UI::QueryWidget(`id(`complete_url), `Value);
}
// use selected editing URL part, remember the value in case the URL is wrong
// and the dialog needs to displayed again
boolean editing_parts = true;
/**
* Handle function of a widget
* @param key string widget key
* @param event map which caused settings being stored
* @return always nil
*/
symbol ServerHandle (string key, map event) {
y2milestone("ServerHandle: %1, %2", key, event);
symbol current_type = (symbol)UI::QueryWidget(`id(`edit_type), `Value);
y2debug("Current edit type: %1", current_type);
any id = event["ID"]:nil;
if (is (id, symbol)
&& contains ([`http, `https, `ftp, `samba, `rb_type], (symbol)id) && current_type == `edit_url_parts)
{
symbol type = (symbol)UI::QueryWidget (`id (`rb_type), `CurrentButton);
string server = UI::WidgetExists (`id (`server))
? (string)UI::QueryWidget (`id (`server), `Value)
: "";
string dir = UI::WidgetExists (`id (`dir))
? (string)UI::QueryWidget (`id (`dir), `Value)
: "";
boolean anonymous = UI::WidgetExists (`id (`anonymous))
? (boolean)UI::QueryWidget (`id (`anonymous), `Value)
: false;
string username = UI::WidgetExists (`id (`username))
? (string)UI::QueryWidget (`id (`username), `Value)
: "";
string password = UI::WidgetExists (`id (`password))
? (string)UI::QueryWidget (`id (`password), `Value)
: "";
string port = UI::WidgetExists (`id (`port))
? (string)UI::QueryWidget (`id (`port), `Value)
: "";
term widget = `VBox (
`HBox(
// text entry
`InputField (`id (`server), `opt (`hstretch), _("Server &Name"), server),
(type == `http || type == `https) ?
`HBox(`HSpacing(1), `HSquash(`InputField (`id (`port), _("&Port"), port)))
: `Empty()
),
type == `samba
// text entry
? `InputField (`id (`share), `opt (`hstretch), _("&Share"))
: `Empty (),
type == `samba
? `VBox (
`InputField (`id (`dir), `opt (`hstretch),
// text entry
_("&Path to Directory or ISO Image"), dir),
// checkbox label
`Left (`CheckBox (`id (`ch_iso), _("ISO &Image")))
)
// text entry
: `InputField (`id (`dir), `opt (`hstretch), _("&Directory on Server"), dir),
`HBox (
`HSpacing (0.5),
// frame
`Frame (_("Au&thentication"), `VBox (
`Left (`CheckBox (`id (`anonymous), `opt (`notify),
// check box
_("&Anonymous"), anonymous)),
type == `samba
// text entry
? `InputField (`id (`workgroup), `opt (`hstretch),
_("&Workgroup or Domain"))
: `Empty (),
// text entry
`VSpacing(0.4),
`InputField(`id (`username), `opt(`hstretch), _("&User Name"), username),
// password entry
`Password (`id (`password), `opt(`hstretch), _("&Password"), password)
)),
`HSpacing (0.5)
)
);
UI::ReplaceWidget (`id (`server_rp), widget);
if (UI::WidgetExists(`id(`port)))
{
// maximum port number is 65535
UI::ChangeWidget(`id(`port), `InputMaxLength, 5);
// allow only numbers in the port spec
UI::ChangeWidget(`id(`port), `ValidChars, String::CDigit());
}
// update widget status
UI::ChangeWidget (`id (`username), `Enabled, !anonymous);
UI::ChangeWidget (`id (`password), `Enabled, !anonymous);
if (UI::WidgetExists (`id (`workgroup)))
UI::ChangeWidget (`id (`workgroup), `Enabled, !anonymous);
InitFocusServerInit ((symbol) id);
return nil;
}
if (event["ID"]:nil == `anonymous && current_type == `edit_url_parts)
{
boolean anonymous = (boolean)UI::QueryWidget (`id (`anonymous),
`Value);
UI::ChangeWidget (`id (`username), `Enabled, !anonymous);
UI::ChangeWidget (`id (`password), `Enabled, !anonymous);
if (UI::WidgetExists (`id (`workgroup)))
UI::ChangeWidget (`id (`workgroup), `Enabled, !anonymous);
return nil;
}
else if ((id == `edit_url_parts || id == `edit_complete_url) && event["EventReason"]:"" == "ValueChanged")
{
y2milestone("Changing dialog type");
// store the current values (note: the radio button just has been switched, compare to the opposite value!)
if (id == `edit_url_parts)
{
ServerStoreComplete();
}
else
{
ServerStoreParts();
}
editing_parts = (id == `edit_url_parts);
// reinitialize the dialog (set the current values)
ServerInit(nil);
}
}
/**
* Init function of a widget
* @param key string widget key
*/
void ServerInit (string key) {
// check the current edit type
symbol current_type = editing_parts ? `edit_url_parts : `edit_complete_url;
// set the stored value
UI::ChangeWidget(`id(`edit_type), `Value, current_type);
y2debug("Current edit type: %1", current_type);
UI::ReplaceWidget(`id(`edit_content), (current_type == `edit_url_parts) ? details_content : complete_content);
if (current_type == `edit_url_parts)
{
term protocol_box = `HBox (
`HStretch (),
// radio button
`RadioButton (`id (`ftp),`opt (`notify), _("&FTP")),
`HStretch(),
// radio button
`RadioButton (`id (`http),`opt (`notify), _("H&TTP")),
`HStretch()
);
if (_allow_https)
{
protocol_box = add (protocol_box,
// radio button
`RadioButton (`id (`https), `opt (`notify), _("HTT&PS"))
);
protocol_box = add (protocol_box, `HStretch ());
}
protocol_box = add (protocol_box,
// radio button
`RadioButton (`id (`samba),`opt (`notify), _("&SMB/CIFS"))
);
protocol_box = add (protocol_box, `HStretch ());
protocol_box = `RadioButtonGroup (`id (`rb_type), `opt (`notify),
protocol_box);
UI::ReplaceWidget (`id (`rb_type_rp), protocol_box);
boolean iso = IsISOURL (_url);
if (iso)
_url = PreprocessISOURL (_url);
map parsed = URL::Parse (_url);
symbol type = `ftp;
if ( parsed["scheme"]:"" == "http" )
type = `http;
else if ( parsed["scheme"]:"" == "https" )
type = `https;
else if ( parsed["scheme"]:"" == "smb" )
type = `samba;
UI::ChangeWidget (`id (`rb_type), `CurrentButton, type);
ServerHandle (key, $[ "ID" : `rb_type ]);
UI::ChangeWidget (`id (`server), `Value, parsed["host"]:"");
string dir = parsed["path"]:"";
if (type == `samba)
{
UI::ChangeWidget (`id (`ch_iso), `Value, iso);
list sharepath = regexptokenize (dir, "^/*([^/]+)(/.*)?$");
string share = sharepath[0]:"";
dir = sharepath[1]:"";
if (dir == nil)
dir = "/";
UI::ChangeWidget (`id (`workgroup), `Value, parsed["domain"]:"");
UI::ChangeWidget (`id (`share), `Value, share);
}
UI::ChangeWidget (`id (`dir), `Value, dir);
UI::ChangeWidget (`id (`username), `Value, parsed["user"]:"");
UI::ChangeWidget (`id (`password), `Value, parsed["pass"]:"");
boolean anonymous = ! (parsed["user"]:"" != "" || parsed["pass"]:"" != "");
y2milestone ("Anonymous: %1", anonymous);
UI::ChangeWidget (`id (`anonymous), `Value, anonymous);
if (anonymous)
{
UI::ChangeWidget (`id (`username), `Enabled, false);
UI::ChangeWidget (`id (`password), `Enabled, false);
if (UI::WidgetExists (`id (`workgroup)))
UI::ChangeWidget (`id (`workgroup), `Enabled, !anonymous);
}
// set HTTP/HTTPS port if it's specified
if (type == `http || type == `https)
{
string port_num = parsed["port"]:"";
if (port_num != nil && port_num != "")
{
UI::ChangeWidget(`id(`port), `Value, port_num);
}
}
InitFocusServerInit (type);
}
else
{
UI::ChangeWidget(`id(`complete_url), `Value, _url);
}
}
boolean ServerValidate (string key, map event) {
symbol current_type = (symbol)UI::QueryWidget(`id(`edit_type), `Value);
y2debug("Current edit type: %1", current_type);
if (current_type == `edit_url_parts)
{
string host = NormalizeHost ((string)UI::QueryWidget (`id (`server), `Value));
if (! Hostname::CheckFQ (host))
{
if (!IP::Check(host))
{
UI::SetFocus (`server);
Popup::Error(sformat("%1\n\n%2", Hostname::ValidFQ (), IP::Valid4()));
return false;
}
}
}
return true;
}
/**
* Store function of a widget
* @param key string widget key
* @param event map which caused settings being stored
*/
void ServerStore (string key, map event) {
y2debug("Server store: %1, %2", key, event);
symbol current_type = (symbol)UI::QueryWidget(`id(`edit_type), `Value);
y2debug("Current edit type: %1", current_type);
editing_parts = (current_type == `edit_url_parts);
if (editing_parts)
{
ServerStoreParts();
}
else
{
ServerStoreComplete();
}
}
/**
* Get widget description map
* @return widget description map
*/
map<string,any> ServerWidget () {
return $[
"widget" : `custom,
"custom_widget" : `VBox (
`RadioButtonGroup (`id (`edit_type),
`HBox (
`RadioButton(`id(`edit_url_parts), `opt(`notify), _("Edit Parts of the URL"), editing_parts),
`HSpacing(2),
`RadioButton(`id(`edit_complete_url), `opt(`notify), _("Edit Complete URL"), !editing_parts)
)
),
`VSpacing(0.3),
`ReplacePoint(`id(`edit_content), `Empty())
),
"init" : ServerInit,
"validate_type" : `function,
"validate_function" : ServerValidate,
"store" : ServerStore,
"handle" : ServerHandle,
// help text - server dialog
"help" : _("<p><big><b>Server and Directory</b></big><br>
Use <b>Server Name</b> and <b>Path to Directory or ISO Image</b>
to specify the NFS server host name and path on the server.
To enable authentication, uncheck <b>Anonymous</b> and specify the
<b>User Name</b> and the <b>Password</b>.</p>
<p>
For the SMB/CIFS repository, specify <b>Share</b> name and <b>Path to Directory
or ISO Image</b>.
If the location is a file holding an ISO image
of the media, set <b>ISO Image</b>.</p>
")
// help text - server dialog, there is a "Port" widget
+ _("<p>It is possible to set the <b>Port</b> number for a HTTP/HTTPS repository.
Leave it empty to use the default port.</p>
")
+ multi_cd_help,
];
}
/**
* Checks whether some network is available in the current moment,
* see the bug #170147 for more information.
*/
boolean IsAnyNetworkAvailable () {
boolean ret = false;
string command = "TERM=dumb /sbin/ip -o address show | grep inet | grep -v scope.host";
y2milestone("Running %1", command);
map cmd_run = (map) SCR::Execute(.target.bash_output, command);
y2milestone("Command returned: %1", cmd_run);
// command failed
if (cmd_run["exit"]:-1 != 0) {
// some errors were there, we don't know the status, rather return that it's available
// `grep` also returns non zero exit code when there is nothing to do...
if (cmd_run["stdout"]:"" != "") {
y2error("Checking the network failed");
ret = true;
}
// some devices are listed
} else if (cmd_run["stdout"]:"" != nil && cmd_run["stdout"]:"" != "") {
ret = true;
}
return ret;
}
/**
* Returns whether Community Repositories are defined in the control file.
*
* @return boolean whether defined
*/
boolean CRURLDefined () {
string link = ProductFeatures::GetStringFeature ("software", "external_sources_link");
y2debug ("software/external_sources_link -> '%1'", link);
if (link == nil || link == "") {
y2milestone ("No software/external_sources_link, community repos will be disabled");
return false;
} else {
return true;
}
}
term SelectRadioWidgetOpt (boolean download_widget) {
term contents = `HBox (`HStretch (), `VBox (
`RadioButtonGroup (`id (`type), `VBox (
`VStretch (),
// radio button
`Left (`RadioButton(`id(`slp), _("&Scan Using SLP..."))),
// bnc #428370, No need to offer community repositories if not defined
(CRURLDefined() ?
// radio button
`Left (`RadioButton(`id(`comm_repos), _("Commun&ity Repositories")))
:
`Empty()
),
`VSpacing(0.4),
// radio button
`Left (`RadioButton (`id (`specify_url),_("Specify &URL..."))),
`VSpacing(0.4),
// radio button
`Left (`RadioButton(`id(`ftp), _("&FTP..."))),
// radio button
`Left (`RadioButton(`id(`http), _("&HTTP..."))),
// radio button
`Left (`RadioButton(`id(`https), _("HTT&PS..."))),
// radio button
`Left (`RadioButton(`id(`samba), _("&SMB/CIFS"))),
// radio button
`Left (`RadioButton(`id(`nfs), _("&NFS..."))),
// radio button
`Left (`RadioButton(`id(`cd), _("&CD..."))),
// radio button
`Left (`RadioButton(`id(`dvd), _("&DVD..."))),
// radio button
`Left (`RadioButton(`id(`hd), _("&Hard Disk..."))),
// radio button
`Left (`RadioButton(`id(`usb), _("&USB Mass Storage (USB Stick, Disk)..."))),
// radio button
`Left (`RadioButton(`id(`local_dir), _("&Local Directory..."))),
// radio button
`Left (`RadioButton(`id(`local_iso), _("&Local ISO Image..."))),
// check box
(download_widget) ? `VBox(
`VSpacing(2),
`Left (`CheckBox (`id (`download_metadata), _("&Download repository description files"), _download_metadata))
)
: `Empty(),
`VStretch ()
))), `HStretch ()
);
if (! IsAnyNetworkAvailable()) {
y2milestone ("Network is not available, skipping all Network-related options...");
contents = `HBox (`HStretch (), `VBox (
`RadioButtonGroup (`id (`type), `VBox (
`VStretch (),
// radio button
`Left (`RadioButton (`id (`specify_url),_("Specify &URL..."))),
`VSpacing(0.4),
// radio button
`Left (`RadioButton(`id(`cd), _("&CD..."))),
// radio button
`Left (`RadioButton(`id(`dvd), _("&DVD..."))),
// radio button
`Left (`RadioButton(`id(`hd), _("&Hard Disk..."))),
// radio button
`Left (`RadioButton(`id(`usb), _("&USB Stick or Disk..."))),
// radio button
`Left (`RadioButton(`id(`local_dir), _("&Local Directory..."))),
// radio button
`Left (`RadioButton(`id(`local_iso), _("&Local ISO Image..."))),
// check box
(download_widget) ? `VBox(
`VSpacing(2),
`Left (`CheckBox (`id (`download_metadata), _("&Download repository description files"), _download_metadata))
)
: `Empty(),
`VStretch ()
))), `HStretch ()
);
} else {
y2milestone("Network is available, allowing Network-related options...");
}
return contents;
}
term SelectRadioWidget()
{
return SelectRadioWidgetOpt(false);
}
term SelectRadioWidgetDL()
{
return SelectRadioWidgetOpt(true);
}
string SelectWidgetHelp () {
// help text
string help_text = _("<p><big><b>Media Type</b></big><br>
The software repository can be located on CD, on a network server,
or on the hard disk.</p>");
// help, continued
help_text = help_text + _("<p>
To add <b>CD</b> or <b>DVD</b>,
have the product CD set or the DVD available.</p>");
// help, continued
help_text = help_text + _("<p>
The product CDs can be copied to the hard disk.
Insert the path where the first
CD is located, for example, /data1/<b>CD1</b>.
Only the base path is required if all CDs are copied
into one directory.</p>
");
// help, continued
help_text = help_text + _("<p>
Network installation requires a working network connection.
Specify the directory where the packages from
the first CD are located, such as /data1/CD1.</p>
");
return help_text;
}
boolean SelectValidate (string key, map event) {
symbol selected = (symbol)UI::QueryWidget (`id (`type), `CurrentButton);
if (selected == nil)
{
// error popup
Popup::Message (_("Select the media type."));
return false;
}
if (selected == `cd || selected == `dvd)
{
Pkg::SourceReleaseAll();
string msg = selected == `cd
? _("Insert the add-on product CD")
: _("Insert the add-on product DVD");
// reset the device name
cd_device_name = "";
// ask for a medium
map<string,any> ui_result = SourceManager::AskForCD (msg);
if (! ui_result["continue"]:false)
return false;
string cd_device = ui_result["device"]:"";
if (cd_device != nil && cd_device != "")
{
y2milestone("Selected CD/DVD device: %1", cd_device);
cd_device_name = cd_device;
}
}
else if (selected == `usb)
{
list<map<string,any> > usb_disks = DetectUSBDisk();
if (size(usb_disks) == 0)
{
Report::Error(_("No USB disk was detected."));
return false;
}
}
return true;
}
symbol SelectHandle (string key, map event) {
// reset the preselected URL when going back
if (event["ID"]:nil == `back)
{
_url = "";
}
if (! (event["ID"]:nil == `next || event["ID"]:nil == `ok))
return nil;
symbol selected = (symbol)UI::QueryWidget (`id (`type), `CurrentButton);
// TODO: disable "download" option when CD or DVD source is selected
if (selected == nil)
return nil;
if (selected == `slp || selected == `cd || selected == `dvd || selected == `comm_repos)
return `finish;
}
void SelectStore (string key, map event) {
_url = "";
_plaindir = false;
_repo_name = "";
symbol selected = (symbol)UI::QueryWidget (`id (`type), `CurrentButton);
if (contains ([`ftp, `http, `https, `samba, `nfs, `cd, `dvd, `usb, `hd,
`local_dir, `specify_url, `slp, `local_iso, `comm_repos], selected))
{
if ( selected == `ftp ) _url = "ftp://";
else if ( selected == `http ) _url = "http://";
else if ( selected == `https ) _url = "https://";
else if ( selected == `samba ) _url = "smb://";
else if ( selected == `nfs ) _url = "nfs://";
else if ( selected == `cd || selected == `dvd)
{
_url = (selected == `cd) ? "cd:///" : "dvd:///";
if (cd_device_name != "")
{
_url = _url + "?devices=" + URLRecode::EscapeQuery(cd_device_name);
}
}
else if ( selected == `hd ) _url = "hd://";
else if ( selected == `usb ) _url = "usb://";
else if ( selected == `local_dir ) _url = "dir://";
else if ( selected == `local_iso ) _url = "file://";
else if ( selected == `slp ) _url = "slp://";
else if ( selected == `comm_repos ) _url = "commrepos://";
}
else
{
y2internal("Unexpected repo type %1", selected);
}
}
void SelectInit (string key) {
symbol current = nil;
if (_url == "ftp://") current = `ftp;
else if ( _url == "http://" ) current = `http;
else if ( _url == "https://" ) current = `https;
else if ( _url == "smb://" ) current = `samba;
else if ( _url == "nfs://" ) current = `nfs;
else if ( _url == "nfs4://" ) current = `nfs;
else if ( _url == "cd:///" ) current = `cd;
else if ( _url == "dvd:///" ) current = `dvd;
else if ( _url == "hd://" ) current = `hd;
else if ( _url == "usb://" ) current = `usb;
else if ( _url == "dir://" ) current = `local_dir;
else if ( _url == "file://" ) current = `local_iso;
else if ( _url == "slp://" ) current = `slp;
else if ( _url == "commrepos://" ) current = `comm_repos;
else
{
y2warning ("Unknown URL scheme '%1'", _url);
current = `specify_url;
}
if (current != nil)
{
UI::ChangeWidget (`id (`type), `CurrentButton, current);
}
}
map<string,any> SelectWidget () {
return $[
"widget" : `func,
"widget_func" : SelectRadioWidget,
"init" : SelectInit,
"help" : SelectWidgetHelp (),
"validate_type" : `function,
"validate_function" : SelectValidate,
"store" : SelectStore,
"handle" : SelectHandle,
];
}
global boolean GetDownloadOption()
{
return _download_metadata;
}
global void SetDownloadOption(boolean download)
{
_download_metadata = download;
}
void SelectStoreDl (string key, map event)
{
SelectStore(key, event);
_download_metadata = ((boolean)UI::QueryWidget (`id (`download_metadata), `Value));
}
string SelectWidgetHelpDl()
{
return _("<p><b>Download Files</b><br>
Each repository has description files which describe content of the repository.
Check the <b>Download repository description files</b> to download the files
when closing this YaST module. If the option is unchecked, YaST will
automatically download the files when it needs them later. </p>
");
}
map<string,any> SelectWidgetDL () {
return $[
"widget" : `func,
"widget_func" : SelectRadioWidgetDL,
"init" : SelectInit,
"help" : SelectWidgetHelp() + SelectWidgetHelpDl(),
"validate_type" : `function,
"validate_function" : SelectValidate,
"store" : SelectStoreDl,
"handle" : SelectHandle,
];
}
// general data
/**
* Individual widgets
*/
map<string,map<string,any> > _widgets = $[];
/**
* Get individual widgets
* @return individual widgets
*/
map<string,map<string,any> > Widgets () {
if (size (_widgets) == 0)
_widgets = $[
"repo_name" : RepoNameWidget(),
"service_name" : ServiceNameWidget(),
"url" : PlainURLWidget (),
"nfs" : NFSWidget (),
"cd" : CDWidget (),
"dvd" : CDWidget (),
"hd" : DiskWidget (),
"usb" : USBWidget (),
"dir" : DirWidget (),
"file" : IsoWidget (),
"http" : ServerWidget (),
"https" : ServerWidget (),
"ftp" : ServerWidget (),
"smb" : ServerWidget (),
"cifs" : ServerWidget (),
"select" : SelectWidget (),
"select_dl" : SelectWidgetDL (),
];
return _widgets;
}
/**
* Captions for individual protocols
*/
map<string,string> _caption = $[
// label / dialog caption
"url" : _("Repository URL"),
// label / dialog caption
"nfs" : _("NFS Server"),
// label / dialog caption
"cd" : _("CD or DVD Media"),
// label / dialog caption
"dvd" : _("CD or DVD Media"),
// label / dialog caption
"hd" : _("Hard Disk"),
// label / dialog caption
"usb" : _("USB Stick or Disk"),
// label / dialog caption
"dir" : _("Local Directory"),
// label / dialog caption
"file" : _("Local ISO Image"),
// label / dialog caption
"http" : _("Server and Directory"),
// label / dialog caption
"https" : _("Server and Directory"),
// label / dialog caption
"ftp" : _("Server and Directory"),
// label / dialog caption
"smb" : _("Server and Directory"),
// label / dialog caption
"cifs" : _("Server and Directory"),
];
// general functions
/**
* Get contents of a popup for specified protocol
* @param proto string protocol to display popup for
* @return term popup contents
*/
term PopupContents (string proto, boolean repository) {
return `VBox (
`HSpacing (50),
// label
`Heading(_caption[proto]:""),
repository ? "repo_name" : "service_name",
`VSpacing(0.4),
proto,
`VSpacing(0.4),
PopupButtons ()
);
};
string EditDisplayInt(boolean repository)
{
string proto = URLScheme (_url);
y2milestone ("Displaying %1 popup for protocol %2", repository ? "repository" : "service", proto);
list<map<string,any> > w = CWM::CreateWidgets ([ (repository ? "repo_name" : "service_name"), proto], Widgets ());
y2milestone("w: %1", w);
term contents = PopupContents (proto, repository);
contents = CWM::PrepareDialog (contents, w);
UI::OpenDialog (contents);
symbol ret = CWM::Run (w, $[]);
y2milestone ("Ret: %1", ret);
UI::CloseDialog ();
if (ret == `ok)
return GetURL ();
else
return "";
}
string EditDisplay()
{
return EditDisplayInt(true);
}
string EditDisplayService()
{
return EditDisplayInt(false);
}
/**
* URL editation popup
* @param url string url URL to edit
* @return string modified URL or empty string if canceled
*/
global string EditPopup (string url) {
SetURL (url);
return EditDisplay();
}
/**
* URL editation popup
* @param url string url URL to edit
* @return string modified URL or empty string if canceled
*/
global string EditPopupService (string url) {
SetURL (url);
return EditDisplayService();
}
/**
* URL editation popup, allows setting plaindir type
* @param url string url URL to edit
* @param plaindir_type set to true if the repository is plaindor
* @return string modified URL or empty string if canceled
*/
global string EditPopupType (string url, boolean plaindir_type)
{
SetURLType(url, plaindir_type);
return EditDisplay();
}
/**
* URL editation popup without the HTTPS option
* @param url string url URL to edit
* @return string modified URL or empty string if canceled
*/
global string EditPopupNoHTTPS (string url) {
_allow_https = false;
string ret = EditPopup (url);
_allow_https = true;
return ret;
}
/**
* Sample implementation of URL selection dialog
* @return symbol for wizard sequencer
*/
global symbol EditDialogProtocol(string proto)
{
y2milestone ("Displaying dialog for protocol %1", proto);
string caption = _caption[proto]:"";
return CWM::ShowAndRun ($[
"widget_names" : ["repo_name", proto],
"widget_descr" : Widgets (),
"contents" : `HVCenter(`MinWidth( 65, `VBox ("repo_name", proto ) ) ),
"caption" : caption,
"back_button" : Label::BackButton (),
"next_button" : Label::NextButton (),
"fallback_functions" : $[]
]);
}
/**
* Sample implementation of URL selection dialog
* @return symbol for wizard sequencer
*/
global symbol EditDialogProtocolService(string proto)
{
y2milestone ("Displaying service dialog for protocol %1", proto);
string caption = _caption[proto]:"";
return CWM::ShowAndRun ($[
"widget_names" : ["service_name", proto],
"widget_descr" : Widgets (),
"contents" : `HVCenter(`MinWidth( 65, `VBox ("service_name", proto ) ) ),
"caption" : caption,
"back_button" : Label::BackButton (),
"next_button" : Label::NextButton (),
"fallback_functions" : $[]
]);
}
/**
* Sample implementation of URL selection dialog
* @return symbol for wizard sequencer
*/
global symbol EditDialog () {
string proto = URLScheme (_url);
return EditDialogProtocol(proto);
}
/**
* URL editation popup with the HTTPS option
* @return string modified URL or empty string if canceled
*/
global string TypePopup () {
list<map<string,any> > w = CWM::CreateWidgets (["select"], Widgets ());
term contents = PopupContents ("select", true);
contents = CWM::PrepareDialog (contents, w);
UI::OpenDialog (contents);
symbol ret = CWM::Run (w, $[]);
y2milestone ("Ret: %1", ret);
UI::CloseDialog ();
return "";
/*
if (ret == `ok)
return GetURL ();
else
return "";
*/
}
/**
* Sample implementation of URL type selection dialog
* @return symbol for wizard sequencer
*/
global symbol TypeDialog () {
y2milestone ("Running repository type dialog");
// dialog caption
string caption = _("Media Type");
symbol ret = CWM::ShowAndRun ($[
"widget_names" : ["select"],
"widget_descr" : Widgets (),
"contents" : `VBox ( "select" ),
"caption" : caption,
"back_button" : Label::BackButton (),
"next_button" : Label::NextButton (),
"fallback_functions" : $[]
]);
y2milestone ("Type dialog returned %1", ret);
return ret;
}
/**
* Sample implementation of URL type selection dialog
* @return symbol for wizard sequencer
*/
global map<string,any> TypeDialogDownloadOpt() {
y2milestone ("Running repository type dialog with download option");
// dialog caption
string caption = _("Media Type");
symbol ui = CWM::ShowAndRun ($[
"widget_names" : ["select_dl"],
"widget_descr" : Widgets (),
"contents" : `VBox ( "select_dl" ),
"caption" : caption,
"back_button" : Label::BackButton (),
"next_button" : Label::NextButton (),
"fallback_functions" : $[]
]);
map<string,any> ret = $[ "ui" : ui, "download" : _download_metadata ];
y2milestone ("Type dialog returned %1", ret);
return ret;
}
} // EOF
ACC SHELL 2018