ACC SHELL

Path : /usr/share/YaST2/include/bootloader/routines/
File Upload :
Current File : //usr/share/YaST2/include/bootloader/routines/section_widgets.ycp

/**
 * File:
 *      include/bootloader/routines/widgets.ycp
 *
 * Module:
 *      Bootloader installation and configuration
 *
 * Summary:
 *      Common widgets for being used by several bootloaders
 *
 * Authors:
 *      Jiri Srain <jsrain@suse.cz>
 *      Olaf Dabrunz <od@suse.de>
 *      Josef Reidinger <jreidinger@suse.cz>
 *
 * $Id: section_widgets.ycp 59979 2009-12-07 13:27:59Z juhliarik $
 *
 */


{

textdomain "bootloader";

import "CWM";
import "Initrd";
import "Label";
import "Mode";
import "Storage";
import "StorageDevices";
import "Bootloader";
import "BootStorage";
import "Popup";
import "FileUtils";


include "bootloader/routines/helps.ycp";
include "bootloader/routines/section_helps.ycp";

boolean validate_image(string widget, map event){
  string value = (string) UI::QueryWidget(`id(widget),`Value);
  if (value == ""){
      Popup::Error(_("Image section must have specified kernel image"));
      UI::SetFocus(`id(widget));
      return false;
  }
  if (!Mode::installation() && !Mode::repair()){
    if (!FileUtils::Exists(value)){
      if (!Popup::YesNo(_("Image file doesn't exist now. Do you really want use it?"))){
        UI::SetFocus(`id(widget));
        return false;
      }
    }
  }

  return true;
}

