- changed read_bool_answer() to take queston string and default answer value
authorJan Kupec <jkupec@suse.cz>
Wed, 18 Jul 2007 05:27:05 +0000 (05:27 +0000)
committerJan Kupec <jkupec@suse.cz>
Wed, 18 Jul 2007 05:27:05 +0000 (05:27 +0000)
- keyring callbacks improved and prepared for non-interactive and
  no-gpg-checks mode

src/zypper-callbacks.cc
src/zypper-callbacks.h
src/zypper-keyring-callbacks.h
src/zypper-misc.cc
src/zypper.cc
src/zypper.h

index 9f3600b..3152be6 100644 (file)
@@ -49,9 +49,8 @@ void display_done () {
 //template<typename Action>
 //Action ...
 int read_action_ari (int default_action) {
-  if (gSettings.verbosity >= 0 || !gSettings.non_interactive)
-    // TranslatorExplanation don't translate letters in parentheses!!
-    cout << _("(A)bort, (R)etry, (I)gnore?") << " "; 
+  // TranslatorExplanation don't translate letters in parentheses!!
+  cout << _("(A)bort, (R)etry, (I)gnore?") << " "; 
 
   // choose abort if no default has been specified
   if (default_action == -1) {
@@ -68,8 +67,8 @@ int read_action_ari (int default_action) {
          default: c = '?';
       }
       // print the answer for conveniecne
-      cout_n << c << endl;
-
+      cout << c << endl;
+      MIL << "answer: " << c << endl;
       return default_action;
   }
 
@@ -78,6 +77,7 @@ int read_action_ari (int default_action) {
     char c;
     cin >> c;
     c = tolower (c);
+    MIL << "answer: " << c << endl;
     if (c == 'a')
       return 0;
     else if (c == 'r')
@@ -85,6 +85,7 @@ int read_action_ari (int default_action) {
     else if (c == 'i')
       return 2;
     cerr << _("Invalid answer. Choose letter a, r, or i.") << endl;
+    DBG << "invalid answer" << endl;
   }
 
   return default_action;
@@ -92,30 +93,36 @@ int read_action_ari (int default_action) {
 
 // ----------------------------------------------------------------------------
 
-// return the default value on input failure
-// TODO make this locale dependent?
-bool read_bool_with_default (bool defval) {
+// Read an answer (ynYN)
+bool read_bool_answer(const string & question, bool default_answer)
+{
+  cout << CLEARLN << question << " [y/n]: " << flush;
+
+  // non-interactive mode: print the answer for convenience and return default
+  if (gSettings.non_interactive)
+  {
+    cout << (default_answer ? 'y' : 'n') << endl;
+    MIL << "answer (default): " << (default_answer ? 'y' : 'n') << endl;
+    return default_answer;
+  }
+
   istream & stm = cin;
 
   string c = "";
   while (stm.good () && c != "y" && c != "Y" && c != "N" && c != "n")
     c = zypp::str::getline (stm, zypp::str::TRIM);
-      
+
+  MIL << "answer: " << c << endl;
   if (c == "y" || c == "Y")
     return true;
   else if (c == "n" || c == "N")
     return false;
   else
-    return defval;
-}
-
-// ----------------------------------------------------------------------------
-
-// Read an answer (ynYN)
-// Defaults to 'false'
-bool readBoolAnswer()
-{
-  return read_bool_with_default (false);
+  {
+    WAR << "could not read answer, returning default: "
+        << (default_answer ? 'y' : 'n') << endl;
+    return default_answer;
+  }
 }
 
 // ----------------------------------------------------------------------------
index 099c548..e3366d8 100644 (file)
@@ -41,22 +41,24 @@ void display_error (Error error, const std::string& reason) {
   }
 }
 
-/** 
+/**
  * Abort, Retry, Ignore stdin prompt.
  * \param default_action Answer to be returned in non-interactive mode. If none
- *             is specified, 0 (ABORT) is returned. In interactive mode, this parameter
+ *    is specified, 0 (ABORT) is returned. In interactive mode, this parameter
  *    is ignored.
  */
 int read_action_ari (int default_action = -1);
 
 /**
  * Prompt for Yes/No answer from stdin.
- * 
- * \todo work with default
- * \todo non-interactive mode
+ *
+ * \param question Question to be printed on prompt.
+ * \param default_answer Value to be returned in non-interactive mode or on
+ *      input failure.
+ *
  * \todo make this localized
  */
-bool readBoolAnswer();
+bool read_bool_answer(const string & question, bool default_answer);
 
 std::string to_string (zypp::Resolvable::constPtr resolvable);
 #endif
index 69e4e54..f915037 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <stdlib.h>
 #include <iostream>
+#include <boost/format.hpp>
 
 #include <zypp/base/Logger.h>
 #include <zypp/ZYppCallbacks.h>
@@ -33,64 +34,131 @@ namespace zypp {
     {
       virtual bool askUserToAcceptUnsignedFile( const std::string &file )
       {
-        cout << CLEARLN << file << _(" is unsigned, continue?") << " [y/n]: " << flush;
-        return readBoolAnswer();
+        if (gSettings.no_gpg_checks)
+        {
+          MIL << "Accepting unsigned file (" << file << ")" << endl;
+          cout_v << boost::format(_("Warning: Accepting an unsigned file %s.")) % file;
+          return true;
+        }
+
+        // TranslatorExplanation: speaking of a file
+        std::string question = boost::str(boost::format(
+            _("%s is unsigned, continue?")) % file);
+        return read_bool_answer(question, false);
       }
-      
+
       virtual bool askUserToImportKey( const PublicKey &key )
       {
         if ( geteuid() != 0 )
           return false;
-        
-        cout << CLEARLN << _("Import key ") << key.id() << _(" to trusted keyring?") << "  [y/n]: " << flush;
-        return readBoolAnswer();
-      } 
+
+        std::string question = boost::str(boost::format(
+            _("Import key %s to trusted keyring?")) % key.id());
+        return read_bool_answer(question, false);
+      }
 
       virtual bool askUserToAcceptUnknownKey( const std::string &file, const std::string &id )
       {
-        cout << CLEARLN << file << _(" is signed with an unknown key id: ") << id << ", " << _("continue?") << " [y/n]: " << flush;
-        return readBoolAnswer();
+        if (gSettings.no_gpg_checks)
+        {
+          MIL << "Accepting file signed with an unknown key (" << file << "," << id << ")" << endl;
+          cout_n << boost::format(
+              _("Warnging: Accepting file %s signed with an unknown key %s."))
+              % file % id;
+          return true;
+        }
+
+        // TranslatorExplanation: speaking of a file
+        std::string question = boost::str(boost::format(
+            _("%s is signed with an unknown key %s. Continue?")) % file % id);
+        return read_bool_answer(question, false);
       }
 
       virtual bool askUserToTrustKey( const PublicKey &key )
       {
        const std::string& keyid = key.id(), keyname = key.name(),
          fingerprint = key.fingerprint();
-        cout  << CLEARLN << _("Do you want to trust key id ") << keyid << " " << keyname << _(" fingerprint:") << fingerprint << " ? [y/n]: "  << flush;
-        return readBoolAnswer();
+
+        if (gSettings.no_gpg_checks)
+        {
+          MIL << boost::format("Automatically trusting key id %s, %s, fingerprint %s")
+              % keyid % keyname % fingerprint << endl;
+          cout_n << boost::format(
+              _("Automatically trusting key id %s, %s, fingerprint %s"))
+              % keyid % keyname % fingerprint << endl;
+          return true;
+        }
+
+        std::string question = boost::str(boost::format(
+           _("Do you want to trust key id %s, %s, fingerprint %s"))
+           % keyid % keyname % fingerprint);
+        return read_bool_answer(question, false);
       }
 
       virtual bool askUserToAcceptVerificationFailed( const std::string &file,const PublicKey &key )
       {
        const std::string& keyid = key.id(), keyname = key.name(),
          fingerprint = key.fingerprint();
-        cout << file << _("Signature verification for ") << file
-            << _(" with public key id ") << keyid << " " << keyname << _(" fingerprint:") << fingerprint << _(" failed, THIS IS RISKY!") << ". " << _("continue?") << " [y/n]: " << endl;
-        return readBoolAnswer(); // TODO do this with format()
+
+        if (gSettings.no_gpg_checks)
+        {
+          MIL << boost::format(
+              "Ignoring failed signature verification for %s"
+              " with public key id %s, %s, fingerprint %s")
+              % file % keyid % keyname % fingerprint << endl;
+          cerr << boost::format(
+              _("Warning: Ignoring failed signature verification for %s"
+                " with public key id %s, %s, fingerprint %s!"
+                " Double-check this is not caused by some malicious"
+                " changes in the file!"))
+              %file % keyid % keyname % fingerprint << endl;
+          return true;
+        }
+
+        std::string question = boost::str(boost::format(
+            _("Signature verification failed for %s"
+              " with public key id %s, %s, fingerprint %s."
+              " Warning: this might be caused by a malicious change in the file!"
+              " Continuing is risky! Continue anyway?"))
+            % file % keyid % keyname % fingerprint);
+        return read_bool_answer(question, false);
       }
     };
 
-
     struct DigestReceive : public zypp::callback::ReceiveReport<zypp::DigestReport>
     {
       virtual bool askUserToAcceptNoDigest( const zypp::Pathname &file )
       {
-       cout << CLEARLN << _("No digest for ") << file
-            << ", " << _("continue?") << " [y/n]" << flush;
-        return readBoolAnswer();
+       std::string question = boost::str(boost::format(
+           _("No digest for file %s.")) % file) + " " + _("Continue?");
+        return read_bool_answer(question, gSettings.no_gpg_checks);
       }
+
       virtual bool askUserToAccepUnknownDigest( const Pathname &file, const std::string &name )
       {
-       cout << CLEARLN << _("Unknown digest ") << name << _(" for ") << file
-            << ", " << _("continue?") << " [y/n]" << flush;
-        return readBoolAnswer();
+        std::string question = boost::str(boost::format(
+            _("Unknown digest %s for file %s.")) %name % file) + " " +
+            _("Continue?");
+        return read_bool_answer(question, gSettings.no_gpg_checks);
       }
+
       virtual bool askUserToAcceptWrongDigest( const Pathname &file, const std::string &requested, const std::string &found )
       {
-       cout << CLEARLN << _("Digest verification failed for ") << file
-            << _(", expected ") << requested << _(" found ") << found
-            << ", " << _("continue?") << " [y/n]" << flush;
-        return readBoolAnswer();
+        if (gSettings.no_gpg_checks)
+        {
+          WAR << boost::format(
+              "Ignoring failed digest verification for %s (expected %s, found %s).")
+              % file % requested % found << endl;
+          cerr << boost::format(
+              _("Ignoring failed digest verification for %s (expected %s, found %s)."))
+              % file % requested % found << endl;
+          return true;
+        }
+
+       std::string question = boost::str(boost::format(
+           _("Digest verification failed for %s. Expected %s, found %s."))
+           % file % requested % found) + " " + _("Continue?");
+        return read_bool_answer(question, false);
       }
     };
 
index a71526f..e43aca1 100644 (file)
@@ -833,8 +833,7 @@ int solve_and_commit (bool non_interactive) {
   int retv = show_summary();
 
   if (retv >= 0) { // there are resolvables to install/uninstall
-    cerr << _("Continue?") << " [y/n] " << (non_interactive ? "y\n" : "");
-    if (non_interactive || readBoolAnswer()) {
+    if (read_bool_answer(_("Continue?"), non_interactive)) {
 
       if (!confirm_licenses(non_interactive)) return ZYPPER_EXIT_OK;
 
@@ -884,7 +883,7 @@ int solve_and_commit (bool non_interactive) {
   return retv;
 }
 
-// TODO
+// TODO confirm licenses
 // - make this more user-friendly e.g. show only license name and
 //  ask for [y/n/r] with 'r' for read the license text
 //  (opened throu more or less, etc...)
@@ -903,11 +902,10 @@ bool confirm_licenses(bool non_interactive)
         " " << _("license") << ": " <<
         it->resolvable()->licenseToConfirm() << endl;
 
-      cout << _("In order to install this package, you must agree"
-        " to terms of the above licencse. Continue?") << " [y/n] " <<
-        (non_interactive ? "n\n" : "");
+      string question = _("In order to install this package, you must agree"
+        " to terms of the above licencse. Continue?");
 
-      if (non_interactive || !readBoolAnswer())
+      if (non_interactive || !read_bool_answer(question, false))
       {
         confirmed = false;
         
index fda4cee..3ed1f13 100644 (file)
@@ -55,16 +55,17 @@ KeyRingCallbacks keyring_callbacks;
 DigestCallbacks digest_callbacks;
 
 static struct option global_options[] = {
-  {"help",     no_argument, 0, 'h'},
-  {"verbose",  no_argument, 0, 'v'},
-  {"quiet",    no_argument, 0, 'q'},
-  {"version",  no_argument, 0, 'V'},
-  {"terse",    no_argument, 0, 't'},
-  {"table-style", required_argument, 0, 's'},
-  {"rug-compatible", no_argument, 0, 'r'},
-  {"non-interactive", no_argument, 0, 0},
-  {"root",     required_argument, 0, 'R'},
-  {"opt",      optional_argument, 0, 'o'},
+  {"help",            no_argument,       0, 'h'},
+  {"verbose",         no_argument,       0, 'v'},
+  {"quiet",           no_argument,       0, 'q'},
+  {"version",         no_argument,       0, 'V'},
+  {"terse",           no_argument,       0, 't'},
+  {"table-style",     required_argument, 0, 's'},
+  {"rug-compatible",  no_argument,       0, 'r'},
+  {"non-interactive", no_argument,       0, 0},
+  {"no-gpg-checks",   no_argument,       0, 0},
+  {"root",            required_argument, 0, 'R'},
+  {"opt",             optional_argument, 0, 'o'},
   {0, 0, 0, 0}
 };
 
@@ -156,17 +157,17 @@ ZypperCommand process_globals(int argc, char **argv)
   if (gopts.count("verbose")) {
     gSettings.verbosity += gopts["verbose"].size();
     cout << _("Verbosity ") << gSettings.verbosity << endl;
-    DBG << _("Verbosity ") << gSettings.verbosity << endl;
+    DBG << "Verbosity " << gSettings.verbosity << endl;
   }
 
   if (gopts.count("non-interactive")) {
-       gSettings.non_interactive = true;
-       cout_n << "Entering non-interactive mode.\n"
-               "WARNING: global non-interactive mode is still under development, use "
-               "with caution. This mode has been implemented and tested for install, "
-               "remove, and update commands so far. In case of problems related to "
-               "non-interactive mode, please file a bugreport following instructions at "
-               "http://en.opensuse.org/Zypper#Troubleshooting" << endl;
+    gSettings.non_interactive = true;
+    MIL << "Entering non-interactive mode" << endl;
+  }
+
+  if (gopts.count("no-gpg-checks")) {
+    gSettings.no_gpg_checks = true;
+    MIL << "Entering no-gpg-checks mode" << endl;
   }
 
   if (gopts.count("table-style")) {
index 1c9e62b..2edbeec 100644 (file)
@@ -49,6 +49,7 @@ struct Settings
   disable_system_resolvables(false),
   is_rug_compatible(false),
   non_interactive(false),
+  no_gpg_checks(false),
   root_dir("/")
   {}
 
@@ -72,6 +73,7 @@ struct Settings
   bool disable_system_resolvables;
   bool is_rug_compatible;
   bool non_interactive;
+  bool no_gpg_checks;
   std::string root_dir;
 };