Committing updates.

This commit is contained in:
Преподобный Ален
2022-10-25 23:04:26 +03:00
parent e5764c6226
commit a816f9d473
5 changed files with 381 additions and 191 deletions

View File

@@ -60,6 +60,76 @@ namespace Apostol {
}
//--------------------------------------------------------------------------------------------------------------
int CheckSum(const CString &Sum) {
if (Sum.IsEmpty())
return 0;
size_t whole = 0, fractional = 0, delimiter = 0;
size_t pos = 0;
TCHAR ch;
ch = Sum.at(pos);
while (ch != 0) {
if (IsNumeral(ch)) {
if (delimiter == 0)
whole++;
else
fractional++;
} else if (ch == '.') {
delimiter++;
} else if (ch == ' ') {
break;
} else {
return -1;
}
ch = Sum.at(++pos);
}
if (whole == 0 || delimiter > 1 || fractional > 8)
return -1;
return 1;
}
//--------------------------------------------------------------------------------------------------------------
int VerifyDate(const CString &Date, CDateTime &Result) {
if (!Date.IsEmpty()) {
if (Date.Length() < 10)
return 0;
CString StrDate(Date);
int pos = 0;
TCHAR ch = StrDate.at(pos);
while (ch != 0 && (IsNumeral(ch) || ((pos == 4 || pos == 7) && (ch == '-' || ch == '/')) ||
(pos == 10 && ch == ' ') || ((pos == 13 || pos == 16) && ch == ':'))) {
ch = StrDate.at(++pos);
}
if (pos == 10)
StrDate << " 00:00:00";
if (StrDate.Length() != 19 && StrDate.Length() != 23) {
return 0;
}
try {
if ((Result = StrToDateTimeDef(StrDate.c_str(), 0, "%04d-%02d-%02d %02d:%02d:%02d")) == 0)
return -1;
return 1;
}
catch (...) {
return 0;
}
}
return 0;
}
//--------------------------------------------------------------------------------------------------------------
CDateTime StringToDate(const CString &Value, const CString &Format) {
return StrToDateTimeDef(Value.c_str(), 0, Format.c_str());
}
@@ -77,6 +147,148 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
CDealOrder DealData::StringToOrder(const CString &Value) {
const CString &S = Value.Lower();
if (S == "create") {
return doCreate;
} else if (S == "created") {
return doCreated;
} else if (S == "pay") {
return doPay;
} else if (S == "paid") {
return doPaid;
} else if (S == "complete") {
return doComplete;
} else if (S == "completed") {
return doCompleted;
} else if (S == "cancel") {
return doCancel;
} else if (S == "canceled") {
return doCanceled;
} else if (S == "execute") {
return doExecute;
} else if (S == "executed") {
return doExecuted;
} else if (S == "delete") {
return doDelete;
} else if (S == "deleted") {
return doDeleted;
} else if (S == "fail") {
return doFail;
} else if (S == "failed") {
return doFailed;
} else if (S == "feedback") {
return doFeedback;
} else {
throw ExceptionFrm("Invalid deal order value: \"%s\".", Value.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CString DealData::OrderToString(CDealOrder Order) {
switch (Order) {
case doCreate:
return "Create";
case doCreated:
return "Created";
case doPay:
return "Pay";
case doPaid:
return "Paid";
case doComplete:
return "Complete";
case doCompleted:
return "Completed";
case doCancel:
return "Cancel";
case doCanceled:
return "Canceled";
case doExecute:
return "Execute";
case doExecuted:
return "Executed";
case doDelete:
return "Delete";
case doDeleted:
return "Deleted";
case doFail:
return "Fail";
case doFailed:
return "Failed";
case doFeedback:
return "Feedback";
default:
return "Unknown";
}
}
//--------------------------------------------------------------------------------------------------------------
CDealType DealData::StringToType(const CString &Value) {
const auto &status = Value.Lower();
if (status.Find("prepayment") != CString::npos) {
return dtPrepayment;
} else if (status.Find("postpayment") != CString::npos) {
return dtPostpayment;
} else {
throw ExceptionFrm(R"(Invalid order type value: "%s".)", status.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CString DealData::TypeToString(CDealType Type) {
switch (Type) {
case dtPrepayment:
return "Prepayment";
case dtPostpayment:
return "Postpayment";
default:
return "Unknown";
}
}
//--------------------------------------------------------------------------------------------------------------
CString DealData::TypeCodeToString(const CString &Code) {
if (Code == "prepayment.deal") {
return {"Prepayment"};
} else if (Code == "postpayment.deal") {
return {"Postpayment"};
} else {
throw ExceptionFrm(R"(Invalid type code value: "%s".)", Code.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CFeedBackStatus DealData::StringToFeedBackStatus(const CString &Value) {
const CString &Status = Value.Lower();
if (Status == "negative") {
return fsNegative;
} else if (Status == "neutral") {
return fsNeutral;
} else if (Status == "positive") {
return fsPositive;
} else {
throw ExceptionFrm(R"(Invalid feedback status value: "%s".)", Status.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CString DealData::FeedBackStatusToString(CFeedBackStatus Status) {
switch (Status) {
case fsNegative:
return "Negative";
case fsNeutral:
return "Neutral";
case fsPositive:
return "Positive";
default:
return "Unknown";
}
}
//--------------------------------------------------------------------------------------------------------------
CString DealData::GetStringData() const {
CString Data;
@@ -146,148 +358,6 @@ namespace Apostol {
}
//--------------------------------------------------------------------------------------------------------------
CDealOrder CDeal::StringToOrder(const CString &Value) {
const CString &S = Value.Lower();
if (S == "create") {
return doCreate;
} else if (S == "created") {
return doCreated;
} else if (S == "pay") {
return doPay;
} else if (S == "paid") {
return doPaid;
} else if (S == "complete") {
return doComplete;
} else if (S == "completed") {
return doCompleted;
} else if (S == "cancel") {
return doCancel;
} else if (S == "canceled") {
return doCanceled;
} else if (S == "execute") {
return doExecute;
} else if (S == "executed") {
return doExecuted;
} else if (S == "delete") {
return doDelete;
} else if (S == "deleted") {
return doDeleted;
} else if (S == "fail") {
return doFail;
} else if (S == "failed") {
return doFailed;
} else if (S == "feedback") {
return doFeedback;
} else {
throw ExceptionFrm("Invalid deal order value: \"%s\".", Value.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CString CDeal::OrderToString(CDealOrder Order) {
switch (Order) {
case doCreate:
return "Create";
case doCreated:
return "Created";
case doPay:
return "Pay";
case doPaid:
return "Paid";
case doComplete:
return "Complete";
case doCompleted:
return "Completed";
case doCancel:
return "Cancel";
case doCanceled:
return "Canceled";
case doExecute:
return "Execute";
case doExecuted:
return "Executed";
case doDelete:
return "Delete";
case doDeleted:
return "Deleted";
case doFail:
return "Fail";
case doFailed:
return "Failed";
case doFeedback:
return "Feedback";
default:
return "Unknown";
}
}
//--------------------------------------------------------------------------------------------------------------
CDealType CDeal::StringToType(const CString &Value) {
const auto &status = Value.Lower();
if (status.Find("prepayment") != CString::npos) {
return dtPrepayment;
} else if (status.Find("postpayment") != CString::npos) {
return dtPostpayment;
} else {
throw ExceptionFrm(R"(Invalid order type value: "%s".)", status.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CString CDeal::TypeToString(CDealType Type) {
switch (Type) {
case dtPrepayment:
return "Prepayment";
case dtPostpayment:
return "Postpayment";
default:
return "Unknown";
}
}
//--------------------------------------------------------------------------------------------------------------
CString CDeal::TypeCodeToString(const CString &Code) {
if (Code == "prepayment.deal") {
return {"Prepayment"};
} else if (Code == "postpayment.deal") {
return {"Postpayment"};
} else {
throw ExceptionFrm(R"(Invalid type code value: "%s".)", Code.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CFeedBackStatus CDeal::StringToFeedBackStatus(const CString &Value) {
const CString &Status = Value.Lower();
if (Status == "negative") {
return fsNegative;
} else if (Status == "neutral") {
return fsNeutral;
} else if (Status == "positive") {
return fsPositive;
} else {
throw ExceptionFrm(R"(Invalid feedback status value: "%s".)", Status.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
CString CDeal::FeedBackStatusToString(CFeedBackStatus Status) {
switch (Status) {
case fsNegative:
return "Negative";
case fsNeutral:
return "Neutral";
case fsPositive:
return "Positive";
default:
return "Unknown";
}
}
//--------------------------------------------------------------------------------------------------------------
CString CDeal::GetHashData() {
return m_Data.GetStringData();
}
@@ -352,7 +422,7 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
std::string CDeal::get_payment_ek(const std::string &key1, const std::string &key2, std::string &key3,
uint8_t version_key, uint8_t version_script) {
uint8_t version_key, uint8_t version_script) {
CWitness Witness(ec_public(key1), ec_public(key2), key3.empty() ? to_public_ek(version_key) : ec_public(key3));
@@ -366,7 +436,7 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
std::string CDeal::get_payment_hd(const std::string &key1, const std::string &key2, std::string &key3,
uint64_t prefixes, uint8_t version_script) {
uint64_t prefixes, uint8_t version_script) {
CWitness Witness(ec_public(key1), ec_public(key2), key3.empty() ? to_public_hd(prefixes) : ec_public(key3));
@@ -380,7 +450,7 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
std::string CDeal::get_payment_witness(const std::string &key1, const std::string &key2, std::string &key3,
uint64_t prefixes) {
uint64_t prefixes) {
CWitness Witness(ec_public(key1), ec_public(key2), key3.empty() ? to_public_hd(prefixes) : ec_public(key3));
@@ -392,7 +462,7 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
CString CDeal::GetPaymentEK(const CString &Key1, const CString &Key2, CString &Key3,
uint8_t version_key, uint8_t version_script) {
uint8_t version_key, uint8_t version_script) {
std::string key3(Key3);
@@ -405,7 +475,7 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
CString CDeal::GetPaymentHD(const CString &Key1, const CString &Key2, CString &Key3,
uint64_t prefixes, uint8_t version_script) {
uint64_t prefixes, uint8_t version_script) {
std::string key3(Key3);
@@ -434,11 +504,18 @@ namespace Apostol {
const auto& deal = node["deal"];
if (deal) {
m_Data.Order = StringToOrder(deal["order"].as<std::string>());
m_Data.Type = StringToType(deal["type"].as<std::string>());
m_Data.Order = CDealData::StringToOrder(deal["order"].as<std::string>());
m_Data.Type = CDealData::StringToType(deal["type"].as<std::string>());
m_Data.At = deal["at"].as<std::string>();
m_Data.Date = UTCFormat(deal["date"].as<std::string>());
const auto &date = deal["date"].as<std::string>();
CDateTime Date;
if (VerifyDate(date, Date) != 1)
throw ExceptionFrm("Invalid deal date format: %s.", date.c_str());
m_Data.Date = DateToString(Date);
const auto& seller = deal["seller"];
m_Data.Seller.Address = seller["address"].as<std::string>();
@@ -469,19 +546,42 @@ namespace Apostol {
if (payment["address"])
m_Data.Payment.Address = payment["address"].as<std::string>();
if (payment["until"])
m_Data.Payment.Until = UTCFormat(payment["until"].as<std::string>());
if (payment["until"]) {
const auto &until = payment["until"].as<std::string>();
m_Data.Payment.Sum = BTCFormat(payment["sum"].as<std::string>());
CDateTime Until;
if (VerifyDate(until, Until) != 1)
throw ExceptionFrm("Invalid until date format: %s.", until.c_str());
m_Data.Payment.Until = DateToString(Until);
} else {
m_Data.Payment.Until = DateToString(Date + 1); // 1 day
}
const auto &sum = payment["sum"].as<std::string>();
if (CheckSum(sum) != 1)
throw ExceptionFrm("Invalid format sum: %s.", sum.c_str());
m_Data.Payment.Sum = BTCFormat(sum);
}
const auto& feedback = deal["feedback"];
if (feedback) {
if (feedback["leave-before"])
m_Data.FeedBack.LeaveBefore = UTCFormat(feedback["leave-before"].as<std::string>());
if (feedback["leave-before"]) {
const auto &leave_before = feedback["leave-before"].as<std::string>();
CDateTime LeaveBefore;
if (VerifyDate(leave_before, LeaveBefore) != 1)
throw ExceptionFrm("Invalid leave before date format: %s.", leave_before.c_str());
m_Data.FeedBack.LeaveBefore = DateToString(LeaveBefore);
} else {
m_Data.FeedBack.LeaveBefore = DateToString(Date + 14); // 14 day
}
if (feedback["status"])
m_Data.FeedBack.Status = StringToFeedBackStatus(feedback["status"].as<std::string>());
m_Data.FeedBack.Status = CDealData::StringToFeedBackStatus(feedback["status"].as<std::string>());
if (feedback["refund"])
m_Data.FeedBack.Refund = feedback["refund"].as<std::string>();
@@ -500,14 +600,6 @@ namespace Apostol {
m_Data.Error.Message = error["message"].as<std::string>();
}
const CDateTime Date = StringToDate(m_Data.Date);
if (m_Data.Payment.Until.IsEmpty())
m_Data.Payment.Until = DateToString(Date + (CDateTime) 3600 / SecsPerDay); // 60 min
if (m_Data.FeedBack.LeaveBefore.IsEmpty())
m_Data.FeedBack.LeaveBefore = DateToString(Date + 1);
m_Data.Code = GetCode();
} else
throw ExceptionFrm("Invalid YAML format: Need node \"deal\".");
@@ -515,14 +607,14 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
void CDeal::SetOrder(YAML::Node &Node, CDealOrder Order) {
Node["deal"]["order"] = CDeal::OrderToString(Order).c_str();
Node["deal"]["order"] = CDealData::OrderToString(Order).c_str();
}
//--------------------------------------------------------------------------------------------------------------
void CDeal::AddFeedback(YAML::Node &Node, CFeedBackStatus Status, const CString &Comments) {
YAML::Node Deal = Node["deal"];
YAML::Node Feedback = Deal["feedback"];
Feedback["status"] = CDeal::FeedBackStatusToString(Status).c_str();
Feedback["status"] = CDealData::FeedBackStatusToString(Status).c_str();
if (!Comments.IsEmpty())
Feedback["comments"] = Comments.c_str();
}

View File

@@ -163,7 +163,7 @@ namespace Apostol {
//--------------------------------------------------------------------------------------------------------------
enum CDealOrder { doCreate = 0, doCreated, doPay, doPaid, doComplete, doCompleted, doCancel, doCanceled,
doExecute, doExecuted, doDelete, doDeleted, doFail, doFailed, doFeedback };
doExecute, doExecuted, doDelete, doDeleted, doFail, doFailed, doFeedback };
//--------------------------------------------------------------------------------------------------------------
typedef struct DealData {
@@ -214,6 +214,76 @@ namespace Apostol {
CString GetStringData() const;
static CDealOrder StringToOrder(const CString &Value);
static CString OrderToString(CDealOrder Order);
static CDealType StringToType(const CString &Value);
static CString TypeToString(CDealType Type);
static CString TypeCodeToString(const CString &Code);
static CFeedBackStatus StringToFeedBackStatus(const CString &Value);
static CString FeedBackStatusToString(CFeedBackStatus Status);
friend CJSON &operator>> (const DealData &LS, CJSON &RM) {
CString R;
RM.Object().AddPair("order", OrderToString(LS.Order));
RM.Object().AddPair("type", TypeToString(LS.Type));
RM.Object().AddPair("code", LS.Code);
RM.Object().AddPair("at", LS.At);
RM.Object().AddPair("date", LS.Date);
CJSON jsonSeller(jvtObject);
jsonSeller.Object().AddPair("address", LS.Seller.Address);
LS.Seller.Rating >> R;
jsonSeller.Object().AddPair("rating", R);
RM.Object().AddPair("seller", jsonSeller.Object());
CJSON jsonCustomer(jvtObject);
jsonCustomer.Object().AddPair("address", LS.Customer.Address);
LS.Customer.Rating >> R;
jsonCustomer.Object().AddPair("rating", R);
RM.Object().AddPair("customer", jsonCustomer.Object());
CJSON jsonPayment(jvtObject);
jsonPayment.Object().AddPair("address", LS.Payment.Address);
jsonPayment.Object().AddPair("until", LS.Payment.Until);
jsonPayment.Object().AddPair("sum", LS.Payment.Sum);
RM.Object().AddPair("payment", jsonPayment.Object());
CJSON jsonFeedback(jvtObject);
jsonFeedback.Object().AddPair("leave_before", LS.FeedBack.LeaveBefore);
if (LS.Type == dtPostpayment && LS.Order >= doComplete) {
jsonFeedback.Object().AddPair("status", FeedBackStatusToString(LS.FeedBack.Status));
if (!LS.FeedBack.Refund.IsEmpty())
jsonFeedback.Object().AddPair("refund", LS.FeedBack.Refund);
if (!LS.FeedBack.Comments.IsEmpty())
jsonFeedback.Object().AddPair("comments", LS.FeedBack.Comments);
}
RM.Object().AddPair("feedback", jsonFeedback.Object());
if (!LS.Error.Message.IsEmpty()) {
CJSON jsonError(jvtObject);
jsonError.Object().AddPair("message", LS.Error.Message);
RM.Object().AddPair("error", jsonError.Object());
}
return RM;
};
} CDealData, *PDealData;
//--------------------------------------------------------------------------------------------------------------
@@ -249,7 +319,7 @@ namespace Apostol {
uint8_t version_script = payment_address::mainnet_p2sh);
std::string get_payment_witness(const std::string &key1, const std::string &key2, std::string &key3,
uint64_t prefixes = hd_private::mainnet);
uint64_t prefixes = hd_private::mainnet);
public:
@@ -273,16 +343,6 @@ namespace Apostol {
CString GetPaymentSW(const CString &Key1, const CString &Key2, CString &Key3,
uint64_t prefixes = hd_private::mainnet);
static CDealOrder StringToOrder(const CString &Value);
static CString OrderToString(CDealOrder Order);
static CDealType StringToType(const CString &Value);
static CString TypeToString(CDealType Type);
static CString TypeCodeToString(const CString &Code);
static CFeedBackStatus StringToFeedBackStatus(const CString &Value);
static CString FeedBackStatusToString(CFeedBackStatus Status);
CDealOrder Order() const { return m_Data.Order; }
void Order(CDealOrder Value) { m_Data.Order = Value; }
@@ -300,6 +360,11 @@ namespace Apostol {
return *this;
}
friend CJSON &operator>> (const CDeal &LS, CJSON &RM) {
LS.m_Data >> RM;
return RM;
};
};
//--------------------------------------------------------------------------------------------------------------

View File

@@ -80,6 +80,23 @@ namespace Apostol {
}
//--------------------------------------------------------------------------------------------------------------
int CWebService::CurrentContextIndex(const CString &Params) {
int index = 0;
while (index < m_Servers.Count()) {
const auto &caContext = m_Servers[index].Value();
if (caContext.Status() == Context::csRunning) {
if (Params == caContext.Name() || Params == caContext.URL().Origin()) {
return index;
}
}
index++;
}
return -1;
}
//--------------------------------------------------------------------------------------------------------------
bool CWebService::DoProxyExecute(CTCPConnection *AConnection) {
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
@@ -228,7 +245,10 @@ namespace Apostol {
const auto &pgpValue = pServerRequest->Params["pgp"];
const auto &caServerParam = pServerRequest->Params["server"];
const auto &caServer = caServerParam.IsEmpty() ? m_CurrentServer.URL().Origin() : caServerParam;
const auto index = CurrentContextIndex(caServerParam);
const auto &caContext = index == -1 ? m_CurrentServer : m_Servers[index].Value();
const auto &caServer = caContext.URL().Origin();
CLocation Location(caServer);
@@ -424,7 +444,7 @@ namespace Apostol {
CHTTPRequest::Prepare(pProxyRequest, "POST", URI.c_str());
pProxyRequest->AddHeader("Authorization", "Bearer " + m_CurrentServer.Tokens()["access_token"]);
pProxyRequest->AddHeader("Authorization", "Bearer " + caContext.Tokens()["access_token"]);
if (!caModuleAddress.IsEmpty())
pProxyRequest->AddHeader("Module-Address", caModuleAddress);
@@ -464,7 +484,10 @@ namespace Apostol {
const auto &pgpValue = pServerRequest->Params["pgp"];
const auto &caServerParam = pServerRequest->Params["server"];
const auto &caServer = caServerParam.IsEmpty() ? m_CurrentServer.URL().Origin() : caServerParam;
const auto index = CurrentContextIndex(caServerParam);
const auto &caContext = index == -1 ? m_CurrentServer : m_Servers[index].Value();
const auto &caServer = caContext.URL().Origin();
CLocation Location(caServer);
@@ -764,7 +787,7 @@ namespace Apostol {
Node = YAML::Load(pServerRequest->Content.c_str());
}
const auto &BTCKeys = m_CurrentServer.BTCKeys();
const auto &BTCKeys = caContext.BTCKeys();
if (BTCKeys.Count() < 2)
throw ExceptionFrm("Bitcoin keys cannot be empty.");
@@ -847,7 +870,7 @@ namespace Apostol {
CHTTPRequest::Prepare(pProxyRequest, "POST", URI.c_str());
pProxyRequest->AddHeader("Authorization", "Bearer " + m_CurrentServer.Tokens()["access_token"]);
pProxyRequest->AddHeader("Authorization", "Bearer " + caContext.Tokens()["access_token"]);
if (!caModuleAddress.IsEmpty())
pProxyRequest->AddHeader("Module-Address", caModuleAddress);
@@ -894,7 +917,10 @@ namespace Apostol {
const auto &pgpValue = pServerRequest->Params["pgp"];
const auto &caServerParam = pServerRequest->Params["server"];
const auto &caServer = caServerParam.IsEmpty() ? m_CurrentServer.URL().Origin() : caServerParam;
const auto index = CurrentContextIndex(caServerParam);
const auto &caContext = index == -1 ? m_CurrentServer : m_Servers[index].Value();
const auto &caServer = caContext.URL().Origin();
CLocation Location(caServer);
@@ -914,7 +940,7 @@ namespace Apostol {
CHTTPRequest::Prepare(pProxyRequest, Method.c_str(), URI.c_str(), caContentType.c_str());
pProxyRequest->AddHeader("Authorization", "Bearer " + m_CurrentServer.Tokens()["access_token"]);
pProxyRequest->AddHeader("Authorization", "Bearer " + caContext.Tokens()["access_token"]);
if (!caModuleAddress.IsEmpty())
pProxyRequest->AddHeader("Module-Address", caModuleAddress);
@@ -944,10 +970,14 @@ namespace Apostol {
return;
}
auto &Keys = m_CurrentServer.PGP();
const auto &caServerParam = pRequest->Params["server"];
int index = CurrentContextIndex(caServerParam);
const auto &caContext = index == -1 ? m_CurrentServer : m_Servers[index].Value();
int index = 0;
while (index < Keys.Count() && Keys[index].Name != m_CurrentServer.Name()) {
auto &Keys = caContext.PGP();
index = 0;
while (index < Keys.Count() && Keys[index].Name != caContext.Name()) {
index++;
}

View File

@@ -58,6 +58,8 @@ namespace Apostol {
void FetchPGP(CContext &Context);
int CurrentContextIndex(const CString &Params);
protected:
CHTTPProxy *GetProxy(CHTTPServerConnection *AConnection);

View File

@@ -605,6 +605,7 @@ namespace Apostol {
if (!pServerRequest->Content.IsEmpty() && Action != "status") {
const auto utc = UTC();
const auto &ContentType = pServerRequest->Headers.Values(_T("content-type"));
if (ContentType.Find("application/x-www-form-urlencoded") == 0) {
@@ -649,7 +650,7 @@ namespace Apostol {
Deal["type"] = formType.c_str();
Deal["at"] = formAt.c_str();
Deal["date"] = formDate.IsEmpty() ? UTCFormat(DateToString(UTC())).c_str() : formDate.c_str();
Deal["date"] = formDate.IsEmpty() ? UTCFormat(DateToString(utc)).c_str() : formDate.c_str();
YAML::Node Seller = Deal["seller"];
@@ -736,7 +737,7 @@ namespace Apostol {
Deal["type"] = formType.c_str();
Deal["at"] = formAt.c_str();
Deal["date"] = formDate.IsEmpty() ? UTCFormat(DateToString(UTC())).c_str() : formDate.c_str();
Deal["date"] = formDate.IsEmpty() ? UTCFormat(DateToString(utc)).c_str() : formDate.c_str();
YAML::Node Seller = Deal["seller"];
@@ -838,7 +839,7 @@ namespace Apostol {
Deal["type"] = formType.c_str();
Deal["at"] = formAt.c_str();
Deal["date"] = formDate.IsEmpty() ? UTCFormat(DateToString(UTC())).c_str() : formDate.c_str();
Deal["date"] = formDate.IsEmpty() ? UTCFormat(DateToString(utc)).c_str() : formDate.c_str();
YAML::Node Seller = Deal["seller"];