Ejemplo n.º 1
0
// Decodes a private key from ASCII armor into an actual key pointer
// and sets that as the m_pPrivateKey on this object.
// This is the version that will handle the bookends ( -----BEGIN ENCRYPTED PRIVATE KEY-----)
bool OTKeypair::SetPrivateKey(const OTString & strKey, bool bEscaped/*=false*/)
{
    OT_ASSERT(NULL != m_pkeyPrivate);
    // ---------------------------------------------------------------
    const char * szOverride = "PGP PRIVATE KEY";

	if (strKey.Contains(szOverride))
	{
		OTASCIIArmor theArmor;
        
		if (theArmor.LoadFromString(const_cast<OTString &>(strKey), bEscaped,
                                    szOverride)) // szOverride == "PGP PRIVATE KEY"
		{
			// This function expects that the bookends are already removed.
			// The ascii-armor loading code removes them and handles the escapes also.
//			return m_pkeyPrivate->LoadPrivateKeyFromPGPKey(theArmor);
            //
			OTLog::vOutput(0, "OTKeypair::SetPrivateKey 1: Failure: PGP private keys are NOT YET SUPPORTED.\n\n");
//			OTLog::vOutput(0, "OTKeypair::SetPrivateKey 1: Failure: PGP private keys are NOT YET SUPPORTED:\n\n%s\n\n",
//                           strKey.Get());
			return false;
		}
		else 
        {
			OTLog::vOutput(0, "OTKeypair::SetPrivateKey 2: Failure: PGP private keys are NOT YET SUPPORTED.\n\n");
//			OTLog::vOutput(0, "OTKeypair::SetPrivateKey 2: Failure: PGP private keys are NOT YET SUPPORTED:\n\n%s\n\n",
//                           strKey.Get());
			return false;
		}
	}
	else // the below function SetPrivateKey (in the return call) expects the
         // bookends to still be there, and it will handle removing them. (Unlike PGP code above.)
        //
		return m_pkeyPrivate->SetPrivateKey(strKey, bEscaped);
}
Ejemplo n.º 2
0
bool OTEnvelope::SetFromBookendedString(
    const String& strArmorWithBookends, // input
    bool bEscaped)
{
    OTASCIIArmor theArmoredText;
    const bool bLoaded = theArmoredText.LoadFromString(
        const_cast<String&>(strArmorWithBookends),
        bEscaped); // std::string str_override="-----BEGIN");

    if (bLoaded) {
        // This function will base64 DECODE theArmoredText's string contents
        // and return them as binary in m_dataContents
        const bool bGotData =
            theArmoredText.GetData(m_dataContents, true); // bLineBreaks = true

        if (!bGotData)
            otErr << __FUNCTION__ << ": Failed while calling: "
                                     "theArmoredText.GetData\n";
        else
            return true;
    }
    else
        otErr << __FUNCTION__ << ": Failed while calling: "
                                 "theArmoredText.LoadFromString\n";

    return false;
}
Ejemplo n.º 3
0
// Decodes a public key from bookended key string into an actual key
// pointer, and sets that as the m_pkeyPublic on this object.
// This is the version that will handle the bookends ( -----BEGIN PUBLIC KEY-----)
//
bool OTKeypair::SetPublicKey(const OTString & strKey, bool bEscaped/*=false*/)
{
    OT_ASSERT(NULL != m_pkeyPublic);
    
    // ---------------------------------------------------------------
    if (strKey.Contains("PGP PUBLIC KEY"))
	{
		OTASCIIArmor theArmor;
		
		if (theArmor.LoadFromString(const_cast<OTString &>(strKey), bEscaped))
		{
			// This function expects that the bookends are already removed.
			// The ascii-armor loading code removes them and handles the escapes also.
			return m_pkeyPublic->LoadPublicKeyFromPGPKey(theArmor);
		}
		else
        {
			OTLog::Output(2, "OTKeypair::SetPublicKey: Failed extracting PGP public key from ascii-armored text.\n");
			return false;
		}
	}
	else // the below function SetPublicKey (in the return call) expects the
        // bookends to still be there, and it will handle removing them. (Unlike PGP code above.)
		return m_pkeyPublic->SetPublicKey(strKey, bEscaped);
}
Ejemplo n.º 4
0
// Let's say you don't know if the input string is raw base64, or if it has
// bookends
// on it like -----BEGIN BLAH BLAH ...
// And if it DOES have Bookends, you don't know if they are escaped:  -
// -----BEGIN ...
// Let's say you just want an easy function that will figure that crap out, and
// load the
// contents up properly into an OTASCIIArmor object. (That's what this function
// will do.)
//
// str_bookend is a default.
// So you could make it more specific like, -----BEGIN ENCRYPTED KEY (or
// whatever.)
//
// static
bool OTASCIIArmor::LoadFromString(OTASCIIArmor& ascArmor,
                                  const String& strInput,
                                  std::string str_bookend)
{

    if (strInput.Contains(str_bookend)) // YES there are bookends around this.
    {
        const std::string str_escaped("- " + str_bookend);

        const bool bEscaped = strInput.Contains(str_escaped);

        String strLoadFrom(strInput);

        if (!ascArmor.LoadFromString(strLoadFrom, bEscaped)) // removes the
                                                             // bookends so we
                                                             // have JUST the
                                                             // coded part.
        {
            //          otErr << "%s: Failure loading string into OTASCIIArmor
            // object:\n\n%s\n\n",
            //                        __FUNCTION__, strInput.Get());
            return false;
        }
    }
    else
        ascArmor.Set(strInput.Get());

    return true;
}
Ejemplo n.º 5
0
// static
bool OTKeyring::KWallet_RetrieveSecret(const OTString& strUser,
                                       OTPassword& thePassword,
                                       const std::string& str_display)
{
    OT_ASSERT(strUser.Exists());

    KWallet::Wallet* pWallet = OTKeyring::OpenKWallet();

    if (nullptr != pWallet) {
        const QString qstrKey(strUser.Get());
        QString qstrPwd;

        // Get the password
        //
        if (pWallet->readPassword(qstrKey, qstrPwd) == 0) {
            const std::string str_password =
                qstrPwd.toStdString(); // todo security: notice str_password
                                       // isn't zero'd here.

            OTString strData(str_password);
            OTASCIIArmor ascData;

            const bool bLoaded =
                strData.Exists() && ascData.LoadFromString(strData);
            strData.zeroMemory();

            if (!bLoaded)
                otErr << __FUNCTION__ << ": Failed trying to decode secret "
                                         "from KWallet contents.\n";
            else {
                OTData thePayload(ascData);
                ascData.zeroMemory();
                if (thePayload.IsEmpty())
                    otErr << __FUNCTION__ << ": Failed trying to decode secret "
                                             "OTData from OTASCIIArmor from "
                                             "KWallet contents.\n";
                else {
                    thePassword.setMemory(thePayload.GetPayloadPointer(),
                                          thePayload.GetSize());
                    thePayload.zeroMemory(); // for security.
                    return true;
                }
            }
        }
        else
            otErr << __FUNCITON__
                  << ": Failed trying to retrieve secret from KWallet.\n";
    }

    // Not an error: what if it just hasn't been set there yet?
    //
    otWarn << "OTKeyring::KWallet_RetrieveSecret: No secret found.\n";

    return false;
}
Ejemplo n.º 6
0
// Let's say you don't know if the input string is raw base64, or if it has bookends
// on it like -----BEGIN BLAH BLAH ...
// And if it DOES have Bookends, you don't know if they are escaped:  - -----BEGIN ...
// Let's say you just want an easy function that will figure that crap out, and load the
// contents up properly into an OTASCIIArmor object. (That's what this function will do.)
//
// str_bookend is a default.
// So you could make it more specific like, -----BEGIN ENCRYPTED KEY (or whatever.)
//
//static
bool OTASCIIArmor::LoadFromString(OTASCIIArmor & ascArmor, const OTString & strInput, const std::string str_bookend/*="-----BEGIN"*/)
{
    // -----------------------------------------------------
    if (strInput.Contains(str_bookend)) // YES there are bookends around this.
    {
        const std::string str_escaped("- " + str_bookend);
        // -----------------------------------
        const bool bEscaped = strInput.Contains(str_escaped);
        // -----------------------------------        
        OTString strLoadFrom(strInput);
        
        if (!ascArmor.LoadFromString(strLoadFrom, bEscaped)) // removes the bookends so we have JUST the coded part.
        {
//          OTLog::vError("%s: Failure loading string into OTASCIIArmor object:\n\n%s\n\n",
//                        __FUNCTION__, strInput.Get());
            return false;
        }
    }
    else
        ascArmor.Set(strInput.Get());
	// -------------------------------------------------    
    
    return true;
}
Ejemplo n.º 7
0
// static
bool OTKeyring::Gnome_RetrieveSecret(const OTString& strUser,
                                     OTPassword& thePassword,
                                     const std::string& str_display)
{
    OT_ASSERT(strUser.Exists());

    GnomeKeyringResult theResult = GNOME_KEYRING_RESULT_IO_ERROR;
    gchar* gchar_p_password = nullptr;

    // if the password exists in the keyring, set it in
    // thePassword (output argument.)
    //
    int32_t nCount = -1;
    int64_t lSleep = 1;

    while ((GNOME_KEYRING_RESULT_OK != theResult)) {
        ++nCount; // 0 on first iteration.

        theResult = gnome_keyring_find_password_sync(
            GNOME_KEYRING_NETWORK_PASSWORD, &gchar_p_password, "user",
            strUser.Get(), "protocol", "opentxs", // todo: hardcoding.
            nullptr);

        if (GNOME_KEYRING_RESULT_OK == theResult) break;

        if (nCount > 2) // todo hardcoding.
            break;      // we try a few times -- not infinite times!

        OTString strGnomeError(gnome_keyring_result_to_message(theResult));

        //        OTString strGnomeError;
        //        switch (theResult) {
        //            case GNOME_KEYRING_RESULT_OK: strGnomeError
        // = "GNOME_KEYRING_RESULT_OK"; break;
        //            case GNOME_KEYRING_RESULT_DENIED: strGnomeError
        // = "GNOME_KEYRING_RESULT_DENIED"; break;
        //            case GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON: strGnomeError
        // = "GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON"; break;
        //            case GNOME_KEYRING_RESULT_ALREADY_UNLOCKED: strGnomeError
        // = "GNOME_KEYRING_RESULT_ALREADY_UNLOCKED"; break;
        //            case GNOME_KEYRING_RESULT_NO_SUCH_KEYRING: strGnomeError
        // = "GNOME_KEYRING_RESULT_NO_SUCH_KEYRING"; break;
        //            case GNOME_KEYRING_RESULT_BAD_ARGUMENTS: strGnomeError
        // = "GNOME_KEYRING_RESULT_BAD_ARGUMENTS"; break;
        //            case GNOME_KEYRING_RESULT_IO_ERROR: strGnomeError
        // = "GNOME_KEYRING_RESULT_IO_ERROR"; break;
        //            case GNOME_KEYRING_RESULT_CANCELLED: strGnomeError
        // = "GNOME_KEYRING_RESULT_CANCELLED"; break;
        //            case GNOME_KEYRING_RESULT_KEYRING_ALREADY_EXISTS:
        // strGnomeError = "GNOME_KEYRING_RESULT_KEYRING_ALREADY_EXISTS"; break;
        //            case GNOME_KEYRING_RESULT_NO_MATCH: strGnomeError
        // = "GNOME_KEYRING_RESULT_NO_MATCH"; break;
        //
        //            default:
        //                strGnomeError = "Unknown! Very strange!";
        //                break;
        //        }

        otErr << __FUNCTION__ << ": gnome_keyring_find_password_sync returned "
              << strGnomeError.Get() << '\n';
        otErr << "Remedy: Sleeping for " << lSleep
              << " seconds and then retrying (attempt " << (nCount + 2) << '\n';
        // on first iteration, nCount is 0, and this will say "attempt 2" aka
        // "second attempt," which is correct.

        sleep(lSleep);
        lSleep *= 2; // double it each time
    }

    if ((theResult == GNOME_KEYRING_RESULT_OK) &&
        (nullptr != gchar_p_password)) {
        size_t sizePassword =
            OTString::safe_strlen(gchar_p_password, MAX_STRING_LENGTH);

        if (sizePassword > 0) {
            OTString strData(gchar_p_password, sizePassword);

            gnome_keyring_free_password(gchar_p_password);
            gchar_p_password = nullptr;

            OTASCIIArmor ascData;
            const bool bLoaded =
                strData.Exists() && ascData.LoadFromString(strData);
            strData.zeroMemory();

            if (!bLoaded)
                otErr << __FUNCTION__ << ": Failed trying to decode secret "
                                         "from Gnome Keyring contents:\n\n"
                      << strData.Get() << "\n\n";
            else {
                OTData thePayload(ascData);
                ascData.zeroMemory();
                if (thePayload.IsEmpty())
                    otErr << __FUNCTION__ << ": Failed trying to decode secret "
                                             "OTData from OTASCIIArmor "
                          << "from Gnome Keyring contents:\n\n" << strData.Get()
                          << "\n\n";
                else {
                    thePassword.setMemory(thePayload.GetPayloadPointer(),
                                          thePayload.GetSize());
                    thePayload.zeroMemory(); // for security.
                    return true;
                }
                return false;
            }
        }
    }

    // Not an error: what if it just hasn't been set there yet?
    //
    otOut << "OTKeyring::Gnome_RetrieveSecret: "
          << "No secret found: gnome_keyring_find_password_sync: "
          << gnome_keyring_result_to_message(theResult) << '\n';

    return false;
}
Ejemplo n.º 8
0
// If this string starts with -----BEGIN OT ARMORED...
// Then this function will load it up into an OTASCIIArmor (removing
// the bookends) and then decode it back into this string. This code
// has been repeated around so I'm doing this as a refactoring exercise.
//
// Return value: true  == There is a string in here that is not armored.
//                        (Whether I actually HAD to unarmor it or not... it's unarmored now.)
//               false == There was some error or the string is empty.
//
bool OTString::DecodeIfArmored(bool bEscapedIsAllowed/*=true*/)
{
    if (!this->Exists())
        return false;
    // ----------------------
    bool bArmoredAndALSOescaped = false;    // "- -----BEGIN OT ARMORED"
    bool bArmoredButNOTescaped  = false;    // "-----BEGIN OT ARMORED"

    if (this->Contains(OT_BEGIN_ARMORED_escaped)) // check this one first...
    {
        bArmoredAndALSOescaped = true;

        if (!bEscapedIsAllowed)
        {
            OTLog::vError("%s: Armored and escaped value passed in, but escaped are forbidden here. "
                          "(Returning.)\n");
            return false;
        }
    }
    else if (this->Contains(OT_BEGIN_ARMORED))
    {
        bArmoredButNOTescaped = true;
    }
    // ----------------------------------------
    const bool bArmored = (bArmoredAndALSOescaped || bArmoredButNOTescaped);
    // ----------------------------------------
    // Whether the string is armored or not, (-----BEGIN OT ARMORED)
    // either way, we'll end up with the decoded version in this variable:
    //
    std::string str_Trim;
    // ------------------------------------------------
    if (bArmored) // it's armored, we have to decode it first.
    {
        OTASCIIArmor ascTemp;
        if (false == (ascTemp.LoadFromString(*this,
                                             bArmoredAndALSOescaped, // if it IS escaped or not, this variable will be true or false to show it.
                                             // The below szOverride sub-string determines where the content starts, when loading.
                                             OT_BEGIN_ARMORED)))     // Default is:       "-----BEGIN"
            // We're doing this: "-----BEGIN OT ARMORED" (Should worked for escaped as well, here.)
        {
            OTLog::vError("%s: Error loading string contents from ascii-armored encoding. "
                          "Contents: \n%s\n", __FUNCTION__, this->Get());
            return false;
        }
        else // success loading the actual contents out of the ascii-armored version.
        {
            OTString strTemp(ascTemp); // <=== ascii-decoded here.
            std::string str_temp(strTemp.Get(), strTemp.GetLength());
            str_Trim = OTString::trim(str_temp); // This is the std::string for the trim process.
        }
    }
    else
    {
        std::string str_temp(this->Get(), this->GetLength());
        str_Trim = OTString::trim(str_temp); // This is the std::string for the trim process. (Wasn't armored, so here we use it as passed in.)
    }
    // ------------------------------------------------
    // At this point, str_Trim contains the actual contents, whether they
    // were originally ascii-armored OR NOT. (And they are also now trimmed, either way.)
    // ------------------------------------------
    this->Release();
    // ------------------------------------------
    if (str_Trim.size() > 0)
        this->Set(str_Trim.c_str());
    // ------------------------------------------
    return this->Exists();
}
Ejemplo n.º 9
0
bool OTPayment::SetPayment(const OTString & strPayment)
{
    if (!strPayment.Exists())
		return false;
    // --------------------------------------------------------------------
	//
    // To support legacy data, we check here to see if it's armored or not.
    // If it's not, we support it. But if it IS, we ALSO support it (we de-armor it here.)
    //
    bool bArmoredAndALSOescaped = false;    // "- -----BEGIN OT ARMORED"
    bool bArmoredButNOTescaped  = false;    // "-----BEGIN OT ARMORED"
    
    if (strPayment.Contains(OT_BEGIN_ARMORED_escaped)) // check this one first...
    {
        bArmoredAndALSOescaped = true;
        
        OTLog::Error("OTPayment::SetPayment: Armored and escaped value passed in, but escaped are forbidden here. (Returning false.)\n");
		return false;
    }
    else if (strPayment.Contains(OT_BEGIN_ARMORED))
    {
        bArmoredButNOTescaped = true;
    }
    // ----------------------------------------
    const bool bArmored = (bArmoredAndALSOescaped || bArmoredButNOTescaped);
    // ----------------------------------------
    
    // Whether the string is armored or not, (-----BEGIN OT ARMORED)
    // either way, we'll end up with the decoded version in this variable:
    //
    std::string str_Trim;
    
    // ------------------------------------------------
    if (bArmored) // it's armored, we have to decode it first.
    {
        OTASCIIArmor ascTemp;
        OTString strPaymentTemp(strPayment);
        
        if (false == (ascTemp.LoadFromString(strPaymentTemp, 
                                             bArmoredAndALSOescaped, // if it IS escaped or not, this variable will be true or false to show it.
                                             // The below szOverride sub-string determines where the content starts, when loading.
                                             OT_BEGIN_ARMORED)))     // Default is:       "-----BEGIN" 
                                                                     // We're doing this: "-----BEGIN OT ARMORED" (Should worked for escaped as well, here.)
        {
            OTLog::vError("OTPayment::SetPayment: Error loading string contents from ascii-armored encoding. Contents: \n%s\n", 
                          strPayment.Get());
            return false;
        }
        else // success loading the actual contents out of the ascii-armored version.
        {
            OTString strTemp(ascTemp); // <=== ascii-decoded here.
            
            std::string str_temp(strTemp.Get(), strTemp.GetLength());
            
            str_Trim = OTString::trim(str_temp); // This is the std::string for the trim process.
        } 
    }
    else
    {
        std::string str_temp(strPayment.Get(), strPayment.GetLength());
        str_Trim = OTString::trim(str_temp); // This is the std::string for the trim process. (Wasn't armored, so here we use it as passed in.)
    }
    // ------------------------------------------------
    
    // At this point, str_Trim contains the actual contents, whether they
    // were originally ascii-armored OR NOT. (And they are also now trimmed, either way.)
    // ------------------------------------------
    
    OTString strContract(str_Trim.c_str());
    
    m_strPayment.Release();
    // ----------------------
    // todo: should be "starts with" and perhaps with a trim first
    //
    if (strContract.Contains("-----BEGIN SIGNED CHEQUE-----"))
        m_Type  = OTPayment::CHEQUE;
    else if (strContract.Contains("-----BEGIN SIGNED VOUCHER-----"))
        m_Type  = OTPayment::VOUCHER;
    else if (strContract.Contains("-----BEGIN SIGNED INVOICE-----"))
        m_Type  = OTPayment::INVOICE;
    // -------------------
    else if (strContract.Contains("-----BEGIN SIGNED PAYMENT PLAN-----"))
        m_Type  = OTPayment::PAYMENT_PLAN;
    else if (strContract.Contains("-----BEGIN SIGNED SMART CONTRACT-----"))
        m_Type  = OTPayment::SMART_CONTRACT;
    // -------------------
    else if (strContract.Contains("-----BEGIN SIGNED PURSE-----"))
        m_Type  = OTPayment::PURSE;
    else
        m_Type  = OTPayment::ERROR_STATE;
    // ----------------------
    if (OTPayment::ERROR_STATE == m_Type)
        return false;

    // *********************************
    
    m_strPayment.Set(strContract);
    
    // *********************************
    
    return true;
}
Ejemplo n.º 10
0
// static -- class factory.
//
OTTransactionType * OTTransactionType::TransactionFactory(const OTString & strInput)
{
	static char		buf[45] = "";
    
	OTTransactionType *	pItem = NULL;
	
	if (!strInput.Exists())
		return NULL;
    
    // --------------------------------------------------------------------
	//
    // To support legacy data, we check here to see if it's armored or not.
    // If it's not, we support it. But if it IS, we ALSO support it (we de-armor it here.)
    //
    bool bArmoredAndALSOescaped = false;    // "- -----BEGIN OT ARMORED"
    bool bArmoredButNOTescaped  = false;    // "-----BEGIN OT ARMORED"
    
    if (strInput.Contains(OT_BEGIN_ARMORED_escaped)) // check this one first...
    {
        bArmoredAndALSOescaped = true;
        
        OTLog::Error("OTTransactionType::TransactionFactory: Armored and escaped value passed in, "
                     "but escaped are forbidden here. (Returning NULL.)\n");
		return NULL;
    }
    else if (strInput.Contains(OT_BEGIN_ARMORED))
    {
        bArmoredButNOTescaped = true;
    }
    // ----------------------------------------
    const bool bArmored = (bArmoredAndALSOescaped || bArmoredButNOTescaped);
    // ----------------------------------------
    
    // Whether the string is armored or not, (-----BEGIN OT ARMORED)
    // either way, we'll end up with the decoded version in this variable:
    //
    std::string str_Trim;
    
    // ------------------------------------------------
    if (bArmored) // it's armored, we have to decode it first.
    {
        OTASCIIArmor ascTemp;
        OTString strInputTemp(strInput);
        
        if (false == (ascTemp.LoadFromString(strInputTemp, 
                                             bArmoredAndALSOescaped, // if it IS escaped or not, this variable will be true or false to show it.
                                             // The below szOverride sub-string determines where the content starts, when loading.
                                             OT_BEGIN_ARMORED)))     // Default is:       "-----BEGIN" 
                                                                     // We're doing this: "-----BEGIN OT ARMORED" (Should worked for escaped as well, here.)
        {
            OTLog::vError("OTTransactionType::TransactionFactory: Error "
                          "loading string contents from ascii-armored encoding. Contents: \n%s\n", 
                          strInput.Get());
            return NULL;
        }
        else // success loading the actual contents out of the ascii-armored version.
        {
            OTString strTemp(ascTemp); // <=== ascii-decoded here.
            std::string str_temp(strTemp.Get(), strTemp.GetLength());
            str_Trim = OTString::trim(str_temp); // This is the std::string for the trim process.
        } 
    }
    else
    {
        std::string str_temp(strInput.Get(), strInput.GetLength());
        str_Trim = OTString::trim(str_temp); // This is the std::string for the trim process. (Wasn't armored, so here we use it as passed in.)
    }
    // ------------------------------------------------
    
    // At this point, str_Trim contains the actual contents, whether they
    // were originally ascii-armored OR NOT. (And they are also now trimmed, either way.)
    // ------------------------------------------
    
    OTString strContract(str_Trim.c_str());
	
	strContract.reset(); // for sgets
	buf[0] = 0; // probably unnecessary.
	bool bGotLine = strContract.sgets(buf, 40);
    
	if (!bGotLine)
		return NULL;
	
	OTString strFirstLine(buf);
	strContract.reset(); // set the "file" pointer within this string back to index 0.
	
	// Now I feel pretty safe -- the string I'm examining is within
	// the first 45 characters of the beginning of the contract, and
	// it will NOT contain the escape "- " sequence. From there, if
	// it contains the proper sequence, I will instantiate that type.
	if (!strFirstLine.Exists() || strFirstLine.Contains("- -"))
		return NULL;
    
	if (strFirstLine.Contains("-----BEGIN SIGNED TRANSACTION-----"))  // this string is 34 chars long.
	{	pItem = new OTTransaction();		OT_ASSERT(NULL != pItem); }
	
	else if (strFirstLine.Contains("-----BEGIN SIGNED TRANSACTION ITEM-----"))  // this string is 39 chars long.
	{	pItem = new OTItem();	OT_ASSERT(NULL != pItem); }
	
	else if (strFirstLine.Contains("-----BEGIN SIGNED LEDGER-----"))  // this string is 29 chars long.
	{	pItem = new OTLedger();			OT_ASSERT(NULL != pItem); }
	
	else if (strFirstLine.Contains("-----BEGIN SIGNED ACCOUNT-----"))  // this string is 30 chars long.
	{	pItem = new OTAccount();			OT_ASSERT(NULL != pItem); }
	
	
	// The string didn't match any of the options in the factory.
	if (NULL == pItem)
		return NULL;
	
    // This causes pItem to load ASSUMING that the PurportedAcctID and PurportedServerID are correct.
    // The object is still expected to be internally consistent with its sub-items, regarding those IDs,
    // but the big difference is that it will SET the Real Acct and Real Server IDs based on the purported
    // values. This way you can load a transaction without knowing the account in advance.
    //
    pItem->m_bLoadSecurely = false;
    
//	OTLog::Error("\n\nTESTING DEBUGGING LOL LOL LOL LOL \n\n\n");

	// Does the contract successfully load from the string passed in?
	if (pItem->LoadContractFromString(strContract))
	{
		// NOTE: this already happens in OTTransaction::ProcessXMLNode and OTLedger::ProcessXMLNode.
		// Specifically, it happens when m_bLoadSecurely is set to false.
		//
//		pItem->SetRealServerID(pItem->GetPurportedServerID());
//		pItem->SetRealAccountID(pItem->GetPurportedAccountID());
//		
		return pItem;
	}
    else
		delete pItem;
	
	return NULL;
}