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 / ProductLicense.ycp < prev    next >
Text File  |  2006-11-29  |  12KB  |  463 lines

  1. /**
  2.  * File:    ProductLicense.ycp
  3.  *
  4.  * Module:    ProductLicense
  5.  *
  6.  * Summary:    Provide access / dialog for product license
  7.  *
  8.  * Author:    Jiri Srain <jsrain@suse.cz>
  9.  *
  10.  */
  11. {
  12.  
  13. module "ProductLicense";
  14.  
  15. import "Directory";
  16. import "InstShowInfo";
  17. import "Language";
  18. import "Popup";
  19. import "Report";
  20. import "Stage";
  21. import "Wizard";
  22. import "Mode";
  23. import "FileUtils";
  24. import "ProductFeatures";
  25.  
  26. textdomain "installation";
  27.  
  28. /**
  29.  * Displays License with Help and ( ) Yes / ( ) No radio buttons
  30.  * @param string file with the license
  31.  */
  32. void DisplayLicenseDialog (list<string> languages, boolean back) {
  33.     string license_text = "";
  34.     map display = UI::GetDisplayInfo();
  35.     integer space = display["TextMode"]:true ? 1 : 3;
  36.     term rt = `RichText(`id( `welcome_text), "");
  37.  
  38.     // dialog caption
  39.     string caption = _("License Agreement");
  40.  
  41.     // bug #204791, no more "languages.ycp" client
  42.     map<string,list> lang_names_orig = Language::GetLanguagesMap (false);
  43.     if (lang_names_orig == nil) {
  44.     y2error("Wrong definition of languages");
  45.     lang_names_orig = $[];
  46.     }
  47.  
  48.     // $[ "en" : "English", "de" : "Deutsch" ]
  49.     map<string,string> lang_names = mapmap (string code, list descr,
  50.     lang_names_orig,
  51.     {
  52.     return $[ code : descr[4]:"" ];
  53.     });
  54.  
  55.     /* for the default fallback */
  56.  
  57.     // language name
  58.     lang_names[""] = _("English");
  59.     // language name
  60.     lang_names["en"] = _("English");
  61.  
  62.     list<list<string> > lang_pairs = maplist (string l, languages, {
  63.     string name = lang_names[l]:"";
  64.     if (name == "")
  65.     {
  66.         string l_short = substring (l, 0, 2);
  67.         foreach (string k, string v, lang_names, {
  68.         if (substring (k, 0, 2) == l_short)
  69.         {
  70.             name = v;
  71.             return true;
  72.         }
  73.         return false;
  74.         });
  75.     }
  76.     return [ l, name ];
  77.     });
  78.  
  79.     // filter-out languages that don't have any name
  80.     lang_pairs = filter (list<string> lang_pair, lang_pairs, {
  81.     if (lang_pair[1]:"" == "") {
  82.         y2warning("Unknown license language '%1', filtering out...", lang_pair);
  83.         return false;
  84.     } else {
  85.         return true;
  86.     }
  87.     });
  88.  
  89.     lang_pairs = sort (list<string> l1, list<string> l2, lang_pairs, {
  90.     return l1[1]:"" < l2[1]:"";
  91.     });
  92.     list langs = maplist (list<string> descr, lang_pairs, {
  93.     return `item (`id (descr[0]:""), descr[1]:"");
  94.     });
  95.  
  96.     term contents = `VBox (
  97.     `VSpacing (space),
  98.     `HBox (
  99.         `HSpacing (2*space),
  100.         `VBox (
  101.         // combo box
  102.         `Left (`ComboBox (`id (`lang), `opt (`notify), _("&Language"),
  103.             langs)),
  104.         `ReplacePoint (`id (`license_rp), rt)
  105.         ),
  106.         `HSpacing (2*space)
  107.     ),
  108.     `VSpacing (2),
  109.     `RadioButtonGroup(`id(`eula),
  110.         `HBox(
  111.         `HSpacing (2*space),
  112.         `VBox(
  113.             `Left(`RadioButton(`id(`yes),
  114.             // radio button
  115.             _("&Yes, I Agree to the License Agreement")
  116.             )),
  117.             `Left(`RadioButton(`id(`no),
  118.             // radio button
  119.             _("N&o, I Do Not Agree")
  120.             ))
  121.         ),
  122.         `HSpacing (2*space)
  123.         )
  124.     ),
  125.     `VSpacing(2)
  126.     );
  127.  
  128.     // help text
  129.     string help = _("<p>Read the license agreement carefully and select
  130. one of the available options. If you do not agree to the license agreement,
  131. the configuration will be aborted.</p>
  132. ");
  133.  
  134.     Wizard::SetContents(caption, contents, help,
  135.     back, true);
  136.     // bugzilla #203543
  137.     if (size(langs) <= 1) {
  138.     UI::ChangeWidget (`id(`lang), `Enabled, false);
  139.     }
  140.  
  141.     Wizard::SetTitleIcon ("yast-license");
  142.     Wizard::SetFocusToNextButton();
  143. }
  144.  
  145.  
  146.  
  147. /**
  148.  * Removes the temporary directory for licenses
  149.  * @param string temporary directory path
  150.  */
  151. void CleanUpLicense (string tmpdir) {
  152.     if (tmpdir != nil)
  153.     SCR::Execute (.target.bash_output, sformat("rm -rf '%1'", tmpdir));
  154. }
  155.  
  156. /**
  157.  * Get all files with license existing in specified directory
  158.  * @param dir string directory to look into
  159.  * @param patterns a list of patterns for the files, regular expressions
  160.  *   with %1 for the language
  161.  * @return a map $[ lang_code : filename ]
  162.  */
  163. map<string,string> LicenseFiles (string dir, list<string> patterns) {
  164.     map<string,string> ret = $[];
  165.     list<string> files = (list<string>)SCR::Read (.target.dir, dir);
  166.     y2milestone ("All files in license directory: %1", files);
  167.  
  168.     foreach (string p, patterns, {
  169.     if (! issubstring (p, "%"))
  170.     {
  171.         foreach (string file, files, {
  172.         if (file == p)
  173.         {
  174.             ret[""] = dir + "/" + file;
  175.         }
  176.         });
  177.     }
  178.     else
  179.     {
  180.         string regpat = sformat (p, "(.+)");
  181.         foreach (string file, files, {
  182.         if (regexpmatch (file, regpat))
  183.         {
  184.             string key = regexpsub (file, regpat, "\\1");
  185.             ret[key] = dir + "/" + file;
  186.         }
  187.         });
  188.     }
  189.     });
  190.     y2milestone ("Files containing license: %1", ret);
  191.     return ret;
  192. }
  193.  
  194. /**
  195.  * Ask user to confirm license agreement
  196.  * @param src_id integer source to get the license from
  197.  * @param dir string directory to look for the license in if src_id is nil
  198.  *   and not 1st stage installation
  199.  * @param patterns a list of patterns for the files, regular expressions
  200.  *   with %1 for the language
  201.  * @param boolean enable_back sets the back_button status
  202.  * @param boolean base_product defines whether it is a base or add-on product
  203.  *   true means base product, false add-on product
  204.  */
  205. global symbol AskLicenseAgreement (integer src_id, string dir,
  206.     list<string> patterns, string action, boolean enable_back,
  207.     boolean base_product)
  208. {
  209.     string tmpdir = nil;
  210.     string info_file = nil;
  211.     string lic_lang = "";
  212.     map<string,string> licenses = $[];
  213.     list<string> available_langs = [];
  214.     string license_dir = nil;
  215.  
  216.     if (src_id == nil)
  217.     {
  218.     if (Stage::initial ())
  219.     {
  220.         license_dir = Directory::vardir + "/license";
  221.     }
  222.     else
  223.     {
  224.         license_dir = dir;
  225.     }
  226.     if (FileUtils::Exists ("/info.txt"))
  227.         info_file = "/info.txt";
  228.     }
  229.     else
  230.     {
  231.     y2milestone ("Getting license info from source %1", src_id);
  232.     tmpdir = (string) SCR::Read(.target.tmpdir) + "/product-license/";
  233.     license_dir = tmpdir;
  234.     string license_file = Pkg::SourceProvideOptionalFile (src_id, 1,
  235.         "/media.1/license.zip");
  236.  
  237.     // license is part of the add-on product
  238.     if (license_file != nil) {
  239.         y2milestone("Product has a license");
  240.         map out = (map)SCR::Execute (.target.bash_output, sformat ("
  241. rm -rf '%1' && \
  242. mkdir -p '%1' && \
  243. cd '%1' && \
  244. unzip -qqo '%2'
  245. ", tmpdir, license_file));
  246.  
  247.         // Extracting license failed, cannot accept the license
  248.         if (out["exit"]:0 != 0)
  249.         {
  250.         y2error("Cannot unzip license -> %1", out);
  251.         // popup error
  252.         Report::Error (_("An error occurred while preparing the installation system."));
  253.         CleanUpLicense(tmpdir);
  254.         return nil; // FIXME
  255.         }
  256.     }
  257.     info_file = Pkg::SourceProvideOptionalFile (src_id, 1, "/media.1/info.txt");
  258.     }
  259.     licenses = LicenseFiles (license_dir,
  260.     ["license.txt", "license\\.%1\\.txt"]);
  261.     if (info_file == nil && size (licenses) == 0)
  262.     return `auto;
  263.  
  264.     // Preferencies how the client selects from available languages
  265.     list<string> langs = [
  266.     Language::language,
  267.     substring (Language::language, 0, 2), // "it_IT" -> "it"
  268.     "en_US",
  269.     "en_EN",
  270.     "en",
  271.     "" // license.txt fallback
  272.     ];
  273.     available_langs = maplist (string lang, string fn,
  274.     licenses,
  275.     {
  276.     return lang;
  277.     });
  278.  
  279.     // "en" is the same as "", we don't need to have them both
  280.     if (contains(available_langs, "en") && contains(available_langs, "")) {
  281.     y2milestone("Removing license fallback '' as we already have 'en'...");
  282.     available_langs = filter (string one_lang, available_langs, {
  283.         return one_lang != "en";
  284.     });
  285.     }
  286.  
  287.     y2milestone ("Preffered lang: %1", Language::language);
  288.     if (size (available_langs) == 0)
  289.     return `auto; // no license available
  290.     lic_lang = find (string l, langs, {
  291.     return haskey (licenses, l);
  292.     });
  293.     if (lic_lang == nil)
  294.     lic_lang = available_langs[0]:"";
  295.  
  296.     y2milestone ("Preselected language: '%1'", lic_lang);
  297.     DisplayLicenseDialog (available_langs, enable_back);
  298.     // Display info as a popup if exists
  299.     if (info_file != nil)
  300.     InstShowInfo::show_info_txt(info_file);
  301.  
  302.     if (lic_lang == nil)
  303.     {
  304.     CleanUpLicense(tmpdir);
  305.     return `auto;
  306.     }
  307.  
  308.     // initial loop
  309.     UI::ChangeWidget(`id(`lang), `Value, lic_lang);
  310.     symbol ret = `first;
  311.  
  312.     // set timeout for autoinstallation
  313.     // bugzilla #206706
  314.     boolean timeout = false;
  315.     if (Mode::autoinst()) {
  316.     timeout = true;
  317.     }
  318.  
  319.     while (true)
  320.     {
  321.     if (ret == `lang || ret == `first)
  322.     {
  323.         // read the selected language if not in the initial loop
  324.         if (ret != `first) lic_lang = (string) UI::QueryWidget (`id (`lang), `Value);
  325.         string license_file = licenses[lic_lang]:"";
  326.         y2milestone ("Using license file: %1", license_file);
  327.         string license_text = (string)
  328.         SCR::Read(.target.string, license_file);
  329.         if (license_text == nil)
  330.         {
  331.         license_text = "";
  332. // TODO error message
  333.         }
  334.         term rt = `Empty();
  335.         if (regexpmatch(license_text, "</.*>"))
  336.         rt = `RichText(`id( `welcome_text), license_text);
  337.         else
  338.         rt = `RichText(`id( `welcome_text), `opt(`plainText), license_text);
  339.         UI::ReplaceWidget (`id (`license_rp), rt);
  340.     }
  341.  
  342.     // bugzilla #206706
  343.     if (timeout) {
  344.         sleep (2000);
  345.         y2milestone("AutoYaST: License has been accepted after timeout...");
  346.         return `accepted;
  347.     }
  348.  
  349.     ret = (symbol) UI::UserInput();
  350.  
  351.     symbol accept = (symbol) UI::QueryWidget(`id(`eula), `CurrentButton);
  352.     // Aborting the license dialog
  353.     if (ret == `abort) {
  354.         // bugzilla #218677
  355.         if (base_product) {
  356.         if (Popup::ConfirmAbort (`painless)) {
  357.             y2milestone("Aborting...");
  358.             return `abort;
  359.         }
  360.         } else {
  361.         // popup question
  362.         if (Popup::ContinueCancel(_("Really abort add-on product installation?"))) {
  363.             y2milestone("Aborting...");
  364.             return `abort;
  365.         }
  366.         }
  367.     }
  368.     else if (ret == `next)
  369.     {
  370.         // License declined
  371.         if (accept == `no)
  372.         {
  373.         if (Popup::YesNo(_("Reread or reconsider the license agreement?")))
  374.         {
  375.             continue;
  376.         }
  377.         else
  378.         {
  379.             y2milestone("License has been declined.");
  380.             if (action == "abort")
  381.             return `abort;
  382.             else if (action == "continue")
  383.             return `accepted;
  384.             else if (action == "halt")
  385.             {
  386.             return `halt;
  387.             // timed ok/cancel popup
  388.             if (!Popup::TimedOKCancel(_("System is shutting down..."), 10))
  389.             {
  390.                 continue;
  391.             }
  392.             else
  393.             {
  394.                 return `halt;
  395.             }
  396.             }
  397.             else
  398.             {
  399.             y2error ("Unknown action %1", action);
  400.             return `abort;
  401.             }
  402.         }
  403.         }
  404.         // License accepted
  405.         else if (accept == `yes)
  406.         {
  407.         y2milestone("License has been accepted.");
  408.         return `accepted;
  409.         }
  410.         else
  411.         {
  412.         // message popup
  413.         Popup::Message(_("Accept or decline the license agreement."));
  414.         continue;
  415.         }
  416.         }
  417.     else if (ret == `back)
  418.     {
  419.         return `back;
  420.     }
  421.     }
  422.  
  423.     CleanUpLicense(tmpdir);
  424.  
  425. }
  426.  
  427. global symbol AskAddOnLicenseAgreement (integer src_id) {
  428.     return AskLicenseAgreement (src_id, "",
  429.     [ "license\\.txt", "license\\.%1\\.txt" ],
  430.     "abort",
  431.     // back button is disabled
  432.     false, false);
  433. }
  434.  
  435. global symbol AskFirstStageLicenseAgreement (string action) {
  436.     // bug #223258
  437.     // disabling back button when the select-language dialog is skipped
  438.     //
  439.     // FIXME: hotfix for 10.2, solve better for 10.3
  440.     //
  441.     boolean enable_back = true;
  442.     if (Stage::initial () &&
  443.     ProductFeatures::GetBooleanFeature ("globals", "skip_language_dialog") &&
  444.     Language::preselected != "en_US"
  445.     ) enable_back = false;
  446.  
  447.     return AskLicenseAgreement (nil, "",
  448.     [ "license\\.txt", "license\\.%1\\.txt" ],
  449.     action,
  450.     // back button is enabled
  451.     enable_back, true);
  452. }
  453.  
  454. global symbol AskInstalledLicenseAgreement (string directory,
  455.     list<string> patterns, string action)
  456. {
  457.     return AskLicenseAgreement (nil, directory, patterns, action, false, true);
  458.  
  459. }
  460.  
  461.  
  462. } // EOF
  463.