146 #include <irrxml/irrXML.hpp>
163 otErr << __FUNCTION__ <<
": Input string is empty.\n";
167 strOutput.
Set(strInput);
172 otErr << __FUNCTION__ <<
": Input string apparently was encoded and "
173 "then failed decoding. Contents: \n"
184 static char buf[75] =
"";
186 bool bGotLine = strOutput.
sgets(buf, 70);
188 if (!bGotLine)
return false;
190 strFirstLine.
Set(buf);
198 if (!strFirstLine.
Exists() || strFirstLine.
Contains(
"- -"))
return false;
203 OTContract::OTContract()
214 m_strFoldername = foldername;
215 m_strFilename = filename;
217 m_ID.SetString(strID);
224 m_ID.SetString(strID);
234 void OTContract::Initialize()
240 m_strSigHashType = OTIdentifier::DefaultHashAlgorithm;
241 m_strVersion =
"2.0";
249 void OTContract::Release_Contract()
259 m_strSigHashType = OTIdentifier::DefaultHashAlgorithm;
261 m_strRawFile.Release();
265 m_mapConditions.clear();
268 while (!m_mapNyms.empty()) {
273 m_mapNyms.erase(m_mapNyms.begin());
277 void OTContract::Release()
285 OTContract::~OTContract()
291 bool OTContract::SaveToContractFolder()
293 OTString strFoldername(OTFolders::Contract().Get()), strFilename;
295 GetIdentifier(strFilename);
301 otInfo <<
"OTContract::SaveToContractFolder: Saving asset contract to "
304 return SaveContract(strFoldername.Get(), strFilename.
Get());
307 void OTContract::GetFilename(
OTString& strFilename)
const
309 strFilename = m_strFilename;
312 void OTContract::GetFoldername(
OTString& strFoldername)
const
314 strFoldername = m_strFoldername;
319 theIdentifier = m_ID;
322 void OTContract::GetIdentifier(
OTString& theIdentifier)
const
330 bool OTContract::VerifyContract()
334 if (!VerifyContractID()) {
335 otWarn << __FUNCTION__ <<
": Failed verifying contract ID.\n";
343 if (
nullptr == pNym) {
344 otOut << __FUNCTION__
345 <<
": Failed retrieving public nym from contract.\n";
349 if (!VerifySignature(*pNym)) {
352 otOut << __FUNCTION__ <<
": Failed verifying the contract's signature "
353 "against the public key that was retrieved "
354 "from the contract, with key ID: " << strNymID
359 otWarn <<
"\nVerified -- The Contract ID from the wallet matches the "
360 "newly-calculated hash of the contract file.\n"
361 "Verified -- A standard \"contract\" Public Key or x509 Cert WAS "
362 "found inside the contract.\n"
363 "Verified -- And the **SIGNATURE VERIFIED** with THAT key.\n\n";
370 std::string str_Trim(m_strRawFile.Get());
371 std::string str_Trim2 = OTString::trim(str_Trim);
373 OTString strTemp(str_Trim2.c_str());
376 otErr << __FUNCTION__ <<
": Error calculating Contract digest.\n";
379 bool OTContract::VerifyContractID()
const
382 CalculateContractID(newID);
393 if (!(m_ID == newID)) {
396 otOut <<
"\nHashes do NOT match in OTContract::VerifyContractID.\n "
397 "Expected: " << str1 <<
"\n Actual: " << str2
406 otWarn <<
"\nContract ID *SUCCESSFUL* match to "
407 << OTIdentifier::DefaultHashAlgorithm
408 <<
" hash of contract file: " << str1 <<
"\n\n";
415 for (
auto& it : m_mapNyms) {
419 "nullptr pseudonym pointer in OTContract::GetContractPublicNym.\n");
426 if (it.first ==
"signer") {
430 else if (it.first ==
"contract") {
446 for (
auto& it : m_mapNyms) {
450 "nullptr pseudonym pointer in OTContract::GetContractPublicKey.\n");
468 else if (it.first ==
"contract") {
490 "OTContract::SignContract: Error allocating memory for Signature.\n");
492 bool bSigned = SignContract(theNym, *pSig, pPWData);
495 m_listSignatures.push_back(pSig);
497 otErr << __FUNCTION__ <<
": Failure while calling "
498 "SignContract(theNym, *pSig, pPWData)\n";
512 OT_ASSERT_MSG(
nullptr != pSig,
"OTContract::SignContractAuthent: Error "
513 "allocating memory for Signature.\n");
515 bool bSigned = SignContractAuthent(theNym, *pSig, pPWData);
518 m_listSignatures.push_back(pSig);
520 otErr << __FUNCTION__ <<
": Failure while calling "
521 "SignContractAuthent(theNym, *pSig, "
537 m_strSigHashType, pPWData);
546 m_strSigHashType, pPWData);
567 "OTContract::SignWithKey: Error allocating memory for Signature.\n");
569 bool bSigned = SignContract(theKey, *pSig, m_strSigHashType, pPWData);
572 m_listSignatures.push_back(pSig);
574 otErr << __FUNCTION__
575 <<
": Failure while calling SignContract(theNym, *pSig).\n";
665 OTCrypto::It()->SignContract(m_xmlUnsigned, theKey, theSignature,
666 strHashType, pPWData)) {
667 otErr <<
"OTContract::SignContract: "
668 "OTCrypto::It()->SignContract returned false.\n";
681 bool OTContract::SignContract(
const char* szFoldername,
682 const char* szFilename,
690 const char* szFunc =
"OTContract::SignContract";
693 otErr << szFunc <<
": File does not exist: " << szFoldername
694 << OTLog::PathSeparator() << szFilename <<
"\n";
699 szFoldername, szFilename));
701 if (strCertFileContents.length() < 2) {
702 otErr << szFunc <<
": Error reading file: " << szFoldername
703 << OTLog::PathSeparator() << szFilename <<
"\n";
708 "(OTContract::SignContract is trying to read the private key...)");
709 if (
nullptr == pPWData) pPWData = &thePWData;
722 OTCrypto::It()->SignContract(m_xmlUnsigned, m_strSigHashType,
723 strCertFileContents, theSignature,
725 otErr << szFunc <<
": OTCrypto::It()->SignContract returned false, "
726 "using Cert file: " << szFoldername
727 << OTLog::PathSeparator() << szFilename <<
"\n";
738 bool OTContract::VerifySignature(
739 const char* szFoldername,
const char* szFilename,
745 nullptr != szFoldername,
746 "Null foldername pointer passed to OTContract::VerifySignature");
748 nullptr != szFilename,
749 "Null filename pointer passed to OTContract::VerifySignature");
751 const char* szFunc = __FUNCTION__;
754 otInfo << szFunc <<
": Reading public key from certfile in order to verify "
758 otErr << szFunc <<
": File does not exist: " << szFoldername
759 << OTLog::PathSeparator() << szFilename <<
"\n";
764 szFoldername, szFilename));
766 if (strCertFileContents.length() < 2) {
767 otErr << szFunc <<
": Error reading file: " << szFoldername
768 << OTLog::PathSeparator() << szFilename <<
"\n";
773 if (
nullptr == pPWData) pPWData = &thePWData;
776 OTCrypto::It()->VerifySignature(m_xmlUnsigned, m_strSigHashType,
777 strCertFileContents, theSignature,
779 otLog4 << szFunc <<
": OTCrypto::It()->VerifySignature returned false, "
780 "using Cert file: " << szFoldername
781 << OTLog::PathSeparator() << szFilename <<
"\n";
795 const bool bNymID = strNymID.
At(nIndex, cNymID);
797 for (
auto& it : m_listSignatures) {
812 if (VerifySigAuthent(theNym, *pSig, pPWData))
return true;
825 const bool bNymID = strNymID.
At(nIndex, cNymID);
827 for (
auto& it : m_listSignatures) {
842 if (VerifySignature(theNym, *pSig, pPWData))
return true;
851 for (
auto& it : m_listSignatures) {
864 if (VerifySignature(theKey, *pSig, m_strSigHashType,
865 (
nullptr != pPWData) ? pPWData : &thePWData))
887 listOutput, theSignature,
'A');
891 for (
auto& it : listOutput) {
895 if (VerifySignature(*pKey, theSignature, m_strSigHashType,
896 (
nullptr != pPWData) ? pPWData : &thePWData))
904 <<
": Tried to grab a list of keys from this Nym (" << strNymID
905 <<
") which might match this signature, "
906 "but recovered none. Therefore, will attempt to verify using "
907 "the Nym's default public "
908 "AUTHENTICATION key.\n";
914 (
nullptr != pPWData) ? pPWData : &thePWData);
932 listOutput, theSignature,
'S');
936 for (
auto& it : listOutput) {
940 if (VerifySignature(*pKey, theSignature, m_strSigHashType,
941 (
nullptr != pPWData) ? pPWData : &thePWData))
949 <<
": Tried to grab a list of keys from this Nym (" << strNymID
950 <<
") which might match this signature, "
951 "but recovered none. Therefore, will attempt to verify using "
952 "the Nym's default public "
959 (
nullptr != pPWData) ? pPWData : &thePWData);
978 OTCrypto::It()->VerifySignature(
979 m_xmlUnsigned, theKey, theSignature, strHashType,
980 (
nullptr != pPWData) ? pPWData : &thePWData)) {
982 <<
": OTCrypto::It()->VerifySignature returned false.\n";
989 void OTContract::ReleaseSignatures()
992 while (!m_listSignatures.empty()) {
994 m_listSignatures.pop_front();
999 bool OTContract::DisplayStatistics(
OTString& strContents)
const
1003 const_cast<char*>(
"ERROR: OTContract::DisplayStatistics was called "
1004 "instead of a subclass...\n"));
1016 bool OTContract::SaveContents(std::ofstream& ofs)
const
1018 ofs << m_xmlUnsigned;
1024 bool OTContract::SaveContents(
OTString& strContents)
const
1032 bool OTContract::SaveContract()
1035 bool bSuccess = RewriteContract(strTemp);
1038 m_strRawFile.Set(strTemp);
1050 void OTContract::UpdateContents()
1080 const char* szFunc =
"OTContract::SignFlatText";
1084 std::string str_Trim(strFlatText.
Get());
1085 std::string str_Trim2 = OTString::trim(str_Trim);
1087 strFlatText.
Set(str_Trim2.c_str());
1090 const uint32_t lLength = strFlatText.
GetLength();
1092 if ((3 > lLength) || !strFlatText.
At(lLength - 1, cNewline)) {
1094 <<
": Invalid input: text is less than 3 bytes "
1095 "int64_t, or unable to read a byte from the end where "
1096 "a newline is meant to be.\n";
1110 if (
'\n' == cNewline)
1111 strInput = strFlatText;
1113 strInput.
Format(
"%s\n", strFlatText.
Get());
1116 OTPasswordData thePWData(
"Signing flat text (need private key)");
1121 OTIdentifier::DefaultHashAlgorithm,
1123 otErr << szFunc <<
": SignContract failed. Contents:\n\n" << strInput
1129 listSignatures.push_back(&theSignature);
1131 const bool bBookends = OTContract::AddBookendsAroundContent(
1133 strInput, strContractType, OTIdentifier::DefaultHashAlgorithm,
1140 bool OTContract::SaveContractRaw(
OTString& strOutput)
const
1148 bool OTContract::AddBookendsAroundContent(
1155 strTemp.
Concatenate(
"-----BEGIN SIGNED %s-----\nHash: %s\n\n",
1156 strContractType.
Get(), strHashType.
Get());
1160 for (
const auto& it : listSignatures) {
1164 strTemp.
Concatenate(
"-----BEGIN %s SIGNATURE-----\n"
1165 "Version: Open Transactions %s\n"
1167 "http://github.com/FellowTraveler/"
1168 "Open-Transactions/wiki\n",
1169 strContractType.
Get(), OTLog::Version());
1180 strTemp.
Concatenate(
"-----END %s SIGNATURE-----\n\n",
1181 strContractType.
Get());
1184 std::string str_Trim(strTemp.
Get());
1185 std::string str_Trim2 = OTString::trim(str_Trim);
1186 strOutput.
Set(str_Trim2.c_str());
1196 bool OTContract::RewriteContract(
OTString& strOutput)
const
1199 SaveContents(strContents);
1201 return OTContract::AddBookendsAroundContent(
1202 strOutput, strContents, m_strContractType, m_strSigHashType,
1206 bool OTContract::SaveContract(
const char* szFoldername,
const char* szFilename)
1209 "Null filename sent to OTContract::SaveContract\n");
1211 "Null foldername sent to OTContract::SaveContract\n");
1213 m_strFoldername.Set(szFoldername);
1214 m_strFilename.Set(szFilename);
1216 OT_ASSERT(m_strFoldername.GetLength() > 2);
1217 OT_ASSERT(m_strFilename.GetLength() > 2);
1219 if (!m_strRawFile.Exists()) {
1220 otErr <<
"OTContract::SaveContract: Error saving file (contract "
1221 "contents are empty): " << szFoldername
1222 << OTLog::PathSeparator() << szFilename <<
"\n";
1232 otErr <<
"OTContract::SaveContract: Error saving file (failed writing "
1233 "armored string): " << szFoldername << OTLog::PathSeparator()
1234 << szFilename <<
"\n";
1242 otErr <<
"OTContract::SaveContract: Error saving file: " << szFoldername
1243 << OTLog::PathSeparator() << szFilename <<
"\n";
1253 bool OTContract::LoadContract()
1256 LoadContractRawFile();
1258 return ParseRawFile();
1268 bool OTContract::LoadContractRawFile()
1270 const char* szFoldername = m_strFoldername.Get();
1271 const char* szFilename = m_strFilename.Get();
1273 if (!m_strFoldername.Exists() || !m_strFilename.Exists())
return false;
1276 otErr << __FUNCTION__ <<
": File does not exist: " << szFoldername
1277 << OTLog::PathSeparator() << szFilename <<
"\n";
1282 szFoldername, szFilename));
1284 if (!strFileContents.
Exists()) {
1285 otErr << __FUNCTION__ <<
": Error reading file: " << szFoldername
1286 << OTLog::PathSeparator() << szFilename <<
"\n";
1293 otErr << __FUNCTION__ <<
": Input string apparently was encoded and "
1294 "then failed decoding. Contents: \n"
1295 << strFileContents <<
"\n";
1303 m_strRawFile.
Set(strFileContents);
1305 return m_strRawFile.Exists();
1308 bool OTContract::LoadContract(
const char* szFoldername,
const char* szFilename)
1312 m_strFoldername.Set(szFoldername);
1313 m_strFilename.Set(szFilename);
1316 if (LoadContractRawFile())
1317 return ParseRawFile();
1320 otErr <<
"Failed loading raw contract file: " << m_strFoldername
1321 << OTLog::PathSeparator() << m_strFilename <<
"\n";
1328 bool OTContract::LoadContractFromString(
const OTString& theStr)
1333 otErr << __FUNCTION__ <<
": ERROR: Empty string passed in...\n";
1342 otErr << __FUNCTION__ <<
": ERROR: Input string apparently was encoded "
1343 "and then failed decoding. "
1344 "Contents: \n" << theStr <<
"\n";
1348 m_strRawFile.
Set(strContract);
1374 bool OTContract::ParseRawFile()
1381 bool bSignatureMode =
false;
1382 bool bContentMode =
false;
1383 bool bHaveEnteredContentMode =
false;
1385 if (!m_strRawFile.GetLength()) {
1386 otErr <<
"Empty m_strRawFile in OTContract::ParseRawFile. Filename: "
1387 << m_strFoldername << OTLog::PathSeparator() << m_strFilename
1394 std::string str_Trim(m_strRawFile.Get());
1395 std::string str_Trim2 = OTString::trim(str_Trim);
1396 m_strRawFile.Set(str_Trim2.c_str());
1398 bool bIsEOF =
false;
1399 m_strRawFile.reset();
1404 memset(buffer1, 0, 2100);
1409 bIsEOF = !(m_strRawFile.sgets(buffer1, 2048));
1412 const char* pConstBuf = line.c_str();
1413 char* pBuf = (
char*)pConstBuf;
1415 if (line.length() < 2) {
1416 if (bSignatureMode)
continue;
1420 else if (line.at(0) ==
'-') {
1421 if (bSignatureMode) {
1425 bSignatureMode =
false;
1435 if (!bHaveEnteredContentMode) {
1436 if ((line.length() > 3) &&
1437 (line.find(
"BEGIN") != std::string::npos) &&
1438 line.at(1) ==
'-' && line.at(2) ==
'-' &&
1439 line.at(3) ==
'-') {
1442 bHaveEnteredContentMode =
true;
1443 bContentMode =
true;
1453 else if (line.length() > 3 &&
1454 line.find(
"SIGNATURE") != std::string::npos &&
1455 line.at(1) ==
'-' && line.at(2) ==
'-' &&
1456 line.at(3) ==
'-') {
1463 bSignatureMode =
true;
1464 bContentMode =
false;
1468 OT_ASSERT_MSG(
nullptr != pSig,
"Error allocating memory for "
1470 "OTContract::ParseRawFile\n");
1472 m_listSignatures.push_back(pSig);
1477 else if (line.length() < 3 || line.at(1) !=
' ' ||
1478 line.at(2) !=
'-') {
1480 <<
"Error in contract " << m_strFilename
1481 <<
": a dash at the beginning of the "
1482 "line should be followed by a space and another dash:\n"
1483 << m_strRawFile <<
"\n";
1497 if (bHaveEnteredContentMode) {
1498 if (bSignatureMode) {
1499 if (line.length() < 2) {
1500 otLog3 <<
"Skipping short line...\n";
1502 if (bIsEOF || !m_strRawFile.sgets(buffer1, 2048)) {
1503 otOut <<
"Error in signature for contract "
1505 <<
": Unexpected EOF after short line.\n";
1511 else if (line.compare(0, 8,
"Version:") == 0) {
1512 otLog3 <<
"Skipping version section...\n";
1514 if (bIsEOF || !m_strRawFile.sgets(buffer1, 2048)) {
1515 otOut <<
"Error in signature for contract "
1517 <<
": Unexpected EOF after \"Version:\"\n";
1523 else if (line.compare(0, 8,
"Comment:") == 0) {
1524 otLog3 <<
"Skipping comment section...\n";
1526 if (bIsEOF || !m_strRawFile.sgets(buffer1, 2048)) {
1527 otOut <<
"Error in signature for contract "
1529 <<
": Unexpected EOF after \"Comment:\"\n";
1535 if (line.compare(0, 5,
"Meta:") == 0) {
1536 otLog3 <<
"Collecting signature metadata...\n";
1538 if (line.length() !=
1545 otOut <<
"Error in signature for contract "
1546 << m_strFilename <<
": Unexpected length for "
1547 "\"Meta:\" comment.\n";
1554 line.at(9), line.at(10), line.at(11),
1557 otOut <<
"Error in signature for contract "
1559 <<
": Unexpected metadata in the \"Meta:\" "
1560 "comment.\nLine: " << line <<
"\n";
1564 if (bIsEOF || !m_strRawFile.sgets(buffer1, 2048)) {
1565 otOut <<
"Error in signature for contract "
1567 <<
": Unexpected EOF after \"Meta:\"\n";
1575 if (line.compare(0, 6,
"Hash: ") == 0) {
1576 otLog3 <<
"Collecting message digest algorithm from "
1577 "contract header...\n";
1579 std::string strTemp = line.substr(6);
1580 m_strSigHashType = strTemp.c_str();
1581 m_strSigHashType.ConvertToUpperCase();
1583 if (bIsEOF || !m_strRawFile.sgets(buffer1, 2048)) {
1584 otOut <<
"Error in contract " << m_strFilename
1585 <<
": Unexpected EOF after \"Hash:\"\n";
1594 if (bSignatureMode) {
1596 "Error: Null Signature pointer WHILE "
1597 "processing signature, in "
1598 "OTContract::ParseRawFile");
1602 else if (bContentMode)
1603 m_xmlUnsigned.Concatenate(
"%s\n", pBuf);
1608 if (!bHaveEnteredContentMode) {
1609 otErr <<
"Error in OTContract::ParseRawFile: Found no BEGIN for signed "
1613 else if (bContentMode) {
1614 otErr <<
"Error in OTContract::ParseRawFile: EOF while reading xml "
1618 else if (bSignatureMode) {
1619 otErr <<
"Error in OTContract::ParseRawFile: EOF while reading "
1623 else if (!LoadContractXML()) {
1624 otErr <<
"Error in OTContract::ParseRawFile: unable to load XML "
1625 "portion of contract into memory.\n";
1642 bool OTContract::LoadContractXML()
1644 int32_t retProcess = 0;
1646 if (!m_xmlUnsigned.Exists()) {
1650 m_xmlUnsigned.reset();
1652 IrrXMLReader* xml = irr::io::createIrrXMLReader(m_xmlUnsigned);
1653 OT_ASSERT_MSG(
nullptr != xml,
"Memory allocation issue with xml reader in "
1654 "OTContract::LoadContractXML()\n");
1655 std::unique_ptr<IrrXMLReader> xmlAngel(xml);
1658 while (xml->read()) {
1661 switch (xml->getNodeType()) {
1663 strNodeType.
Set(
"EXN_NONE");
1666 strNodeType.
Set(
"EXN_COMMENT");
1668 case EXN_ELEMENT_END:
1669 strNodeType.
Set(
"EXN_ELEMENT_END");
1672 strNodeType.
Set(
"EXN_CDATA");
1692 retProcess = ProcessXMLNode(xml);
1695 if ((-1) == retProcess) {
1696 otErr <<
"OTContract::LoadContractXML: (Cancelling this "
1697 "contract load; an error occurred.)\n";
1701 else if (0 == retProcess) {
1703 otErr <<
"UNKNOWN element type in OTContract::LoadContractXML: "
1704 << xml->getNodeName() <<
", value: " << xml->getNodeData()
1726 "OTContract::SkipToElement -- assert: nullptr != xml");
1728 const char* szFunc =
"OTContract::SkipToElement";
1730 while (xml->read() && (xml->getNodeType() != EXN_ELEMENT)) {
1734 if (xml->getNodeType() == EXN_NONE) {
1735 otOut <<
"*** " << szFunc <<
": EXN_NONE (skipping)\n";
1738 else if (xml->getNodeType() == EXN_COMMENT) {
1739 otOut <<
"*** " << szFunc <<
": EXN_COMMENT (skipping)\n";
1742 else if (xml->getNodeType() == EXN_ELEMENT_END)
1746 otWarn <<
"*** " << szFunc <<
": EXN_ELEMENT_END (skipping "
1747 << xml->getNodeName() <<
")\n";
1750 else if (xml->getNodeType() == EXN_CDATA) {
1751 otOut <<
"*** " << szFunc
1752 <<
": EXN_CDATA (ERROR -- unexpected CData)\n";
1755 else if (xml->getNodeType() == EXN_TEXT) {
1756 otErr <<
"*** " << szFunc <<
": EXN_TEXT\n";
1759 else if (xml->getNodeType() == EXN_ELEMENT) {
1760 otOut <<
"*** " << szFunc <<
": EXN_ELEMENT\n";
1765 otErr <<
"*** " << szFunc
1766 <<
": SHOULD NEVER HAPPEN (Unknown element type!)\n";
1778 "OTContract::SkipToTextField -- assert: nullptr != xml");
1780 const char* szFunc =
"OTContract::SkipToTextField";
1782 while (xml->read() && (xml->getNodeType() != EXN_TEXT)) {
1783 if (xml->getNodeType() == EXN_NONE) {
1784 otOut <<
"*** " << szFunc <<
": EXN_NONE (skipping)\n";
1787 else if (xml->getNodeType() == EXN_COMMENT) {
1788 otOut <<
"*** " << szFunc <<
": EXN_COMMENT (skipping)\n";
1791 else if (xml->getNodeType() == EXN_ELEMENT_END)
1796 otOut <<
"*** " << szFunc <<
": EXN_ELEMENT_END (ERROR)\n";
1799 else if (xml->getNodeType() == EXN_CDATA) {
1800 otOut <<
"*** " << szFunc
1801 <<
": EXN_CDATA (ERROR -- unexpected CData)\n";
1804 else if (xml->getNodeType() == EXN_ELEMENT) {
1805 otOut <<
"*** " << szFunc <<
": EXN_ELEMENT\n";
1808 else if (xml->getNodeType() == EXN_TEXT) {
1809 otErr <<
"*** " << szFunc <<
": EXN_TEXT\n";
1814 otErr <<
"*** " << szFunc
1815 <<
": SHOULD NEVER HAPPEN (Unknown element type!)\n";
1833 "OTContract::SkipAfterLoadingField -- assert: nullptr != xml");
1835 if (EXN_ELEMENT_END != xml->getNodeType())
1838 const char* szFunc =
"OTContract::SkipAfterLoadingField";
1841 while (xml->read()) {
1842 if (xml->getNodeType() == EXN_NONE) {
1843 otOut <<
"*** " << szFunc <<
": EXN_NONE (skipping)\n";
1846 else if (xml->getNodeType() == EXN_COMMENT) {
1847 otOut <<
"*** " << szFunc <<
": EXN_COMMENT (skipping)\n";
1850 else if (xml->getNodeType() == EXN_ELEMENT_END) {
1851 otLog5 <<
"*** " << szFunc <<
": EXN_ELEMENT_END (success)\n";
1854 else if (xml->getNodeType() == EXN_CDATA) {
1855 otOut <<
"*** " << szFunc <<
": EXN_CDATA (Unexpected!)\n";
1858 else if (xml->getNodeType() == EXN_ELEMENT) {
1859 otOut <<
"*** " << szFunc <<
": EXN_ELEMENT (Unexpected!)\n";
1862 else if (xml->getNodeType() == EXN_TEXT) {
1863 otErr <<
"*** " << szFunc <<
": EXN_TEXT (Unexpected!)\n";
1867 otErr <<
"*** " << szFunc
1868 <<
": SHOULD NEVER HAPPEN (Unknown element type!)\n";
1887 if (OTContract::LoadEncodedTextField(xml, ascOutput) &&
1889 return ascOutput.
GetString(strOutput,
true);
1900 "OTContract::LoadEncodedTextField -- assert: nullptr != xml");
1902 const char* szFunc =
"OTContract::LoadEncodedTextField";
1907 if (EXN_TEXT != xml->getNodeType()) {
1908 otLog4 << szFunc <<
": Skipping non-text field... \n";
1912 if (!SkipToTextField(xml)) {
1914 <<
": Failure: Unable to find expected text field.\n";
1918 <<
": Finished skipping non-text field. (Successfully.)\n";
1921 if (EXN_TEXT == xml->getNodeType())
1924 OTString strNodeData = xml->getNodeData();
1932 strNodeData.
At(0, cNewline)) {
1933 if (
'\n' == cNewline) {
1934 ascOutput.
Set(strNodeData.
Get() + 1);
1937 ascOutput.
Set(strNodeData.
Get());
1948 if (!SkipAfterLoadingField(xml)) {
1949 otOut <<
"*** " << szFunc
1950 <<
": Bad data? Expected EXN_ELEMENT_END here, but "
1951 "didn't get it. Returning false.\n";
1959 otOut << szFunc <<
": Failure: Unable to find expected text field. 2\n";
1968 const char*& szName,
1975 if (OTContract::LoadEncodedTextFieldByName(xml, ascOutput, szName,
1978 return ascOutput.
GetString(strOutput,
true);
1988 const char*& szName,
1993 const char* pElementExpected = szName;
1998 if ((EXN_ELEMENT != xml->getNodeType()) ||
2000 !(strcmp(pElementExpected, xml->getNodeName()) ==
2005 if (!SkipToElement(xml)) {
2006 otOut << __FUNCTION__
2007 <<
": Failure: Unable to find expected element: " << szName
2013 if (EXN_ELEMENT == xml->getNodeType())
2015 if (!strcmp(pElementExpected, xml->getNodeName())) {
2023 for (
auto& it : mapExtraVars) {
2024 std::string first = it.first;
2025 OTString strTemp = xml->getAttributeValue(first.c_str());
2028 mapExtraVars[first] = strTemp.
Get();
2039 OTContract::LoadEncodedTextField(
2043 otErr << __FUNCTION__ <<
": Error loading " << pElementExpected
2065 otErr << __FUNCTION__ <<
": Error: missing " << pElementExpected
2071 otErr << __FUNCTION__ <<
": Error: Expected " << pElementExpected
2072 <<
" element with text field.\n";
2095 bool OTContract::CreateContract(
const OTString& strContract,
2102 const uint32_t lLength = strContract.
GetLength();
2104 if ((3 > lLength) || !strContract.
At(lLength - 1, cNewline)) {
2105 otErr << __FUNCTION__
2106 <<
": Invalid input: contract is less than 3 bytes "
2107 "int64_t, or unable to read a byte from the end where a "
2108 "newline is meant to be.\n";
2121 if (
'\n' == cNewline)
2122 m_xmlUnsigned = strContract;
2124 m_xmlUnsigned.
Format(
"%s\n", strContract.
Get());
2129 bool bLoaded = LoadContractXML();
2135 if (
nullptr == GetContractPublicNym()) {
2136 const bool bHasCredentials =
2139 if (!bHasCredentials) {
2144 InsertNym(
"contract", strPubkey);
2150 OTString strCredList, strSignerNymID;
2155 std::unique_ptr<OTPseudonym> pNym(
new OTPseudonym);
2157 pNym->SetIdentifier(strSignerNymID);
2161 if (!pNym->LoadFromString(strCredList, &mapCredFiles)) {
2162 otErr << __FUNCTION__ <<
": Failure loading nym "
2163 << strSignerNymID <<
" from credential string.\n";
2172 else if (!pNym->VerifyPseudonym()) {
2174 << __FUNCTION__ <<
": Loaded nym " << strSignerNymID
2175 <<
" from credentials, but then it failed verifying.\n";
2181 m_mapNyms[
"signer"] = pNym.release();
2194 OTPasswordData thePWData(
"OTContract::CreateContract needs the private "
2195 "key to sign the contract...");
2197 if (!SignContract(theSigner, &thePWData)) {
2198 otErr << __FUNCTION__ <<
": SignContract failed.\n";
2205 SaveContractRaw(strTemp);
2208 LoadContractFromString(strTemp);
2215 CalculateContractID(NEW_ID);
2221 otErr << __FUNCTION__
2222 <<
": LoadContractXML failed. strContract contents:\n\n"
2223 << strContract <<
"\n\n";
2230 void OTContract::CreateInnerContents()
2234 if (!m_mapConditions.empty()) {
2235 m_xmlUnsigned.
Concatenate(
"<!-- CONDITIONS -->\n\n");
2237 for (
auto& it : m_mapConditions) {
2238 std::string str_condition_name = it.first;
2239 std::string str_condition_value = it.second;
2241 m_xmlUnsigned.Concatenate(
2242 "<condition name=\"%s\">%s</condition>\n\n",
2243 str_condition_name.c_str(), str_condition_value.c_str());
2249 if (!m_mapNyms.empty()) {
2253 for (
auto& it : m_mapNyms) {
2254 std::string str_name = it.first;
2257 "1: nullptr pseudonym pointer in "
2258 "OTContract::CreateInnerContents.\n");
2260 if ((
"contract" == str_name) || (
"certification" == str_name) ||
2261 (
"serverCertification" == str_name)) {
2266 strTemp.
Concatenate(
"<key name=\"%s\">\n%s</key>\n\n",
2267 str_name.c_str(), strPubkey.
Get());
2273 m_xmlUnsigned.Concatenate(
"<!-- KEYS -->\n\n%s", strTemp.
Get());
2278 for (
auto& it : m_mapNyms) {
2279 std::string str_name = it.first;
2282 "2: nullptr pseudonym pointer in "
2283 "OTContract::CreateInnerContents.\n");
2285 if (
"signer" == str_name) {
2286 const bool bHasCredentials =
2301 " altLocation=\"%s\""
2304 bHasCredentials ?
"true" :
"false",
2305 strNymID.
Get(), ascAltLocation.
Get());
2309 strTemp.
Concatenate(
"<nymIDSource>\n%s</nymIDSource>\n\n",
2310 ascNymIDSource.Get());
2316 if (bHasCredentials) {
2320 std::unique_ptr<OTDB::Storable> pStorable(
2325 (
nullptr == pStorable)
2327 : dynamic_cast<OTDB::StringMap*>(pStorable.get());
2329 if (
nullptr == pMap)
2330 otErr << __FUNCTION__ <<
": Error: failed trying to "
2332 "STORED_OBJ_STRING_MAP.\n";
2342 if (strCredList.
Exists() &&
2347 const bool bSuccessEncoding =
2348 (str_Encoded.size() > 0);
2349 if (bSuccessEncoding) {
2351 armor2.
Set(str_Encoded.c_str());
2352 if (armor1.Exists())
2354 "credentialList>\n\n",
2358 "<credentials>\n%s</credentials>\n\n",
2365 strTemp.
Concatenate(
"</%s>\n\n", str_name.c_str());
2371 m_xmlUnsigned.Concatenate(
"<!-- NYMS -->\n\n%s", strTemp.
Get());
2384 void OTContract::CreateContents()
2386 OT_FAIL_MSG(
"ASSERT: OTContract::CreateContents should never be called, "
2387 "but should be overrided. (In this case, it wasn't.)");
2393 const OTString strNodeName(xml->getNodeName());
2395 if (strNodeName.Compare(
"entity")) {
2396 m_strEntityShortName = xml->getAttributeValue(
"shortname");
2397 if (!m_strName.Exists())
2400 m_strName = m_strEntityShortName;
2404 m_strEntityLongName = xml->getAttributeValue(
"longname");
2405 m_strEntityEmail = xml->getAttributeValue(
"email");
2407 otWarn <<
"Loaded Entity, shortname: " << m_strEntityShortName
2408 <<
"\nLongname: " << m_strEntityLongName
2409 <<
", email: " << m_strEntityEmail <<
"\n----------\n";
2413 else if (strNodeName.Compare(
"condition")) {
2420 strConditionName = xml->getAttributeValue(
"name");
2422 if (!SkipToTextField(xml)) {
2423 otOut <<
"OTContract::ProcessXMLNode: Failure: Unable to find "
2424 "expected text field for xml node named: "
2425 << xml->getNodeName() <<
"\n";
2429 if (EXN_TEXT == xml->getNodeType()) {
2430 strConditionValue = xml->getNodeData();
2433 otErr <<
"Error in OTContract::ProcessXMLNode: Condition without "
2434 "value: " << strConditionName <<
"\n";
2440 m_mapConditions.insert(std::pair<std::string, std::string>(
2441 strConditionName.
Get(), strConditionValue.
Get()));
2443 otWarn <<
"---- Loaded condition \"" << strConditionName <<
"\"\n";
2450 else if (strNodeName.Compare(
"signer")) {
2451 const OTString strSignerNymID = xml->getAttributeValue(
"nymID");
2453 xml->getAttributeValue(
"hasCredentials");
2455 xml->getAttributeValue(
"altLocation");
2456 OTString strAltLocation, strSignerSource;
2458 if (ascAltLocation.
Exists())
2459 ascAltLocation.
GetString(strAltLocation,
2462 bool bHasCredentials = strHasCredentials.
Compare(
"true");
2463 const bool bHasAltLocation = strAltLocation.
Exists();
2465 if (!strSignerNymID.
Exists()) {
2466 otErr <<
"Error in " << __FUNCTION__
2468 "Expected nymID attribute on signer element.\n";
2474 const char* pElementExpected =
"nymIDSource";
2475 otWarn << __FUNCTION__ <<
": Loading " << pElementExpected <<
"...\n";
2476 if (!OTContract::LoadEncodedTextFieldByName(xml, strSignerSource,
2477 pElementExpected)) {
2478 otErr <<
"Error in " << __FILE__ <<
" line " << __LINE__
2479 <<
": failed loading expected " << pElementExpected
2480 <<
" field:\n\n" << m_xmlUnsigned <<
"\n\n\n";
2486 if (!bHasCredentials) {
2494 if (bHasAltLocation) {
2495 otErr << __FUNCTION__
2496 <<
": WARNING: No credentials provided. An alternate "
2498 "listed, but that's not yet supported in the "
2499 "code.\nLocation: " << strAltLocation <<
"\n";
2530 otErr << __FUNCTION__
2531 <<
": WARNING: Alternate location not listed, and no "
2532 "credentials provided, so we need to download"
2533 " them from the source--but that's not yet supported "
2534 "in the code.\nNymID Source String: "
2535 << strSignerSource <<
"\n";
2545 pElementExpected =
"credentialList";
2547 if (!OTContract::LoadEncodedTextFieldByName(xml, ascArmor,
2548 pElementExpected)) {
2549 otErr <<
"Error in " << __FUNCTION__ <<
": "
2551 << pElementExpected <<
" element with text field.\n";
2555 pElementExpected =
"credentials";
2557 if (!OTContract::LoadEncodedTextFieldByName(xml, ascArmor2,
2558 pElementExpected)) {
2559 otErr <<
"Error in " << __FUNCTION__ <<
": "
2561 << pElementExpected <<
" element with text field.\n";
2566 bHasCredentials = (ascArmor.
Exists() && ascArmor2.
Exists());
2573 if (bHasCredentials) {
2579 if (strCredentialList.
Exists()) {
2583 (
nullptr == pStorable)
2585 : dynamic_cast<OTDB::StringMap*>(pStorable.get());
2587 if (
nullptr == pMap)
2588 otOut << __FUNCTION__
2589 <<
": Failed decoding StringMap object.\n";
2595 std::unique_ptr<OTPseudonym> pNym(
new OTPseudonym);
2596 pNym->SetIdentifier(strSignerNymID);
2599 pNym->LoadFromString(strCredentialList, &theMap)) {
2600 otErr << __FUNCTION__ <<
": Failure loading nym "
2601 << strSignerNymID <<
" from credential string.\n";
2610 else if (!pNym->VerifyPseudonym()) {
2611 otErr << __FUNCTION__ <<
": Loaded nym "
2613 <<
" from credentials, but then it failed "
2622 m_mapNyms[strNodeName.Get() ] =
2635 else if (strNodeName.Compare(
"key")) {
2639 strKeyName = xml->getAttributeValue(
"name");
2641 if (!SkipToTextField(xml)) {
2642 otOut <<
"OTContract::ProcessXMLNode: Failure: Unable to find "
2644 "field for xml node named: " << xml->getNodeName() <<
"\n";
2648 if (EXN_TEXT == xml->getNodeType()) {
2649 strKeyValue = xml->getNodeData();
2652 otErr <<
"Error in OTContract::ProcessXMLNode: Key without value: "
2653 << strKeyName <<
"\n";
2669 if (!InsertNym(strKeyName, strKeyValue))
2670 otErr <<
"Error performing OTContract::InsertNym.\n";
2691 bool bResult =
false;
2696 "Error allocating memory for new Nym in OTContract::InsertNym\n");
2700 if (strKeyValue.
Contains(
"CERTIFICATE") &&
2704 m_mapNyms[strKeyName.
Get()] = pNym;
2706 otWarn <<
"---- Loaded certificate \"" << strKeyName <<
"\"\n";
2709 else if (strKeyValue.
Contains(
"PUBLIC KEY") &&
2713 m_mapNyms[strKeyName.
Get()] = pNym;
2715 otWarn <<
"---- Loaded public key \"" << strKeyName <<
"\"\n";
2721 otOut <<
"\nLoaded key \"" << strKeyName
2722 <<
"\" but FAILED adding the"
2723 " Nym to the Contract:\n--->" << strKeyValue <<
"<---\n";
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
OTLOG_IMPORT OTLogStream otLog4
EXPORT void GetPublicCredentials(OTString &strCredList, OTString::Map *pmapCredFiles=nullptr) const
std::map< std::string, std::string > Map
EXPORT Storable * CreateObject(StoredObjectType eType)
EXPORT bool SetPublicKey(const OTString &strKey, bool bEscaped=true)
std::list< OTAsymmetricKey * > listOfAsymmetricKeys
EXPORT bool CalculateDigest(const OTData &dataInput)
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
OTSignatureMetadata * m_pMetadata
EXPORT bool SetCertificate(const OTString &strCert, bool bEscaped=true)
OTLOG_IMPORT OTLogStream otOut
OTLOG_IMPORT OTLogStream otLog3
EXPORT uint32_t GetLength() const
EXPORT void Concatenate(const char *arg,...)
EXPORT bool WriteArmoredString(OTString &strOutput, const std::string str_type, bool bEscaped=false) const
EXPORT bool DecodeIfArmored(bool escapedIsAllowed=true)
EXPORT bool Exists() const
EXPORT bool SetString(const OTString &theData, bool bLineBreaks=true)
EXPORT std::string EncodeObject(Storable &theContents)
EXPORT void Format(const char *fmt,...)
EXPORT bool Compare(const char *compare) const
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
EXPORT bool GetPublicKey(OTASCIIArmor &strKey) const
EXPORT const OTAsymmetricKey & GetPublicAuthKey() const
EXPORT bool SetIdentifierByPubkey()
EXPORT int32_t GetPublicKeysBySignature(listOfAsymmetricKeys &listOutput, const OTSignature &theSignature, char cKeyType= '0') const
bool sgets(char *buffer, uint32_t size)
const OTAsymmetricKey & GetPrivateAuthKey() const
OTSignatureMetadata & getMetaData()
#define OT_ASSERT_MSG(x, s)
OTLOG_IMPORT OTLogStream otInfo
EXPORT const OTString & GetAltLocation() const
EXPORT bool At(uint32_t index, char &c) const
EXPORT const OTAsymmetricKey & GetPublicSignKey() const
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
OTLOG_IMPORT OTLogStream otErr
std::map< std::string, std::string > the_map
EXPORT void GetString(OTString &theStr) const
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
EXPORT const OTString & GetNymIDSource() const
EXPORT bool Contains(const char *compare) const
EXPORT Storable * DecodeObject(StoredObjectType theObjectType, std::string strInput)
const OTAsymmetricKey & GetPrivateSignKey() const
EXPORT bool GetString(OTString &theData, bool bLineBreaks=true) const
virtual EXPORT void Release()
EXPORT size_t GetMasterCredentialCount() const
std::list< OTSignature * > listOfSignatures
virtual EXPORT void Release()
OTLOG_IMPORT OTLogStream otLog5