Add isListEnabled into client configuration

Change-Id: Ib3471fd0658e64040d5ffee653e297fa58f2cfd7
diff --git a/.gitignore b/.gitignore
index b54981e..0d8bb83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@
 **/*.pyc
 build/
 VERSION
+.vscode
\ No newline at end of file
diff --git a/src/client-config.cpp b/src/client-config.cpp
index aeeaddc..e28407c 100644
--- a/src/client-config.cpp
+++ b/src/client-config.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2017, Regents of the University of California.
+ * Copyright (c) 2017-2018, Regents of the University of California.
  *
  * This file is part of ndncert, a certificate management system based on NDN.
  *
@@ -62,6 +62,13 @@
   item.m_caName = Name(configSection.get<std::string>("ca-prefix"));
   item.m_caInfo = configSection.get<std::string>("ca-info");
   item.m_probe = configSection.get("probe", "");
+  std::string listEnabledField = configSection.get("is-list-enabled", "false");
+  if (listEnabledField == "true") {
+    item.m_isListEnabled = true;
+  }
+  else {
+    item.m_isListEnabled = false;
+  }
   item.m_targetedList = configSection.get("target-list", "");
 
   std::istringstream ss(configSection.get<std::string>("certificate"));
diff --git a/src/client-config.hpp b/src/client-config.hpp
index 97c282b..72dd78f 100644
--- a/src/client-config.hpp
+++ b/src/client-config.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2017, Regents of the University of California.
+ * Copyright (c) 2017-2018, Regents of the University of California.
  *
  * This file is part of ndncert, a certificate management system based on NDN.
  *
@@ -36,11 +36,12 @@
   // The identity name of the CA. Extracted from config field "ca-prefix"
   Name m_caName;
 
-  // TODO: remove the caInfo, probe, and targetedList. Put them into the cert
   // A brief introduction to the CA. Extracted from config field "ca-info"
   std::string m_caInfo;
   // An instruction for requesters to use _PROBE. Extracted from config field "probe"
   std::string m_probe;
+  // Whether support list function
+  bool m_isListEnabled;
   // An instruction for requesters to get a recommended CA. Extracted from config field "target-list"
   std::string m_targetedList;
 
diff --git a/tests/unit-tests/client-config.t.cpp b/tests/unit-tests/client-config.t.cpp
index 6035510..c057023 100644
--- a/tests/unit-tests/client-config.t.cpp
+++ b/tests/unit-tests/client-config.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2017, Regents of the University of California.
+ * Copyright (c) 2017-2018, Regents of the University of California.
  *
  * This file is part of ndncert, a certificate management system based on NDN.
  *
@@ -39,6 +39,7 @@
   BOOST_CHECK_EQUAL(item.m_caInfo, "UCLA's ceritificate authority, located in BH4805.");
   BOOST_CHECK_EQUAL(item.m_probe, "Please use your email address to apply a namespace first. UCLA email is preferred.");
   BOOST_CHECK_EQUAL(item.m_targetedList, "Use your email address (edu preferred) as input");
+  BOOST_CHECK_EQUAL(item.m_isListEnabled, true);
   BOOST_CHECK_EQUAL(item.m_anchor.getName().toUri(),
                     "/ndn/site1/KEY/%11%BC%22%F4c%15%FF%17/self/%FD%00%00%01Y%C8%14%D9%A5");
 
@@ -54,6 +55,7 @@
   item.m_caName = Name("/test");
   item.m_caInfo = "test";
   item.m_probe = "test";
+  item.m_isListEnabled = false;
 
   config.m_caItems.push_back(item);
   BOOST_CHECK_EQUAL(config.m_caItems.size(), 3);
diff --git a/tests/unit-tests/client.conf.test b/tests/unit-tests/client.conf.test
index 9c39af1..7cd85e8 100644
--- a/tests/unit-tests/client.conf.test
+++ b/tests/unit-tests/client.conf.test
@@ -6,11 +6,13 @@
         "ca-info": "UCLA's ceritificate authority, located in BH4805.",
         "target-list": "Use your email address (edu preferred) as input",
         "probe": "Please use your email address to apply a namespace first. UCLA email is preferred.",
+        "is-list-enabled": "true",
         "certificate": "Bv0CJAcsCANuZG4IBXNpdGUxCANLRVkICBG8IvRjFf8XCARzZWxmCAn9AAABWcgU2aUUCRgBAhkEADbugBX9AU8wggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAES9Cb9iANUNYmwt5bjwNW1mZgjzIkDJb6FTCdiYWnkMMIVxh2YDllphoWDEAPS6kqJczzCuhnGYpZCp9tTaYKGxZMGwEDHB0HGwgDbmRuCAVzaXRlMQgDS0VZCAgRvCL0YxX/F/0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwMzcwMTE3VDIxMjg0NhdIMEYCIQDXkR1hF3GiP7yLXq+0JBJfi9QC+hhAu/1Bykx+MWz6RAIhANwelBTxxZr2C5bD15mjfhWudK4I1tOb4b/9xWCHyM7F"
     },
     {
         "ca-prefix": "/ndn/edu/ucla/zhiyi/CA",
         "ca-info": "Zhiyi's own ceritificate authority",
+        "is-list-enabled": "false",
         "certificate": "Bv0CJAcsCANuZG4IBXNpdGUxCANLRVkICBG8IvRjFf8XCARzZWxmCAn9AAABWcgU2aUUCRgBAhkEADbugBX9AU8wggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAES9Cb9iANUNYmwt5bjwNW1mZgjzIkDJb6FTCdiYWnkMMIVxh2YDllphoWDEAPS6kqJczzCuhnGYpZCp9tTaYKGxZMGwEDHB0HGwgDbmRuCAVzaXRlMQgDS0VZCAgRvCL0YxX/F/0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwMzcwMTE3VDIxMjg0NhdIMEYCIQDXkR1hF3GiP7yLXq+0JBJfi9QC+hhAu/1Bykx+MWz6RAIhANwelBTxxZr2C5bD15mjfhWudK4I1tOb4b/9xWCHyM7F"
     }
   ],
diff --git a/tools/ndncert-client.cpp b/tools/ndncert-client.cpp
index a4b3368..7e9c5a4 100644
--- a/tools/ndncert-client.cpp
+++ b/tools/ndncert-client.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2017, Regents of the University of California.
+ * Copyright (c) 2017-2018, Regents of the University of California.
  *
  * This file is part of ndncert, a certificate management system based on NDN.
  *
@@ -52,7 +52,7 @@
   downloadCb(const shared_ptr<RequestState>& state)
   {
     std::cerr << "Step " << nStep++
-              << "DONE! Certificate has already been installed to local keychain" << std::endl;
+              << "DONE! Certificate has already been installed to local keychain\n";
     return;
   }
 
@@ -76,7 +76,7 @@
     }
     else {
       if (caItem.m_probe != "") {
-        std::cerr <<"Step " << nStep++ << ": Probe Requirement-" << caItem.m_probe << std::endl;
+        std::cerr << "Step " << nStep++ << ": Probe Requirement-" << caItem.m_probe << std::endl;
         std::string probeInfo;
         getline(std::cin, probeInfo);
         client.sendProbe(caItem, probeInfo,
@@ -84,7 +84,7 @@
                          bind(&ClientTool::errorCb, this, _1));
       }
       else {
-        std::cerr <<"Step " << nStep++ << ": Please type in the identity name" << std::endl;
+        std::cerr << "Step " << nStep++ << ": Please type in the identity name\n";
         std::string nameComponent;
         getline(std::cin, nameComponent);
         Name identityName = caItem.m_caName.getPrefix(-1);
@@ -113,12 +113,12 @@
       // without recommendation
       int count = 0;
       for (auto name : caList) {
-        std::cerr << "***************************************" << "\n"
+        std::cerr << "***************************************\n"
                   << "Index: " << count++ << "\n"
                   << "CA prefix:" << name << "\n"
-                  << "***************************************" << std::endl;
+                  << "***************************************\n";
       }
-      std::cerr << "Select an index to apply for a certificate."<< std::endl;
+      std::cerr << "Select an index to apply for a certificate\n";
 
       std::string option;
       getline(std::cin, option);
@@ -137,7 +137,7 @@
   validateCb(const shared_ptr<RequestState>& state)
   {
     if (state->m_status == ChallengeModule::SUCCESS) {
-      std::cerr << "DONE! Certificate has already been issued" << std::endl;
+      std::cerr << "DONE! Certificate has already been issued \n";
       client.requestDownload(state,
                              bind(&ClientTool::downloadCb, this, _1),
                              bind(&ClientTool::errorCb, this, _1));
@@ -147,7 +147,7 @@
     auto challenge = ChallengeModule::createChallengeModule(state->m_challengeType);
     auto requirementList = challenge->getRequirementForValidate(state->m_status);
 
-    std::cerr << "Step" << nStep++ << ": Please satisfy following instruction(s)" << std::endl;
+    std::cerr << "Step " << nStep++ << ": Please satisfy following instruction(s)\n";
     for (auto requirement : requirementList) {
       std::cerr << "\t" << requirement << std::endl;
     }
@@ -169,7 +169,7 @@
     auto challenge = ChallengeModule::createChallengeModule(state->m_challengeType);
     auto requirementList = challenge->getRequirementForValidate(state->m_status);
 
-    std::cerr << "Step" << nStep++ << ": Please satisfy following instruction(s)" << std::endl;
+    std::cerr << "Step " << nStep++ << ": Please satisfy following instruction(s)" << std::endl;
     for (auto item : requirementList) {
       std::cerr << "\t" << item << std::endl;
     }
@@ -189,7 +189,7 @@
   void
   newCb(const shared_ptr<RequestState>& state)
   {
-    std::cerr << "Step" << nStep++ << ": Please select one challenge from following types." << std::endl;
+    std::cerr << "Step " << nStep++ << ": Please select one challenge from following types\n";
     for (auto item : state->m_challengeList) {
       std::cerr << "\t" << item << std::endl;
     }
@@ -200,7 +200,7 @@
     auto requirementList = challenge->getRequirementForSelect();
     std::list<std::string> paraList;
     if (requirementList.size() != 0) {
-      std::cerr << "Step" << nStep++ << ": Please satisfy following instruction(s)" << std::endl;
+      std::cerr << "Step " << nStep++ << ": Please satisfy following instruction(s)\n";
       for (auto item : requirementList) {
         std::cerr << "\t" << item << std::endl;
       }
@@ -228,10 +228,12 @@
   bool isIntra = false;
   po::options_description description("General Usage\n ndncert-client [-h] [-i] [-f]\n");
   description.add_options()
-    ("help,h", "produce help message")
-    ("intra-node,i", "optional, if specified, switch on the intra-node mode")
-    ("config-file,f", po::value<std::string>(&configFilePath), "config file name")
-    ;
+    ("help,h",
+     "produce help message")
+    ("intra-node,i",
+     "optional, if specified, switch on the intra-node mode")
+    ("config-file,f", po::value<std::string>(&configFilePath),
+     "config file name");
   po::positional_options_description p;
 
   po::variables_map vm;
@@ -263,15 +265,15 @@
         auto caList = config.m_caItems;
         int count = 0;
         for (auto item : caList) {
-          std::cerr << "***************************************" << "\n"
+          std::cerr << "***************************************\n"
                     << "Index: " << count++ << "\n"
                     << "CA prefix:" << item.m_caName << "\n"
                     << "Introduction: " << item.m_caInfo << "\n"
-                    << "***************************************" << std::endl;
+                    << "***************************************\n";
         }
         std::vector<ClientCaItem> caVector{std::begin(caList), std::end(caList)};
-        std::cerr << "Step" << nStep++
-                  << ": Please type in the CA namespace index that you want to apply" << std::endl;
+        std::cerr << "Step " << nStep++
+                  << ": Please type in the CA namespace index that you want to apply\n";
         std::string caIndexS;
         getline(std::cin, caIndexS);
         int caIndex = std::stoi(caIndexS);
@@ -280,7 +282,7 @@
 
         auto targetCaItem = caVector[caIndex];
         if (targetCaItem.m_probe != "") {
-          std::cerr <<"Step" << nStep++ << ": Probe Requirement-" << targetCaItem.m_probe << std::endl;
+          std::cerr << "Step " << nStep++ << ": Probe Requirement-" << targetCaItem.m_probe << std::endl;
           std::string probeInfo;
           getline(std::cin, probeInfo);
           client.sendProbe(targetCaItem, probeInfo,
@@ -288,7 +290,7 @@
                            bind(&ClientTool::errorCb, &tool, _1));
         }
         else {
-          std::cerr <<"Step" << nStep++ << ": Please type in the identity name" << std::endl;
+          std::cerr << "Step " << nStep++ << ": Please type in the identity name\n";
           std::string nameComponent;
           getline(std::cin, nameComponent);
           Name identityName = targetCaItem.m_caName.getPrefix(-1);
@@ -301,34 +303,58 @@
       bind(&ClientTool::errorCb, &tool, _1));
   }
   else {
+    // Inter-node Application
+    bool listFirst = false;
     auto caList = client.getClientConf().m_caItems;
     int count = 0;
     for (auto item : caList) {
-      std::cerr << "***************************************" << "\n"
+      std::cerr << "***************************************\n"
                 << "Index: " << count++ << "\n"
                 << "CA prefix:" << item.m_caName << "\n"
                 << "Introduction: " << item.m_caInfo << "\n"
-                << "***************************************" << std::endl;
+                << "***************************************\n";
     }
     std::vector<ClientCaItem> caVector{std::begin(caList), std::end(caList)};
-    std::cerr << "Step " << nStep++ << ": Please type in the CA namespace index that you want to apply" << std::endl;
+    std::cerr << "Step " << nStep++ << ": Please type in the CA namespace index that you want to apply\n";
 
     std::string caIndexS;
     getline(std::cin, caIndexS);
-
     int caIndex = std::stoi(caIndexS);
-
     BOOST_ASSERT(caIndex <= count);
-
     auto targetCaItem = caVector[caIndex];
-    std::cerr << "You want a namespace with prefix (A) /ndn or (B) a sub-namespace of "
-              << targetCaItem.m_caName << "?" << std::endl;
-    std::string listOption;
-    getline(std::cin, listOption);
-    if (listOption == "A" || listOption == "a") {
-      // should directly send _PROBE or _NEW
+
+    if (targetCaItem.m_isListEnabled) {
+      std::cerr << "This CA provides several sub-namepace CAs \n"
+                << "Do you want to (A) get a certificate from " << targetCaItem.m_caName << "directly? \n"
+                << "Or (B) get a certificate from one of its sub-namespace CAs? \n"
+                << "Please type in your choice (A or B) \n";
+      std::string listOption;
+      getline(std::cin, listOption);
+      if (listOption == "A" || listOption == "a") {
+        listFirst = false;
+      }
+      else if (listOption == "B" || listOption == "b") {
+        listFirst = true;
+        std::string additionalInfo = "";
+        if (targetCaItem.m_targetedList != "") {
+          std::cerr << "Step " << nStep++
+                    << ": Enter nothing if you want to see all available sub-namespace CAs"
+                    << " or follow the instruction to get a recommended CA\n"
+                    << "\t" << targetCaItem.m_targetedList << std::endl;
+          getline(std::cin, additionalInfo);
+        }
+        client.requestList(targetCaItem, additionalInfo,
+                           bind(&ClientTool::listCb, &tool, _1, _2, _3, targetCaItem),
+                           bind(&ClientTool::errorCb, &tool, _1));
+      }
+      else {
+        std::cerr << "Your input is not an option." << std::endl;
+        return 1;
+      }
+    }
+    if (!listFirst) {
       if (targetCaItem.m_probe != "") {
-        std::cerr <<"Step " << nStep++ << ": Probe Requirement-" << targetCaItem.m_probe << std::endl;
+        std::cerr << "Step " << nStep++ << ": Probe Requirement-" << targetCaItem.m_probe << std::endl;
         std::string probeInfo;
         getline(std::cin, probeInfo);
         client.sendProbe(targetCaItem, probeInfo,
@@ -336,7 +362,7 @@
                          bind(&ClientTool::errorCb, &tool, _1));
       }
       else {
-        std::cerr <<"Step " << nStep++ << ": Please type in the identity name" << std::endl;
+        std::cerr << "Step " << nStep++ << ": Please type in the identity name\n";
         std::string nameComponent;
         getline(std::cin, nameComponent);
         Name identityName = targetCaItem.m_caName.getPrefix(-1);
@@ -346,22 +372,6 @@
                        bind(&ClientTool::errorCb, &tool, _1));
       }
     }
-    else if (listOption == "B" || listOption == "b") {
-      std::string additionalInfo = "";
-      if (targetCaItem.m_targetedList != "") {
-        std::cerr <<"Step " << nStep++
-                  << ": Enter nothing if you want to see all available sub-namespace CAs"
-                  << "or follow the instruction to get a recommended CA\n"
-                  << "\t" << targetCaItem.m_targetedList << std::endl;
-        getline(std::cin, additionalInfo);
-      }
-      client.requestList(targetCaItem, additionalInfo,
-                         bind(&ClientTool::listCb, &tool, _1, _2, _3, targetCaItem),
-                         bind(&ClientTool::errorCb, &tool, _1));
-    }
-    else {
-      std::cerr << "Your input is not an option." << std::endl;
-    }
   }
 
   face.processEvents();
@@ -371,8 +381,7 @@
 } // namespace ndncert
 } // namespace ndn
 
-int
-main(int argc, char* argv[])
+int main(int argc, char* argv[])
 {
   return ndn::ndncert::main(argc, argv);
 }