boolean validate_initrd(string widget, map event){
  string value = (string) UI::QueryWidget(`id(widget),`Value);
  if (!Mode::installation() && !Mode::repair()){
    if (!FileUtils::Exists(value)){
      if (!Popup::YesNo(_("Initrd file doesn't exist now. Do you really want use it?"))){
        UI::SetFocus(`id(widget));
        return false;
      }
    }
  }
  return true;
}

map<string,boolean (string, map)> validation_map = $[
  "image" : validate_image,
  "initrd" : validate_initrd,
];

/**
 * Init function for widget value
 * @param widget any id of the widget
 */
void SectionOptionInit (string widget) {
    UI::ChangeWidget (`id (widget), `Value,
	BootCommon::current_section[widget]:"");
}

/**
 * Store function of a widget
 * @param widget any widget key
 * @param event map event description of event that occured
 */
void SectionOptionStore (string widget, map event) {
    BootCommon::current_section[widget]
	= UI::QueryWidget (`id (widget), `Value); 
}

/**
 * Map of fallback handlers for events on sections
 */
map<string,any> section_handlers = $[
    "init" : SectionOptionInit,
    "store" : SectionOptionStore,
];


void InitSectionBool(string widget){
  boolean value = BootCommon::current_section[widget]:"false" == "true";
  UI::ChangeWidget (`id (widget), `Value, value);
}

void StoreSectionBool(string widget, map event){
  boolean value = (boolean)UI::QueryWidget (`id (widget), `Value);
  BootCommon::current_section[widget] = value ? "true" : "false";
}

map<string,any> SectionCheckBoxWidget( string name){
  return $[
    "label" : section_descriptions[name]:name,
    "widget" : `checkbox,
    "help" : section_help_messages[name]:"",
    "init" : InitSectionBool,
    "store" : StoreSectionBool
  ];
}


void InitEnableSelinux (string widget)
{
    string append = BootCommon::current_section["append"]:"";
    if ((append != "") && (BootCommon::current_section["type"]:"" == "image"))
    {
	if ((search(append, "security=selinux") !=nil) && (search(append, "selinux=1") != nil) 
	    && (search(append, "enforcing=0") != nil))
	    UI::ChangeWidget (`id (widget), `Value, true);
	else
	    UI::ChangeWidget (`id (widget), `Value, false);
    } else {
	UI::ChangeWidget (`id (widget), `Value, false);
    }

    if ((BootCommon::current_section["type"]:"" != "image") || 
	(BootCommon::current_section["original_name"]:"" == "failsafe"))
	UI::ChangeWidget (`id (widget), `Enabled, false);
}

string add_selinux_append (string append)
{
    string ret = append;
    if ((search(append, "security=selinux") ==nil))
	ret = ret + " security=selinux";
    if ((search(append, "selinux=1") ==nil))
	ret = ret + " selinux=1";
    if ((search(append, "enforcing=0") ==nil))
	ret = ret + " enforcing=0";
    return ret;
}

string delete_selinux_append (string append)
{
    string ret = append;
    list <string> l_append = splitstring(append, " ");
    l_append = filter(string v, l_append,
    {
	if ((v != "") && (tolower(v)!="security=selinux")
	    &&(tolower(v)!="selinux=1") && (tolower(v)!="enforcing=0"))
	     return true;
    });
    ret = mergestring(l_append, " ");
    return ret;
}

void StoreEnableSelinux(string widget, map event)
{
//    string append = BootCommon::current_section["append"]:"";
    string append = (string)UI::QueryWidget (`id ("append"), `Value);
    boolean value = (boolean)UI::QueryWidget (`id (widget), `Value);
    if (value)
    {
	append = add_selinux_append(append);
	BootCommon::enable_selinux = true;
    } else {
	append = delete_selinux_append(append);
	BootCommon::enable_selinux = false;
    }
    BootCommon::current_section["append"] = append;
}

symbol HandleEnableSelinux (string widget, map event) 
{
    boolean value = (boolean)UI::QueryWidget (`id (widget), `Value);
    //string append = BootCommon::current_section["append"]:"";
    string append = (string)UI::QueryWidget (`id ("append"), `Value);
    if (value)
    {
	UI::ChangeWidget (`id ("append"), `Value, add_selinux_append(append));
    } else {
	UI::ChangeWidget (`id ("append"), `Value, delete_selinux_append(append));
    }
    return nil;
}
map <string,any> EnableSelinux(){
  return $[
    "label" : _("Enable &SELinux"),
    "widget" : `checkbox,
    "help" : section_help_messages["enable_selinux"]:"",
    "init" : InitEnableSelinux,
    "handle": HandleEnableSelinux,
    "opt"   : [`notify],
    "store" : StoreEnableSelinux,
  ];
}


map<string,any> SectionTextFieldWidget( string name){
  map<string,any> ret = $[
    "label" : section_descriptions[name]:name,
    "widget" : `textentry,
    "help" : section_help_messages[name]:"",
  ];

  if (haskey(validation_map,name)){
    ret["validate_type"] = `function;
    ret["validate_function"] = validation_map[name]:nil;//nil cannot happen
  }

  return ret;
}

/**
 * Handle function of a widget (InputField + browse button)
 * @param widget any widget key
 * @param event map event description of event that occured
 * @return symbol nil
 */
symbol HandleSectionBrowse (string widget, map event) {
    string current = (string)UI::QueryWidget (`id (widget), `Value);
    if (current == "" || current == nil)
      current = "/boot";
    // file open popup caption
    current = UI::AskForExistingFile (current, "*", _("Select File"));
    if (current != nil)
	UI::ChangeWidget (`id (widget), `Value, current);
    return nil;
}

/**
 * Handle function of a widget (InputField + browse button)
 * Asks for directory instead file
 * @param widget any widget key
 * @param event map event description of event that occured
 * @return symbol nil
 */
symbol HandleSectionBrowseDirectory (string widget, map event) {
    string current = (string)UI::QueryWidget (`id (widget), `Value);
    // file open popup caption
    current = UI::AskForExistingFile (current, "*", _("Select File"));
    if (current != nil)
	UI::ChangeWidget (`id (widget), `Value, current);
    return nil;
}

/**
 * Generic widget of a inputfield + browse button
 * Use validation function from  validation_map
 * if it is necessary create own definition of widget
 * @param string lable of widget
 * @param string help text for widget
 * @param string id of widget
 * @return map<string,any> CWS widget
 */
map<string,any> SectionInputFieldBrowseWidget(string id){
  string browse = "browse" + id;
  map<string,any> ret = $[
    "widget" : `custom,
    "custom_widget" : `HBox(
	     `Left(`InputField(`id(id),`opt(`hstretch),
                    section_descriptions[id]:id)),
              `VBox(
                 `Label(""),
                 `PushButton(`id(browse),`opt(`notify), Label::BrowseButton())
              )
            ),
    "init" : SectionOptionInit,
    "store" : SectionOptionStore,
    "handle" : HandleSectionBrowse,
    "handle_events" : [browse],
    "help" : section_help_messages[id]:id,
  ];
  if (haskey(validation_map,id)){
    ret["validate_type"] = `function;
    ret["validate_function"] = validation_map[id]:nil;//nil cannot happen
  }

  return ret;
}

map<string,any> SectionInputFieldBrowseDirectoryWidget(string id){
  map<string,any> ret = SectionInputFieldBrowseWidget(id);
  ret["handle"] = HandleSectionBrowseDirectory;
  return ret;
}


void InitSectionInt(string widget){
  integer value = tointeger(BootCommon::current_section[widget]:"0");
    UI::ChangeWidget (`id (widget), `Value, value);
}

void StoreSectionInt(string widget, map event){
  integer value = (integer)UI::QueryWidget (`id (widget), `Value);
  BootCommon::current_section[widget] = tostring(value);
}

map<string,any> SectionIntFieldWidget( string name,
                                      integer min, integer max){
  map<string,any> ret = $[
    "label" : section_descriptions[name]:name,
    "widget" : `intfield,
    "help" : section_help_messages[name]:name,
    "init" : InitSectionInt,
    "store" : StoreSectionInt
  ];
  if ( min != nil )
    ret["minimum"] = min;
  if ( max != nil )
    ret["maximum"] = max;

  return ret;

}
/**
 * Validate function of the name widget
 * @param widget any widget key
 * @param event map event description of event that occured
 * @return boolean true if widget settings ok
 */
boolean SectionNameValidate (string widget, map event) {
    string bl = Bootloader::getLoaderType();

    list<string> existing = [];
    foreach (map<string,any> s, BootCommon::sections, {
	existing = add (existing, s["name"]:"");
    });
    existing = (list<string>)filter (string l, existing, {
	return l != BootCommon::current_section_name;
    });
    existing = (list<string>)add (existing, "");
    string new = (string)UI::QueryWidget (`id (widget), `Value);

    if (contains (existing, new))
    {
	usedNameErrorPopup ();
	return false;
    }

    // bnc#456362 filter out special chars like diacritics china chars etc.
    if ((Mode::normal()) && (bl == "grub"))
    {
	string filtered_new = 
	     filterchars (new, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 /\\_.-()");

	if (filtered_new != new)
	{
	    Report::Error (_("The name includes unallowable char(s)"));
	    return false;
	}

    }
    return true;
}

/**
 * Store function of the name widget
 * @param widget any widget key
 * @param event map event description of event that occured
 */
void SectionNameStore (string widget, map event) {
    string value = (string)UI::QueryWidget (`id (widget), `Value);

    //check if we need change default value in globals
    if ( BootCommon::globals["default"]:nil
        == BootCommon::current_section[widget]:""){
      BootCommon::globals["default"] = value;
    }

    BootCommon::current_section[widget] = value;
}


/**
 * Init function of the root device widget
 * @param widget any id of the widget
 */
void RootDeviceInit (string widget) {
    y2milestone ("RootDeviceInit: %1", widget);
    list<string> available = BootStorage::getPartitionList (`root, Bootloader::getLoaderType());
    // if we mount any of these devices by id, label etc., we add a hint to
    // that effect to the item
    y2milestone ("RootDeviceInit: getHintedPartitionList for %1", available);
    available = BootStorage::getHintedPartitionList (available);
    UI::ChangeWidget (`id (widget), `Items, available);
    UI::ChangeWidget (`id (widget), `Value,
	(BootStorage::getHintedPartitionList ([BootCommon::current_section[widget]:""]))[0]:"");
}

/**
 * Store function of the root device widget
 * @param widget any widget key
 * @param event map event description of event that occured
 */
void RootDeviceStore (string widget, map event) {
    BootCommon::current_section[widget]
	= (splitstring( (string)UI::QueryWidget (`id (widget), `Value), " "))[0]:"";
}

/**
 * Handle function of the root device widget
 * @param widget any widget key
 * @param event map event description of event that occured
 * @return symbol to return to wizard sequencer, or nil
 */
symbol RootDeviceHandle (string widget, map event) {
    if (event["EventReason"]:nil != "ValueChanged")
	return nil;
    // append hint string when user changed root device
    string current
	= (splitstring( (string)UI::QueryWidget (`id (widget), `Value), " "))[0]:"";
    // check against the list of existing partitions
    list<string> available = BootStorage::getPartitionList (`root, Bootloader::getLoaderType());
    if (contains(available, current))
	UI::ChangeWidget (`id (widget), `Value,
	    (BootStorage::getHintedPartitionList ([current]))[0]:"");
    return nil;
}

/**
 * Init function of widget
 * @param widget any id of the widget
 */
void VgaModeInit (string widget) {
    list<map> vga_modes = Initrd::VgaModes ();
    list items = maplist (map m, vga_modes, {
	return `item (`id (sformat ("%1",  tohexstring(m["mode"]:0))),
	    // combo box item
	    // %1 is X resolution (width) in pixels
	    // %2 is Y resolution (height) in pixels
	    // %3 is color depth (usually one of 8, 16, 24, 32)
	    // %4 is the VGA mode ID (hexadecimal number)
	    sformat (_("%1x%2, %3 bits (mode %4)"),
		m["width"]:0, m["height"]:0, m["color"]:0,  tohexstring(m["mode"]:0)));
    });
    items = prepend(items,`item(`id("ask"), _("Ask for resolution during boot.")));
    items = prepend(items,`item(`id("extended"), _("Standard 8-pixel font mode.")));
    // item of a combo box
    items = prepend (items, `item (`id ("normal"), _("Text Mode")));
    UI::ChangeWidget (`id (widget), `Items, items);
    SectionOptionInit (widget);
}

/**
 * Init function of widget
 * @param widget any id of the widget
 */
void ChainloaderInit (string widget) {
    list<string> available = BootStorage::getPartitionList (`boot_other, Bootloader::getLoaderType());
    UI::ChangeWidget (`id (widget), `Items, available);
    SectionOptionInit (widget);
}

/**
 * Widget for selecting section type
 * @return term widget
 */
term SectionTypesWidget () {
    integer count = 0;
    term contents = `VBox ();
    if (BootCommon::current_section_name != "")
    {
	contents = add (contents, `Left (`RadioButton (`id ("clone"),
	    // radio button
	    _("Clone Selected Section"), true)));
	count = count + 1;
    }
    list<string> section_types = Bootloader::blsection_types();
    map<string,string> section_types_descr = $[
	// radio button
	"image" : _("Image Section"),
	// radio button
	"xen" : _("Xen Section"),
	// radio button (don't translate 'chainloader')
	"other" : _("Other System (Chainloader)"),
	// radio button
	"menu"  : _("Menu Section"),
	// radio button
	"dump"  : _("Dump Section"),
    ];
    foreach (string t, section_types, {
	if (count > 0)
	    contents = add (contents, `VSpacing (0.4));
	count = count + 1;
	contents = add (contents, `Left (`RadioButton (`id (t),
	    section_types_descr[t]:t, count == 1)));
    });
    // frame
    contents = `Frame (_("Section Type"), `VBox (
	`VSpacing (1),
	`HBox (
	    `HSpacing (2),
	    `RadioButtonGroup (`id (`sect_type), contents),
	    `HSpacing (2)
	),
	`VSpacing (1)
    ));
    return contents;
}

/**
 * Handle function of a widget
 * @param widget string widget key
 * @param event map event description of event that occured
 * @return symbol to return to wizard sequencer, or nil
 */
symbol SectionTypeHandle (string widget, map event) {
    if (event["ID"]:nil != `next)
	return nil;
    string selected = (string)
	UI::QueryWidget (`id (`sect_type), `CurrentButton);
    string original_name = selected;
    if (original_name == "image")
	original_name = "linux";
    if (selected != "clone")
    {	
	BootCommon::current_section = $[
	    "type" : selected,
	    "original_name" : original_name,
	];
    }
    else
    {
	BootCommon::current_section["name"] = "";
	// fix the problem with missing YaST commnet in menu.lst
	// it seems be correct if original_name stay same...
	BootCommon::current_section["original_name"] = "";
	BootCommon::current_section["__auto"] = false;
	// fix for problem with cloning section
	if (haskey(BootCommon::current_section,"lines_cache_id"))
		BootCommon::current_section = remove(BootCommon::current_section, "lines_cache_id");
    }
    y2milestone ("Added section template: %1", BootCommon::current_section);
    return nil;
}



/**
 * Cache for CommonSectionWidgets
 */
map<string,map<string,any> > _common_section_widgets = nil;

/**
 * Get common widgets for loader sections
 * @return a map describing common loader section related widgets
 */
map<string,map<string,any> > CommonSectionWidgets () {

    if (_common_section_widgets == nil)
    {
	  _common_section_widgets = $[
	    "name" : $[
		// text entry
		"label" : _("Section &Name"),
		"widget" : `textentry,
		"validate_type" : `function,
		"validate_function" : SectionNameValidate,
		"store" : SectionNameStore,
		"help" : SectionNameHelp (),
	    ],
	    "image" : SectionInputFieldBrowseWidget("image"),
	    "initrd" : SectionInputFieldBrowseWidget("initrd"),
	    "xen" : SectionInputFieldBrowseWidget("xen"),
	    "target" : SectionInputFieldBrowseDirectoryWidget("target"),
	    "parmfile" : SectionInputFieldBrowseWidget("parmfile"),
	    "dumpto" : $[ //FIXME when exist browse device use it
		"label" : section_descriptions["dumpto"]:"dumpto",
		"widget" : `textentry,
		"help" : section_help_messages["dumpto"]:""
	    ],
	    "dumptofs" : $[ //FIXME when exist browse device use it
		"label" : section_descriptions["dumptofs"]:"dumptofs",
		"widget" : `textentry,
		"help" : section_help_messages["dumptofs"]:""
	    ],
	    "root" : $[
		"widget" : `combobox,
		// combo box
		"label" : section_descriptions["root"]:"root",
		"opt" : [ `editable, `hstretch, `notify ],
		"init" : RootDeviceInit,
		"handle" : RootDeviceHandle,
		"store" : RootDeviceStore,
		"help" : section_help_messages["root"]:"",
	    ],
	    "vgamode" : $[
		"widget" : `combobox,
		// combo box
		"label" : section_descriptions["vgamode"]:"vgamode",
		"opt" : [ `editable, `hstretch ],
		"init" : VgaModeInit,
		"help" : section_help_messages["vgamode"]:"",
	    ],
	    "append" : SectionTextFieldWidget("append"),
	    "xen_append" : SectionTextFieldWidget("xen_append"),
	    "configfile" : SectionTextFieldWidget("configfile"),
	    "list" : SectionTextFieldWidget("list"),
	    "chainloader" : $[
		"widget" : `combobox,
		"init" : ChainloaderInit,
		"help" : section_help_messages["chainloader"]:"",
                "label" : section_descriptions["chainloader"]:"chainloader",
		"opt" : [ `editable, `hstretch ],
	    ],
	    "section_type" : $[
		"widget" : `func,
		"widget_func" : SectionTypesWidget,
		"handle" : SectionTypeHandle,
		"help" : SectionTypeHelp (),
	    ],
            "makeactive" : SectionCheckBoxWidget("makeactive"),
            "noverifyroot" : SectionCheckBoxWidget("noverifyroot"),
            "remap" : SectionCheckBoxWidget("remap"),
            "relocatable" : SectionCheckBoxWidget("relocatable"),
	    "enable_selinux" : EnableSelinux(),
            "prompt" : SectionCheckBoxWidget("prompt"),
            "blockoffset" : SectionIntFieldWidget(
                "blockoffset",0,nil),
            "default" : SectionIntFieldWidget(
                "default",1,10),
            "timeout" : SectionIntFieldWidget(
                "timeout",0,60),
            "optional" : SectionCheckBoxWidget("optional"),
            "copy" : SectionCheckBoxWidget("copy"),
	    "other" :  //FIXME change to combobox and add proper init function
	              SectionTextFieldWidget("other"),
	];
    }

    return _common_section_widgets;
}

} // include end

ACC SHELL 2018