Add support for authentication without time permits

Added code to ignore time permits when usePermits = false is specified in client settings.
Fixed bug in JSON parser when reading excaped symbols.

Closes: MAASMOB-29
diff --git a/src/json/reader.inl b/src/json/reader.inl
index c903f75..9211675 100644
--- a/src/json/reader.inl
+++ b/src/json/reader.inl
@@ -303,10 +303,13 @@
 }
 
 static void ConsumeUnicode(std::istream& str, std::vector<utf8::uint16_t>& uni16) {
-    str >> std::hex;
-    utf8::uint16_t cp;
-    str >> cp;
-    str >> std::dec;
+    char bytes[4];
+    memset(bytes, 0, sizeof(bytes));
+    str.get(bytes[0]);
+    str.get(bytes[1]);
+    str.get(bytes[2]);
+    str.get(bytes[3]);
+    utf8::uint16_t cp = (bytes[0] - '0') << 12 | (bytes[1] - '0') << 8 | (bytes[2] - '0') << 4 | (bytes[3] - '0');
     uni16.push_back(cp);
 }
 
diff --git a/src/mpin_crypto_non_tee.cpp b/src/mpin_crypto_non_tee.cpp
index cd6848a..77cdbc0 100644
--- a/src/mpin_crypto_non_tee.cpp
+++ b/src/mpin_crypto_non_tee.cpp
@@ -201,20 +201,26 @@
         return Status(Status::CRYPTO_ERROR, String("Session is not opened or not initialized"));
     }
 
-    // Combine time permit shares
-    if(timePermitShares.size() != 2)
-    {
-        return Status(Status::CRYPTO_ERROR, String().Format("Expecting 2 time permit shares (provided=%d)", (int) timePermitShares.size()));
-    }
-
-    Octet tp1(timePermitShares[0]);
-    Octet tp2(timePermitShares[1]);
     Octet timePermit(Octet::TOKEN_SIZE);
 
-    int res = MPIN_RECOMBINE_G1(&tp1, &tp2, &timePermit);
-    if(res)
+    // Valid date (date != 0) means authentication *with* time permit and 2 time permit shares are expected
+    // Invalid date (date == 0) means authentication with *no* time permit and time permit shares are ignored
+    if(date != 0)
     {
-        return Status(Status::CRYPTO_ERROR, String().Format("MPIN_RECOMBINE_G1() failed with code %d", res));
+        // Combine time permit shares
+        if(timePermitShares.size() != 2)
+        {
+            return Status(Status::CRYPTO_ERROR, String().Format("Expecting 2 time permit shares (provided=%d)", (int) timePermitShares.size()));
+        }
+
+        Octet tp1(timePermitShares[0]);
+        Octet tp2(timePermitShares[1]);
+
+        int res = MPIN_RECOMBINE_G1(&tp1, &tp2, &timePermit);
+        if(res)
+        {
+            return Status(Status::CRYPTO_ERROR, String().Format("MPIN_RECOMBINE_G1() failed with code %d", res));
+        }
     }
 
     // Get the stored token
@@ -246,7 +252,7 @@
     Octet ut(Octet::TOKEN_SIZE);
 
     // Authentication pass 1
-    res = MPIN_CLIENT_1(date, &cid, &rng, &x, pin.GetHash(), &token, &clientSecret, &u, &ut, &timePermit);
+    int res = MPIN_CLIENT_1(date, &cid, &rng, &x, pin.GetHash(), &token, &clientSecret, &u, &ut, &timePermit);
     if(res)
     {
         return Status(Status::CRYPTO_ERROR, String().Format("MPIN_CLIENT_1() failed with code %d", res));
diff --git a/src/mpin_sdk.cpp b/src/mpin_sdk.cpp
index a441448..3f94c73 100644
--- a/src/mpin_sdk.cpp
+++ b/src/mpin_sdk.cpp
@@ -985,6 +985,12 @@
         return s;
     }
 
+    bool useTimePermits = m_clientSettings.GetBoolParam("usePermits", true);
+    if(!useTimePermits)
+    {
+        return Status::OK;
+    }
+
     // Request a time permit share from the customer's D-TA and a signed request for a time permit share from CertiVox's D-TA.
     String mpinIdHex = user->GetMPinIdHex();
     String url = String().Format("%s/%s", m_clientSettings.GetStringParam("timePermitsURL"), mpinIdHex.c_str());
@@ -1073,8 +1079,10 @@
         return s;
     }
 
+    bool useTimePermits = m_clientSettings.GetBoolParam("usePermits", true);
+
     // Check if time permit was obtained from StartAuthentication
-    if(user->m_timePermitShare1.empty() || user->m_timePermitShare2.empty())
+    if(useTimePermits && (user->m_timePermitShare1.empty() || user->m_timePermitShare2.empty()))
     {
         return Status(Status::FLOW_ERROR, String().Format("Cannot finish user '%s' authentication: Invalid time permit", user->GetId().c_str()));
     }
@@ -1088,10 +1096,13 @@
     }
 
     std::vector<String> timePermitShares;
-    timePermitShares.push_back(user->m_timePermitShare1);
-    timePermitShares.push_back(user->m_timePermitShare2);
-
-	int date =  user->GetTimePermitCache().GetDate();
+    int date = 0;
+    if(useTimePermits)
+    {
+        timePermitShares.push_back(user->m_timePermitShare1);
+        timePermitShares.push_back(user->m_timePermitShare2);
+    	date = user->GetTimePermitCache().GetDate();
+    }
 	
     // Authentication pass 1
     String u, ut;
diff --git a/tests/cmdline_test.cpp b/tests/cmdline_test.cpp
index 7ababfa..6957afd 100644
--- a/tests/cmdline_test.cpp
+++ b/tests/cmdline_test.cpp
@@ -45,6 +45,7 @@
     Backend backends[] = 
     {
         {"https://m-pindemo.certivox.org"},
+        //{"http://192.168.10.159:8001"},
         //{"http://ec2-54-77-232-113.eu-west-1.compute.amazonaws.com", "/rps/"},
         //{"https://mpindemo-qa-v3.certivox.org", "rps"},
     };