This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

#5657 Fleshed out the implementation of SerialKey

  • Loading branch information...
Jerry (Xinyu Hou)
Jerry (Xinyu Hou) committed Oct 13, 2016
1 parent 92a8855 commit 2a452307cd00181cc95a6e9e60124f6142bf0398
Showing with 185 additions and 17 deletions.
  1. +154 −13 src/lib/shared/SerialKey.cpp
  2. +31 −4 src/lib/shared/SerialKey.h
@@ -17,44 +17,185 @@
#include "SerialKey.h"
+#include <vector>
+
+using namespace std;
+
SerialKey::SerialKey(std::string serial) :
m_userLimit(1),
- m_warnTime(1),
- m_expireTime(1),
- m_trial(true)
+ m_warnTime(0),
+ m_expireTime(0),
+ m_edition(kBasic),
+ m_trial(true),
+ m_valid(false)
{
- m_userLimit = 1;
- m_warnTime = 1;
- m_expireTime = 1;
- m_trial = true;
+ string plainText = decode(serial);
+ if (!plainText.empty()) {
+ parse(serial);
+ }
}
-
+
bool
SerialKey::isValid(unsigned long long currentTime) const
{
- return true;
+ bool result = false;
+
+ if (m_valid) {
+ if (m_trial) {
+ if (currentTime < m_expireTime) {
+ result = true;
+ }
+ }
+ else {
+ result = true;
+ }
+ }
+
+ return result;
}
bool
SerialKey::isExpiring(unsigned long long currentTime) const
{
- return true;
+ bool result = false;
+
+ if (m_valid) {
+ if (m_warnTime < currentTime && currentTime < m_expireTime) {
+ result = true;
+ }
+ }
+
+ return result;
}
bool
SerialKey::isExpired(unsigned long long currentTime) const
{
- return true;
+ bool result = false;
+
+ if (m_valid) {
+ if (currentTime > m_expireTime) {
+ result = true;
+ }
+ }
+
+ return result;
}
bool
SerialKey::isTrial() const
{
- return true;
+ return m_trial;
}
int
SerialKey::edition() const
{
- return 1;
+ return m_edition;
+}
+
+unsigned long long
+SerialKey::dayLeft(unsigned long long currentTime) const
+{
+ unsigned long long timeLeft = 0;
+ if (m_expireTime > currentTime) {
+ timeLeft = m_expireTime - currentTime;
+ }
+
+ unsigned long long day = 60 * 60 * 24;
+
+ return timeLeft / day;
+}
+
+std::string
+SerialKey::decode(const std::string& serial) const
+{
+ static const char* const lut = "0123456789ABCDEF";
+ string output;
+ size_t len = serial.length();
+ if (len & 1) {
+ return output;
+ }
+
+ output.reserve(len / 2);
+ for (size_t i = 0; i < len; i += 2) {
+
+ char a = serial[i];
+ char b = serial[i + 1];
+
+ const char* p = std::lower_bound(lut, lut + 16, a);
+ const char* q = std::lower_bound(lut, lut + 16, b);
+
+ if (*q != b || *p != a) {
+ return output;
+ }
+
+ output.push_back(static_cast<char>(((p - lut) << 4) | (q - lut)));
+ }
+
+ return output;
+}
+
+void
+SerialKey::parse(std::string plainSerial)
+{
+ string parityStart = plainSerial.substr(0, 1);
+ string parityEnd = plainSerial.substr(plainSerial.length() - 1, 1);
+
+ // check for parity chars { and }, record parity result, then remove them.
+ if (parityStart == "{" && parityEnd == "}") {
+ plainSerial = plainSerial.substr(1, plainSerial.length() - 2);
+
+ // tokenize serialised subscription.
+ vector<string> parts;
+ std::string::size_type pos = 0;
+ bool look = true;
+ while (look) {
+ std::string::size_type start = pos;
+ pos = plainSerial.find(";", pos);
+ if (pos == string::npos) {
+ pos = plainSerial.length();
+ look = false;
+ }
+ parts.push_back(plainSerial.substr(start, pos - start));
+ pos += 1;
+ }
+
+ if ((parts.size() == 8)
+ && (parts.at(0).find("v1") != string::npos)) {
+ // e.g.: {v1;basic;Bob;1;email;company name;1398297600;1398384000}
+ m_edition = getEdition(parts.at(1));
+ m_name = parts.at(2);
+ sscanf(parts.at(3).c_str(), "%d", &m_userLimit);
+ m_email = parts.at(4);
+ m_company = parts.at(5);
+ sscanf(parts.at(6).c_str(), "%lld", &m_warnTime);
+ sscanf(parts.at(7).c_str(), "%lld", &m_expireTime);
+ m_valid = true;
+ }
+ else if ((parts.size() == 9)
+ && (parts.at(0).find("v2") != string::npos)) {
+ // e.g.: {v2;trial;basic;Bob;1;email;company name;1398297600;1398384000}
+ m_trial = parts.at(1) == "trial" ? true : false;
+ m_edition = getEdition(parts.at(2));
+ m_name = parts.at(3);
+ sscanf(parts.at(4).c_str(), "%d", &m_userLimit);
+ m_email = parts.at(5);
+ m_company = parts.at(6);
+ sscanf(parts.at(7).c_str(), "%lld", &m_warnTime);
+ sscanf(parts.at(8).c_str(), "%lld", &m_expireTime);
+ m_valid = true;
+ }
+ }
+}
+
+Edition
+SerialKey::getEdition(std::string editionStr)
+{
+ Edition e = kBasic;
+ if (editionStr == "pro") {
+ e = kPro;
+ }
+
+ return e;
}
View
@@ -19,6 +19,15 @@
#include <string>
+#ifdef TEST_ENV
+#include "gtest/gtest_prod.h"
+#endif
+
+enum Edition{
+ kBasic,
+ kPro
+};
+
class SerialKey {
public:
SerialKey(std::string serial);
@@ -28,14 +37,32 @@ class SerialKey {
bool isExpired(unsigned long long currentTime) const;
bool isTrial() const;
int edition() const;
-
+ unsigned long long dayLeft(unsigned long long currentTime) const;
+
+private:
+ std::string decode(const std::string& serial) const;
+ void parse(std::string plainSerial);
+ Edition getEdition(std::string editionStr);
+
+#ifdef TEST_ENV
+private:
+ FRIEND_TEST(SerialKeyTests, decode_empty_returnEmptyString);
+ FRIEND_TEST(SerialKeyTests, decode_invalidDigit_returnEmptyString);
+ FRIEND_TEST(SerialKeyTests, decode_validSerial_returnPlainText);
+ FRIEND_TEST(SerialKeyTests, parse_noParty_invalid);
+ FRIEND_TEST(SerialKeyTests, parse_invalidPartsLenghth_invalid);
+ FRIEND_TEST(SerialKeyTests, parse_validV1Serial_valid);
+ FRIEND_TEST(SerialKeyTests, parse_validV2Serial_valid);
+#endif
+
private:
std::string m_name;
- std::string m_edition;
std::string m_email;
std::string m_company;
int m_userLimit;
- int m_warnTime;
- int m_expireTime;
+ unsigned long long m_warnTime;
+ unsigned long long m_expireTime;
+ Edition m_edition;
bool m_trial;
+ bool m_valid;
};

0 comments on commit 2a45230

Please sign in to comment.