Esempio n. 1
0
const bool OTPaths::LoadSetScriptsFolder  // ie. PrefixFolder() + lib/opentxs/
	(
	OTSettings * pConfig, //optional
	const OTString & strScriptsFolder,	//optional
	const bool & bIsRelative			//optional
	)
{
	if (NULL == pConfig)  { OT_ASSERT(false); return false; }

	const bool bPreLoaded(pConfig->IsLoaded());

	if (!bPreLoaded)
	{
		pConfig->Reset();
		if(!pConfig->Load()) { OT_ASSERT(false); return false; }
	}

	OTString strRelativeKey = "";
	strRelativeKey.Format("%s%s","scripts",OT_CONFIG_ISRELATIVE);


	// local vairables.
	bool bConfigIsRelative = false;
	OTString strConfigFolder = "";


	// lets first check what we have in the configuration:
	{
	bool bKeyIsNew = false;

	if (!pConfig->CheckSet_bool("paths",strRelativeKey,true,bConfigIsRelative,bKeyIsNew)) { return false; }
	if (!pConfig->CheckSet_str("paths","scripts",OT_SCRIPTS_DIR,strConfigFolder,bKeyIsNew)) { return false; }
	}

	// lets first test if there was a folder passed in

	if ((strScriptsFolder.Exists()) && (3 < strScriptsFolder.GetLength())) {

		// we have a folder passed in, lets now check if we need to update anything:

		if (bConfigIsRelative != bIsRelative) {

			bConfigIsRelative = bIsRelative;
			bool bNewOrUpdated = false;

			if (!pConfig->Set_bool("paths", strRelativeKey, bConfigIsRelative, bNewOrUpdated)) { return false; }

		}

		if (!strConfigFolder.Compare(strScriptsFolder)) {

			strConfigFolder = strScriptsFolder; // update folder
			bool bNewOrUpdated = false;

			if (!pConfig->Set_str( "paths", "scripts", strConfigFolder, bNewOrUpdated)) { return false; }
		}
	}


	if(bConfigIsRelative)
	{
		if(!FixPath(strConfigFolder,strConfigFolder,true)) { OT_ASSERT(false); return false; }

		OTString strScriptPath = "";
		if(!AppendFolder(strScriptPath, PrefixFolder(), strConfigFolder)) { OT_ASSERT(false); return false; }

		m_strScriptsFolder = strScriptPath; // set
	}
	else
	{
		if(!ToReal(strConfigFolder, strConfigFolder)) { OT_ASSERT(false); return false; }
		if(!FixPath(strConfigFolder, strConfigFolder, true)) { OT_ASSERT(false); return false; }
		m_strScriptsFolder = strConfigFolder; // set
	}
		
	if (!bPreLoaded)
	{
		if(!pConfig->Save()) { OT_ASSERT(false); return false; }
		pConfig->Reset();
	}
	return true;  // success
}
Esempio n. 2
0
bool OTMint::SaveMint(const char * szAppend/*=NULL*/)
{
	if (!m_strFoldername.Exists())
		m_strFoldername.Set(OTFolders::Mint().Get());
	
	const OTString strServerID(m_ServerID), strAssetTypeID(m_AssetID);
	
	if (!m_strFilename.Exists())
	{
		if (NULL != szAppend)
			m_strFilename.Format("%s%s%s%s", strServerID.Get(), OTLog::PathSeparator(), // server side
								 strAssetTypeID.Get(), szAppend);
		else
			m_strFilename.Format("%s%s%s", strServerID.Get(), OTLog::PathSeparator(), strAssetTypeID.Get()); // client side
	}
	
	OTString strFilename;
	if (NULL != szAppend) 
		strFilename.Format("%s%s", strAssetTypeID.Get(), szAppend);
	else
		strFilename = strAssetTypeID.Get();
	
	const char * szFolder1name	= OTFolders::Mint().Get();
	const char * szFolder2name	= strServerID.Get();
	const char * szFilename		= strFilename.Get();
	
	// --------------------------------------------------------------------

	OTString strRawFile;

	if (!SaveContractRaw(strRawFile))
	{
		OTLog::vError("OTMint::SaveMint: Error saving Mintfile (to string):\n%s%s%s%s%s\n", szFolder1name,
					  OTLog::PathSeparator(), szFolder2name, OTLog::PathSeparator(), szFilename);
		return false;
	}
	// --------------------------------------------------------------------
	//
	OTString strFinal;
    OTASCIIArmor ascTemp(strRawFile);
    
    if (false == ascTemp.WriteArmoredString(strFinal, m_strContractType.Get()))
    {
		OTLog::vError("OTMint::SaveMint: Error saving mint (failed writing armored string):\n%s%s%s%s%s\n",
					  szFolder1name, OTLog::PathSeparator(), szFolder2name, OTLog::PathSeparator(), szFilename);
		return false;
    }
    // --------------------------------------------------------------------
	bool bSaved = OTDB::StorePlainString(strFinal.Get(), szFolder1name, 
										 szFolder2name, szFilename); // <=== SAVING TO LOCAL DATA STORE.
	if (!bSaved)
	{
		if (NULL != szAppend) 
			OTLog::vError("OTMint::SaveMint: Error writing to file: %s%s%s%s%s%s\n", szFolder1name,
					  OTLog::PathSeparator(), szFolder2name, OTLog::PathSeparator(), szFilename, szAppend);
		else
			OTLog::vError("OTMint::SaveMint: Error writing to file: %s%s%s%s%s\n", szFolder1name,
						  OTLog::PathSeparator(), szFolder2name, OTLog::PathSeparator(), szFilename);	

		return false;
	}
	// --------------------------------------------------------------------
	
	return true;
}
// *********************************************************************************************************
//
//
//             *** SERVER MAIN ***
//
//
// The MAIN function for the server software, which starts up the ZMQ listener, as well
// as well as the Open Transactions library and the OT Server object.
//
// After initialization, this function becomes the "main loop" of OT server.
//
int main(int argc, char* argv[])
{
	OTLog::vOutput(0, "\n\nWelcome to Open Transactions... Test Server -- version %s\n"
				   "(transport build: OTMessage -> OTEnvelope -> ZMQ )\n\n", OTLog::Version());

	// WINSOCK WINDOWS
	// -----------------------------------------------------------------------
#ifdef _WIN32

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
	wVersionRequested = MAKEWORD(2, 2);

	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
	/* Tell the user that we could not find a usable		*/
	/* Winsock DLL.											*/
		printf("WSAStartup failed with error: %d\n", err);
		return 1;
	}

	/*	Confirm that the WinSock DLL supports 2.2.			*/
	/*	Note that if the DLL supports versions greater		*/
	/*	than 2.2 in addition to 2.2, it will still return	*/
	/*	2.2 in wVersion since that is the version we		*/
	/*	requested.											*/

	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		printf("Could not find a usable version of Winsock.dll\n");
		WSACleanup();
		return 1;
	}
	else
		printf("The Winsock 2.2 dll was found okay\n");

	/* The Winsock DLL is acceptable. Proceed to use it. */
	/* Add network programming using Winsock here */
	/* then call WSACleanup when done using the Winsock dll */
#endif





	// ***********************************************************************
    // INITIALIZATION and CLEANUP (for the OT library, and for this server application.)
    //
    class __ot_server_
    {
        OTServer * m_pServer;
    public:
        OTServer * GetServer() { return m_pServer; }
        // -----------------------------------
        __ot_server_() : m_pServer(NULL) // INIT 
        {
            // -----------------------------------------------------------------------   
	
            // -----------------------------------------------------------------------
            // OTLog class exists on both client and server sides.
            // #define OT_NO_SIGNAL_HANDLING if you want to turn off OT's signal handling.
            //
#if defined(OT_SIGNAL_HANDLING)
            OTLog::SetupSignalHandler(); // This is optional! (I, of course, am using it in this test app...)
#endif
            // -----------------------------------------------------------------------    
            // I instantiate this here (instead of globally) so that I am assured that any globals and other
            // setup is already done before we instantiate the server object itself.
            //
            OT_ASSERT_MSG(NULL == m_pServer, "server main(): ASSERT: NULL == m_pServer.");
            m_pServer = new OTServer;
            //
            // (This .cpp file you are currently reading is a wrapper for OTServer,
            // which adds the transport layer.)
            //
            OT_ASSERT_MSG(NULL != m_pServer, "server main(): ASSERT: Unable to instantiate OT server.\n");

			OTString pathUserAppDataPath, pathIniFileLocation;

			pathUserAppDataPath = GetRoamingAppDataLocation();
			pathIniFileLocation.Format("%s%s%s", pathUserAppDataPath.Get(), OTLog::PathSeparator(), SERVER_INI_FILE_DEFAULT);


			OTString pathOTServerDataLocation;

			OTLog::vOutput(0, "\nFound ot_init.cfg in: \n     %s \nNow checking to see if it contains the OT Server path...", pathIniFileLocation.Get());
			// Read the File, If successful use result

			if (false == GetOTAppDataFolderLocation(pathIniFileLocation, pathOTServerDataLocation))
			{
				OTLog::vOutput(0, "Path not found... Will attempt default!... \n");
				// Not successfull will will assume it is in default location:
				pathOTServerDataLocation.Format("%s%s%s", pathUserAppDataPath.Get(), OTLog::PathSeparator(), SERVER_PATH_DEFAULT);
			};

			OTLog::vOutput(0, "     %s \n", pathOTServerDataLocation.Get());


			OTLog::SetMainPath(pathOTServerDataLocation.Get());              // <============ SET MAIN PATH
            OTLog::vOutput(0, "Using server_data path:  %s\n", OTLog::Path());


            // -----------------------------------------------------------------------    
            
            OTCrypto::It()->Init();  // <========== (OpenSSL gets initialized here.)
            
        }
        // ****************************************
        //
        ~__ot_server_()  // CLEANUP
        {
            OTLog::vOutput(0, "\n\n OT version %s, shutting down and cleaning up.\n",
                           OTLog::Version());

            // ------------------------------
            if (NULL != m_pServer)
                delete m_pServer;
            m_pServer = NULL;
            // ------------------------------
            // We clean these up in reverse order from the Init function, which just seems
            // like the best default, in absence of any brighter ideas.
            //
            OTCrypto::It()->Cleanup();  // <======= (OpenSSL gets cleaned up here.)

            // -------------------------
            // (This is at the bottom, since we do the cleanup in the 
            // reverse order from initialization.)
#ifdef _WIN32
            WSACleanup();
#endif
        }
    };	
	// ***********************************************************************
    //
    // INSTANTIATE and INITIALIZE...
    //
    // (Cleanup happens automatically when this object goes out of scope.)
    //
    __ot_server_  the_server_obj;
    OTServer * pServer = the_server_obj.GetServer();
    OT_ASSERT(NULL != pServer);
    // -----------------------------------------------------------------------
//	OTString strCAFile, strDHFile, strKeyFile;  //, strSSLPassword;
//	strCAFile. Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), CA_FILE);
//	strDHFile. Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), DH_FILE);
//	strKeyFile.Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), KEY_FILE);
	// -----------------------------------------------------------------------
    //
    // UPDATE: This was moved to OTLog::OT_Init(), which is called above, by the
    // nested cleanup class.
    //
	// Initialize SSL -- This MUST occur before any Private Keys are loaded!
//	SSL_library_init();
//	SSL_load_error_strings();
	
	// -----------------------------------------------------------------------
	// OTServer::Init loads up server's nym so it can decrypt messages sent in
    // envelopes. It also does various other initialization work.
	//
	// (Envelopes prove that ONLY someone who actually had the server contract,
	//  and had loaded it into his wallet, could ever connect to the server or 
	//  communicate with it. And if that person is following the contract, there
	//  is only one server he can connect to, and one key he can use to talk to it.)
	//
	OTLog::vOutput(0, 
				   "\nNow loading the server nym, which will also ask you for a password, to unlock\n"
				   "its private key. (Default password is \"%s\".)\n", KEY_PASSWORD);
	
	pServer->Init(); // Keys, etc are loaded here. ===> Assumes main path is set! <===
	
	// -----------------------------------------------------------------------
	// We're going to listen on the same port that is listed in our server contract.
	//
	//
	OTString	strHostname;	// The hostname of this server, according to its own contract.
	int			nPort=0;		// The port of this server, according to its own contract.
	
    const bool bConnectInfo = pServer->GetConnectInfo(strHostname, nPort);
    
	OT_ASSERT_MSG(bConnectInfo, "server main: Unable to find my own connect info (which SHOULD be in my server contract, BTW.) Perhaps you failed trying to open that contract? Have you tried the test password? (\"test\")\n");
	
	const int   nServerPort = nPort;
	
	// -----------------------------------------------------------------------
    // OT CRON
    //
    // A heartbeat for recurring transactions, such as markets, payment plans,
    // and smart contracts.

	pServer->ActivateCron();

    // NOTE: Currently we trigger OT Cron's processing internally, but there's no reason why, in the
    // future, we can't make an actual cron job that triggers a script, that fires a message
    // to OT, causing OT to process its Cron (even if we were single-threaded we could do this...)
    //
    // Have to put some thought into it...
    //
    // Wouldn't require much security, since OT can still be smart enough not to process cron any
    // more often than X minutes, no matter HOW many times the ProcessCron script fires.
    // Thing is, though, that with this setup, we can't really guarantee that cron will EVER be
    // triggered -- whereas the way OT is now, at least we know it WILL fire every X seconds.
    //
    
	// --------------------------------------
    //
    // NETWORK
    //
	// Prepare our context and listening socket...

	OTSocket theSocket;
	OTString strBindPath; strBindPath.Format("%s%d", "tcp://*:", nServerPort);
	theSocket.Listen(strBindPath);
    
    // ******************************************************************************************
    //
    //      *** MAIN LOOP ***
    //
	do // ---------------------------
	{
        // =-=-=- HEARTBEAT -=-=-=
		//
		// The Server now processes certain things on a regular basis.
		// ProcessCron is what gives it the opportunity to do that.
		// All of the Cron Items (including market trades, payment plans, smart contracts...) 
		// they all have their hooks here...
		//
		pServer->ProcessCron();  // Internally this is smart enough to know how often to actually activate itself.
                                   // Most often it just returns doing nothing (waiting for its timer.)		
		// -----------------------------------------------------------------------
		// Wait for client http requests (and process replies out to them.)
		// ----------------------------------------------------------------------
		// Number of requests to process per heartbeat: OTServer::GetHeartbeatNoRequests()
		//
		// Loop: process up to 10 client requests, then sleep for 1/10th second.
		// That's a total of 100 requests per second. Can the computers handle it? 
		// Is it too much or too little? Todo: load testing.
		//
		// Then: check for shutdown flag.
		//
		// Then: go back to the top ("do") and repeat the loop.... process cron, 
		// process 10 client requests, sleep, check for shutdown, etc.
		//
		//
                
		Timer t;	// start timer
		t.start();
		const double tick1 = t.getElapsedTimeInMilliSec();
		// -----------------------------------------------------
		//
        // PROCESS X NUMBER OF REQUESTS (THIS PULSE.)
        //
        // Theoretically the "number of requests" that we process EACH PULSE.
        // (The timing code here is still pretty new, need to do some load testing.)
        //
		for (int i = 0; i < /*10*/OTServer::GetHeartbeatNoRequests(); i++) 
		{
			std::string	str_Message;
			
			// With 100ms heartbeat, receive will try 100 ms, then 200 ms, then 400 ms, total of 700.
			// That's about 15 Receive() calls every 10 seconds. Therefore if I want the ProcessCron()
			// to trigger every 10 seconds, I need to set the cron interval to roll over every 15 heartbeats.
			// Therefore I will be using a real Timer for Cron, instead of the damn intervals.
			//
			bool bReceived = theSocket.Receive(str_Message);  
			
			if  (bReceived)
			{
				std::string str_Reply; // Output.
				
				if (str_Message.length() <= 0)
				{
					OTLog::Error("server main: Received a message, but of 0 length or less. Weird. (Skipping it.)\n");
				}
				else // ------------------------------------
				{
                    // true  == YES, DISCONNECT m_pSocket, something must have gone wrong.
                    // false ==  NO, do NOT disconnect m_pSocket, everything went wonderfully!
                    //
					const bool bShouldDisconnect = ProcessMessage_ZMQ(*pServer, str_Message, str_Reply); // <================== PROCESS the message!
					// --------------------------------------------------

					if ((str_Reply.length() <= 0) || bShouldDisconnect)
					{
						OTLog::vOutput(0, "server main: ERROR: Unfortunately, not every client request is "
                                       "legible or worthy of a server response. :-)  "
									   "Msg:\n\n%s\n\n", str_Message.c_str());
                        
                        theSocket.Listen();
					}
					else
					{
						bool bSuccessSending = theSocket.Send(str_Reply); // <===== SEND THE REPLY
						
						if (false == bSuccessSending)
							OTLog::vError("server main: Socket ERROR: failed while trying to send reply "
                                          "back to client! \n\n MESSAGE:\n%s\n\nREPLY:\n%s\n\n", 
										  str_Message.c_str(), str_Reply.c_str());
						// --------------------------------------------------
					}
				}
			}
		} //  for
		
		// -----------------------------------------------------------------------
		//
        // IF the time we had available wasn't all used up -- if some of it is still
        // available, then SLEEP until we reach the NEXT PULSE. (In practice, we will 
        // probably use TOO MUCH time, not too little--but then again OT isn't ALWAYS
        // processing a message. There could be plenty of dead time in between...)
        //
		const	double tick2	= t.getElapsedTimeInMilliSec();
		const	long elapsed	= static_cast<long>(tick2 - tick1);
		long	lSleepMS		= 0;
			
		if (elapsed < /*100*/OTServer::GetHeartbeatMsBetweenBeats()) 
		{
			lSleepMS = OTServer::GetHeartbeatMsBetweenBeats() - elapsed;

			// Now go to sleep.
			// (The main loop processes ten times per second, currently.)		
			OTLog::SleepMilliseconds(lSleepMS); // 100 ms == (1 second / 10)
		}
		
		// -----------------------------------------------------------------------
		// ARTIFICIAL LIMIT:
		// 10 requests per heartbeat, 10 rounds per second == 100 requests per second.
		//
		// *** ONE HUNDRED CLIENT MESSAGES PER SECOND is the same as:
		// 
		//     6000 PER MINUTE == 360,000 PER HOUR == 8,640,000 PER DAY***
		//
		// Speeding it up is just a matter of adjusting the above numbers, and LOAD TESTING,
        // to see if OT can handle it. (Not counting optimization of course.)
		//
		// -----------------------------------------------------------------------

		if (pServer->IsFlaggedForShutdown())
		{
			OTLog::Output(0, "main: OT Server is shutting down gracefully....\n");
			break;
		}
        
    } while (1);  // (MAIN LOOP)
    
	// ------------------------------------
    
	return 0;
}
Esempio n. 4
0
void OTMessageOutbuffer::AddSentMessage(OTMessage & theMessage) // must be heap allocated.
{
    int64_t lRequestNum = 0;
    
    if (theMessage.m_strRequestNum.Exists())
        lRequestNum = atol(theMessage.m_strRequestNum.Get()); // The map index is the request number on the message itself.
    // ----------------
    // It's technically possible to have TWO messages (from two different
    // servers) that happen to have the same request number. So we verify
    // that here, before removing any old ones with the same number and IDs.
    //
    mapOfMessages::iterator it = m_mapMessages.begin();
    
    for (; it != m_mapMessages.end(); ++it)
    {
        // -----------------------------
        const int64_t  & lTempReqNum   = it->first;
        // -----------------------
        if (lTempReqNum != lRequestNum)
        {
            continue;
        }
        // -----------------------
        OTMessage   * pMsg          = it->second;
        OT_ASSERT(NULL != pMsg);
        // -----------------------------
        //
        // If a server ID was passed in, but doesn't match the server ID on this message,
        // Then skip this one. (Same with the NymID.)
        //
        if (!theMessage.m_strServerID.Compare(pMsg->m_strServerID) ||
            !theMessage.m_strNymID.   Compare(pMsg->m_strNymID))
        {
            continue;
        }
        // --------
        else
        {
            delete pMsg;
            pMsg = NULL;
            m_mapMessages.erase(it);
            break;
        }
    }
    // Whatever it was, it's gone now!
    // ----------------------------------
    // Now that we KNOW there's nothing already there with that request number (for that
    // server ID and Nym ID), we go ahead and add the new message to the map. (And take ownership.)
    //
    m_mapMessages.insert(std::pair<int64_t, OTMessage *>(lRequestNum, &theMessage));
    // ----------------------------------
    //
    // Save it to local storage, in case we don't see the reply until the next run.
    //
    bool bAlreadyExists=false, bIsNewFolder=false;
    OTString strFolder, strFolder1, strFolder2;
    strFolder1.Format("%s%s%s",
                      OTFolders::Nym().Get(),               OTLog::PathSeparator(),
                      theMessage.m_strServerID.Get());
    strFolder2.Format("%s%s%s", strFolder1.Get(), OTLog::PathSeparator(),
                      "sent" /*todo hardcoding*/);
    // ----------------------------------
    strFolder.Format("%s%s%s", strFolder2.Get(), OTLog::PathSeparator(),
                     theMessage.m_strNymID.Get());
    // ----------------------------------

	OTString strFolderPath = "", strFolder1Path = "", strFolder2Path = "";

	OTPaths::AppendFolder(strFolderPath,  m_strDataFolder,strFolder );
	OTPaths::AppendFolder(strFolder1Path, m_strDataFolder,strFolder1);
	OTPaths::AppendFolder(strFolder2Path, m_strDataFolder,strFolder2);

	OTPaths::ConfirmCreateFolder(strFolderPath,bAlreadyExists,bIsNewFolder);
	OTPaths::ConfirmCreateFolder(strFolder1Path,bAlreadyExists,bIsNewFolder);
	OTPaths::ConfirmCreateFolder(strFolder2Path,bAlreadyExists,bIsNewFolder);
    
    OTString strFile;
    strFile.Format("%s.msg", theMessage.m_strRequestNum.Get());
    
    theMessage.SaveContract(strFolder.Get(), strFile.Get());
    // ----------------------------------
    // We also keep a list of the request numbers, so let's load it up, add the number
    // to that list, and then save it again.
    //
    OTNumList theNumList;
    std::string str_data_filename("sent.dat"); // todo hardcoding.
    if (OTDB::Exists(strFolder.Get(), str_data_filename))
    {
        OTString strNumList(OTDB::QueryPlainString(strFolder.Get(), str_data_filename));
        if (strNumList.Exists())
            theNumList.Add(strNumList);
        theNumList.Add(lRequestNum); // Add the new request number to it.
    }
    else // it doesn't exist on disk, so let's just create it from the list we have in RAM so we can store it to disk.
    {
        it = m_mapMessages.begin();
        while (it != m_mapMessages.end())
        {
            // -----------------------------
            const int64_t  & lTempReqNum   = it->first;
            // -----------------------
            OTMessage   * pMsg          = it->second;
            OT_ASSERT(NULL != pMsg);
            // -----------------------------
            //
            // If a server ID was passed in, but doesn't match the server ID on this message,
            // Then skip this one. (Same with the NymID.)
            //
            if (!theMessage.m_strServerID.Compare(pMsg->m_strServerID) ||
                !theMessage.m_strNymID.   Compare(pMsg->m_strNymID))
            {
                ++it;
                continue;
            }
            // --------
            else
            {
                theNumList.Add(lTempReqNum);
            }
            ++it;
        }
    }// else
    // ----------------------------------
    // By this point, theNumList has either been loaded from local storage and had the new number added,
    // or it wasn't in local storage and thus we created it and added all the numnbers to it (including new one.)
    // Therefore nothing left to do here, but save it back again!
    //
    OTString strOutput;
    theNumList.Output(strOutput);
    
    if (!OTDB::StorePlainString(strOutput.Get(), strFolder.Get(), str_data_filename)) // todo hardcoding.
    {
        OTLog::Error("OTMessageOutbuffer::AddSentMessage: Error: failed writing list of request numbers to storage.\n");
    }
}
Esempio n. 5
0
int main (int argc, char * const argv[])
{
	if (argc < 4)
	{
		printf("\n\nUsage:  createmint  server_id  server_user_id  asset_type_id \n\n"
			"For now, expiration dates are automatically set:\n"
			"-- FROM: Today, Now.\n"
			"-- TO: 6 months from now.\n\n"
			"It is recommended that you issue a new series (create a new mint) every 3 months for each\n"
			"asset type, so that there is a 3-month overlap. In the future, this will be configured inside\n"
			"the contracts themselves.\n\n"
			"Server ID needs to match the Server ID from notaryServer.xml\n"
			"Server user ID needs to match the Server User ID from notaryServer.xml\n"
			"Asset Type ID needs to match the Asset ID (aka Hashed Contract ID) of the currency contract.\n\n"
			//			   "The path to the data folder is necessary for initialization of the OT library.\n\n"
			//             "(You probably want to use ~/.ot/server_data as your data folder.)\n\n"
			);
		return 0;
	}
	// **************************************************************************

	class __OTcreatemint_RAII
	{
	public:
		__OTcreatemint_RAII()
		{
			if(!OTLog::Init(SERVER_CONFIG_KEY,0)) { assert(false); };  // setup the logger.

			OTLog::vOutput(0, "\n\nWelcome to Open Transactions -- 'createmint', version %s\n", 
				OTLog::Version());
			// ------------------------------------
#ifdef _WIN32
			WSADATA wsaData;
			WORD wVersionRequested = MAKEWORD( 2, 2 );
			int err = WSAStartup( wVersionRequested, &wsaData );

			/* Tell the user that we could not find a usable		*/
			/* Winsock DLL.											*/		

			OT_ASSERT_MSG((err == 0), "WSAStartup failed!\n");


			/*	Confirm that the WinSock DLL supports 2.2.			*/
			/*	Note that if the DLL supports versions greater		*/
			/*	than 2.2 in addition to 2.2, it will still return	*/
			/*	2.2 in wVersion since that is the version we		*/
			/*	requested.											*/

			bool bWinsock = (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2);

			/* Tell the user that we could not find a usable */
			/* WinSock DLL.                                  */

			if (!bWinsock) WSACleanup();  // do cleanup.
			OT_ASSERT_MSG((!bWinsock), "Could not find a usable version of Winsock.dll\n");

			/* The Winsock DLL is acceptable. Proceed to use it. */
			/* Add network programming using Winsock here */
			/* then call WSACleanup when done using the Winsock dll */
			OTLog::vOutput(0,"The Winsock 2.2 dll was found okay\n");
#endif
			// ------------------------------------
			// SIGNALS
			//
#if defined(OT_SIGNAL_HANDLING)
			//
			OTLog::SetupSignalHandler();  // <===== SIGNALS
			//
			// This is optional! You can always remove it using the OT_NO_SIGNAL_HANDLING
			//  option, and plus, the internals only execute once anyway. (It keeps count.)
#endif
			// ------------------------------------

			//
			// OT Server Path:
			//
			{
				bool bSetupPathsSuccess = false;
				if(!OTDataFolder::Init(SERVER_CONFIG_KEY)) { OT_FAIL; }
				else
					bSetupPathsSuccess = true;

				OT_ASSERT_MSG(bSetupPathsSuccess, "main(): Assert failed: Failed to set OT Path");
			}

			// -----------------------------------------------------------------------    

			OTCrypto::It()->Init(); // (OpenSSL gets initialized here.)

			// ------------------------------------
		}
		~__OTcreatemint_RAII()
		{
			// We clean these up in reverse order from the Init function, which just seems
			// like the best default, in absence of any brighter ideas.
			//
			OTCrypto::It()->Cleanup();  // (OpenSSL gets cleaned up here.)

			// ------------------------------------
#ifdef _WIN32
			WSACleanup(); // Corresponds to WSAStartup() in InitOTAPI().
#endif
			// ------------------------------------
		}
	};
	// --------------------------------------------

	__OTcreatemint_RAII   the_createmint_cleanup;

	// **************************************************************************

	OTServer theServer;

	// -----------------------------------------

	int nReturnVal = 0;

	OTString		strServerID(argv[1]),
                    strServerNymID(argv[2]),
                    strAssetTypeID(argv[3]);

	OTIdentifier	ASSET_TYPE_ID(strAssetTypeID),
                    SERVER_ID(strServerID);

	//	std::string strDataFolderPath(argv[4]), strNotaryFile("notaryServer.xml");

	OTLog::vOutput(0, 
		"\nNow loading the server nym, which will also ask you for a password, to unlock\n"
		"its private key. (Default password is \"%s\".)\n", KEY_PASSWORD);

	// Keys, etc are loaded here. ===> Assumes main path is set! <===
	//
	theServer.Init(true); //bool bReadOnly=false by default (We don't want to overwrite anything if the ACTUAL server is running...)


	//  NOTE: I copied some code in here from xmlrpcxx_server.cpp, including the above
	//  call to theServer.Init(), which has the InitDefaultStorage inside of it, and
	//  which uses OTLog::Path(), which the above new code should be setting properly
	//  before theServer.Init() actually gets called. (So this should work....)
	//  
	//	bool bSuccessInitDefault = OTDB::InitDefaultStorage(OTDB_DEFAULT_STORAGE, 
	//														OTDB_DEFAULT_PACKER, strDataFolderPath, strNotaryFile);
	//    if (!bSuccessInitDefault)
	//    {
	//        OTLog::vError("\n\n%s: Failed invoking OTDB::InitDefaultStorage with path: %s and main filename: %s\n\n",
	//                      __FUNCTION__, strDataFolderPath.c_str(), strNotaryFile.c_str());
	//        return 0;
	//    }
	// -----------------------------------------

	OTString strMintPath;
	bool bFileIsPresent = false;		
	int nSeries = 0;

	for (nSeries = 0; nSeries < 10000; ++nSeries)
	{
//		struct stat st;

		OTString strFilename;
		strFilename.Format("%s%s%d", strAssetTypeID.Get(), ".", nSeries);

		bFileIsPresent = OTDB::Exists(OTFolders::Mint().Get(),
                                      strServerID.Get(),
                                      strFilename.Get());

		// Old Code
		//strMintPath.Format("%s%s%s%s%s%s%s%s%d", 
		//	OTLog::Path(), 
		//	OTLog::PathSeparator(),
		//	OTFolders::Mint().Get(),
		//	OTLog::PathSeparator(),
		//	strServerID.Get(),
		//	OTLog::PathSeparator(),
		//	strAssetTypeID.Get(), ".", nSeries);
		//bFileIsPresent = (stat(strMintPath.Get(), &st) == 0);

		if (!bFileIsPresent)
			break;
	}

	// if bFileIsPresent is STILL true, that means we got all the way up to 1000 and the 
	// file was present every time.
	// Geez, there must be 10000 mints on this computer.  At one new Mint per 3 months,
	// that's 4 per year, that's 2500 years already!!
	//
	if (bFileIsPresent)
	{
		OTLog::Output(0, "\n\nThis program automatically finds the next series, up to 10000. You\n"
			"have reached 10000. You will have to change the source code of this\n"
			"program in order to continue. Sorry.\n\n");
		return 0;
	}
	// ---------------------------------------------------------------------

	// nSeries now contains the number we need to use for the next series.
	// and strMintPath now contains the correct file path.

	OTMint * pMint = OTMint::MintFactory(strServerID, strServerNymID, strAssetTypeID);
	OT_ASSERT(NULL != pMint);

	OTString strSeries; strSeries.Format("%s%d", ".", nSeries);

	if (pMint->LoadMint(strSeries.Get()))
	{
		OTLog::Output(0, "\n\nSorry, that mint already exists. Delete it first if you wish to re-create it.\n\n");
	}
	else 
	{
		OTLog::vOutput(0, "\n\nMint file does not (yet) exist for series %d and asset type:\n%s\n Creating......\n\n", 
			nSeries, strAssetTypeID.Get());

		// TODO: read the denominations out of the asset contract itself, instead of hardcoding them here.


		// Calculate FROM as Today, Now, 
		// then calculate TO as 6 months from now, 
		// and EXPIRATION as 3 months from now.
		//
		// TODO: Let these numbers be configured either in server operator contract, or issuer contract.
		// In the meantime, 3 and 6 months are good enough.

		OTPseudonym theNym;
		theNym.SetIdentifier(strServerNymID);

		// 1 hour	==     3600 Seconds
		// 1 day	==    86400 Seconds
		// 30 days	==  2592000 Seconds
		// 3 months ==  7776000 Seconds
		// 6 months == 15552000 Seconds


		// This part requires the server operator to enter his passphrase.
		// Which is why the server can't just fire it off automatically and
		// make a mint available to the client.  The client has to wait a day or
		// until the operator is able to run this script and type the passphrase.
		if (theNym.Loadx509CertAndPrivateKey(false))
		{								
			const time_t	CURRENT_TIME	= time(NULL), 
				VALID_TO		= CURRENT_TIME + 15552000,	// Tokens generated by this mint are valid from today until 6 months from today
				MINT_EXPIRATION	= CURRENT_TIME + 7776000;	// The mint itself will expire in 3 months from today, and be replaced with a new one.

			pMint->GenerateNewMint(nSeries, CURRENT_TIME, VALID_TO, MINT_EXPIRATION, ASSET_TYPE_ID, SERVER_ID,
				// penny, nickel, dime, quarter, $1, $5, $10, $20, $100, $1000
				theNym, 1, 5, 10, 25, 100, 500, 1000, 2000, 10000, 100000);
			// should be: 1, 2, 4,   8,  16,  32,   64,  128,   256,    512, 1024, 2048, 4096, 8192, 16384, 32768, 65536

			// ---------------------------------------

//			OTString strFilename;// strPUBLICFilename;		
//			strFilename.		Format("%s%s%s",		strServerID.Get(), OTLog::PathSeparator(), strAssetTypeID.Get());
//			strPUBLICFilename.	Format("%s%s%s%sPUBLIC",strServerID.Get(), OTLog::PathSeparator(), strAssetTypeID.Get(), ".");

			if (!OTDataFolder::IsInitialized()) { OT_FAIL; }

			OTString strServerFolder(""), strMintFolder("");
            
//            OTLog::vError("DEBUGGING: OTDataFolder::Get().Get(): %s \n", OTDataFolder::Get().Get());
//            OTLog::vError("DEBUGGING: OTFolders::Mint().Get(): %s \n",   OTFolders::Mint().Get());
//            OTLog::vError("DEBUGGING: strServerID.Get(): %s \n",   strServerID.Get());
            
			if (!OTPaths::AppendFolder(strMintFolder,	OTDataFolder::Get(), OTFolders::Mint())) { OT_FAIL; } // mint/
			if (!OTPaths::AppendFolder(strServerFolder,	strMintFolder,		 strServerID.Get())) { OT_FAIL; } // mint/serverID

			bool bFolderCreated;
			if (OTPaths::BuildFolderPath(strServerFolder, bFolderCreated))
			{
				// -------------------------------------------------------------------
				// This causes the next serialization to save the private, not just public, keys.
				pMint->SetSavePrivateKeys(); // <== PRIVATE MINT VERSION.

				pMint->SignContract(theNym);
				pMint->SaveContract();
				pMint->SaveMint();		// save the private mint file as: path/mints/server_id/Asset_TypeID (overwriting the last "current mint"...)
				pMint->SaveMint(strSeries.Get()); // save the private mint file as: path/mints/server_id/Asset_TypeID.nSeries (These accumulate.)

				// When the server needs to reference the "current" private keys, then it just loads the
				// mint without specifying the series number. Since this file is overwritten with each new 
				// mint, it is thus always the latest one.  (Similarly, the latest public is always asset_id.PUBLIC)
				// On the other hand, if I need to load the keys for a specific series, (since more than one may be
				// redeemable, even if only the latest one is being issued) then they are all also saved by series
				// number, which is not overwritten with each new mint, but accumulates.
				// That is why above, you see me save the mint twice in two different files, and below you see
				// it being saved with the .PUBLIC appending to the filename.

//				pMint->SaveContract(OTFolders::Mint().Get(), strFilename.Get());  // save the mint file.

				// -------------------------------------------------------------------
				// Now I sign it again, to get the private keys out of there.
				pMint->ReleaseSignatures();
				pMint->SignContract(theNym);
				pMint->SaveContract();
				pMint->SaveMint(".PUBLIC");  // save the public mint file.
//				pMint->SaveContract(OTFolders::Mint().Get(), strPUBLICFilename.Get());  // save the public mint file.

				nReturnVal = 1;

				OTLog::Output(0, "\nDone.\n\n");
			}
			else
				OTLog::Output(0, "\n\nError calling OTLog::ConfirmOrCreateFolder() for path/mints/server_id\n\n");
		}
		else
			OTLog::Output(0, "\n\nError calling theNym.Loadx509CertAndPrivateKey(false)\n\n");
	} // Mint file doesn't exist yet (therefore the above block creates it...)

	return nReturnVal;
}
Esempio n. 6
0
// ---------------------------------------
// For outgoing, pending (not-yet-accepted) instruments.
//
bool MTRecord::CancelOutgoing(const std::string str_via_acct) // This can be blank if it's a cheque.
{
    if (!this->CanCancelOutgoing())
        return false;
    
    switch (this->GetRecordType())
    {
        case MTRecord::Instrument:
        {
            if (m_str_nym_id.empty())
            {
                OTLog::vError("%s: Error: missing nym id (%s)\n",
                              __FUNCTION__, m_str_nym_id.c_str());
                return false;
            }
            
            const OTIdentifier theNymID(m_str_nym_id);
            // ------------------------------
            std::string str_using_acct;
            
            if (this->IsCheque())
            {
                str_using_acct = m_str_account_id;
            }
            else
            {
                str_using_acct = str_via_acct;
            }
            // ---------------------------------------
            if (str_using_acct.empty())
            {
                OTLog::vError("%s: Error: Missing account ID (FAILURE)\n", __FUNCTION__);
                return false;
            }
            // ------------------------------
            if (0 == m_lTransactionNum)
            {
                if (IsCash())
                {
                    // Maybe it's cash...
                    std::string strOutpayment(OTAPI_Wrap::GetNym_OutpaymentsContentsByIndex(m_str_nym_id, GetBoxIndex()));
                    
                    if (strOutpayment.empty())
                    {
                        long lIndex = static_cast<long>(GetBoxIndex());
                        OTLog::vError("%s: Error: Blank outpayment at index %ld\n", __FUNCTION__, lIndex);
                        return false;
                    }
                    // ------------------------
                    OTString  strPayment(strOutpayment);
                    OTPayment thePayment(strPayment);
                    
                    if (!thePayment.IsValid() || !thePayment.SetTempValues())
                    {
                        long lIndex = static_cast<long>(GetBoxIndex());
                        OTLog::vError("%s: Error: Invalid outpayment at index %ld\n", __FUNCTION__, lIndex);
                        return false;
                    }
                    // ------------------------
                    long lTransNum = 0;
                    thePayment.GetOpeningNum(lTransNum, theNymID);
                    // ------------------------
                    if (0 == lTransNum) // Found it.
                    {
                        long lIndex = static_cast<long>(GetBoxIndex());
                        OTString strIndices;
                        strIndices.Format("%ld", lIndex);
                        const std::string str_indices(strIndices.Get());
                        // ---------------------------------
                        OT_ME madeEasy;
                        
                        return madeEasy.cancel_outgoing_payments(m_str_nym_id, str_using_acct, str_indices);
                    }
                    else
                    {
                        OTLog::vError("%s: Error: Transaction number is non-zero (%ld), for cash outgoing payment for nym id (%s)\n",
                                      __FUNCTION__, lTransNum, m_str_nym_id.c_str());
                        return false;
                    }
                } // IsCash()
                else
                {
                    OTLog::vError("%s: Error: Transaction number is 0, for non-cash outgoing payment for nym id (%s)\n",
                                  __FUNCTION__, m_str_nym_id.c_str());
                    return false;
                }
            }
            // ---------------------------------------
            // Find the payment in the Nym's outpayments box that correlates to this MTRecord.
            //
            int32_t nCount = OTAPI_Wrap::GetNym_OutpaymentsCount(m_str_nym_id);
            
            for (int32_t nIndex = 0; nIndex < nCount; ++nIndex)
            {
                std::string strOutpayment(OTAPI_Wrap::GetNym_OutpaymentsContentsByIndex(m_str_nym_id, nIndex));
                
                if (strOutpayment.empty())
                {
                    long lIndex = nIndex;
                    OTLog::vError("%s: Error: Blank outpayment at index %ld\n", __FUNCTION__, lIndex);
                    return false;
                }
                // ------------------------
                OTString  strPayment(strOutpayment);
                OTPayment thePayment(strPayment);
                
                if (!thePayment.IsValid() || !thePayment.SetTempValues())
                {
                    long lIndex = nIndex;
                    OTLog::vError("%s: Error: Invalid outpayment at index %ld\n", __FUNCTION__, lIndex);
                    return false;
                }
                // ------------------------
                long lTransNum = 0;
                thePayment.GetOpeningNum(lTransNum, theNymID);
                // ------------------------
                if (lTransNum == m_lTransactionNum) // Found it.
                {
                    long lIndex = nIndex;
                    OTString strIndices;
                    strIndices.Format("%ld", lIndex);
                    const std::string str_indices(strIndices.Get());
                    // ---------------------------------
                    OT_ME madeEasy;
                    
                    return madeEasy.cancel_outgoing_payments(m_str_nym_id, str_using_acct, str_indices);
                }
            } // for
            // ---------------------------------------------------
        }
            break;
            // -----------------------------
        default:
            OTLog::vError("%s: Unexpected type: %s\n",
                          __FUNCTION__, this->GetInstrumentType().c_str());
            return false;
    }
    
    return true;
}
Esempio n. 7
0
// ---------------------------------------
// For incoming, pending (not-yet-accepted) instruments.
//
bool MTRecord::DiscardIncoming()
{
    if (!this->CanDiscardIncoming())
        return false;
    
    switch (this->GetRecordType())
    {
        case MTRecord::Instrument:
        {
            if (m_str_server_id.empty() || m_str_nym_id.empty())
            {
                OTLog::vError("%s: Error: missing server id (%s) or nym id (%s)\n",
                              __FUNCTION__, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------
            if (0 == m_lTransactionNum)
            {
                OTLog::vError("%s: Error: Transaction number is 0, in payment inbox for server id (%s), nym id (%s)\n",
                              __FUNCTION__, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------
            const OTIdentifier theServerID(m_str_server_id), theNymID(m_str_nym_id);
            
            // Open the Nym's payments inbox.
            OTLedger * pInbox = OTAPI_Wrap::OTAPI()->LoadPaymentInbox(theServerID, theNymID);
            OTCleanup<OTLedger> theInboxAngel(pInbox);
            // ------------------------------------------
            if (NULL == pInbox)
            {
                OTLog::vError("%s: Error: Unable to load payment inbox for server id (%s), nym id (%s)\n",
                              __FUNCTION__, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------------------
            // Find the payment therein that correlates to this MTRecord.
            //
            int nIndex = pInbox->GetTransactionIndex(m_lTransactionNum);
            
            if ((-1) == nIndex)
            {
                OTLog::vError("%s: Error: Unable to find transaction %ld in payment inbox for server id (%s), nym id (%s)\n",
                              __FUNCTION__, m_lTransactionNum, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------------------
            // Accept it.
            //
            OTString strIndices;
            strIndices.Format("%d", nIndex);
            const std::string str_indices(strIndices.Get());
            
            OT_ME madeEasy;
            
            return madeEasy.discard_incoming_payments(m_str_server_id, m_str_nym_id, str_indices);
            
        } // case: instrument
            break;
            // --------------------------------------------
        default:
            OTLog::vError("%s: Unexpected type: %s\n",
                          __FUNCTION__, this->GetInstrumentType().c_str());
            return false;
    }
    
    return true;
}
Esempio n. 8
0
// ---------------------------------------
// For incoming, pending (not-yet-accepted) instruments.
//
bool MTRecord::AcceptIncomingInstrument(const std::string & str_into_acct)
{
    if (!this->CanAcceptIncoming())
        return false;
    
    switch (this->GetRecordType())
    {
            // --------------------------------------------
            // Accept from Nym's payments inbox.
            //
        case MTRecord::Instrument:
        {
            if (m_str_server_id.empty() || m_str_nym_id.empty())
            {
                OTLog::vError("%s: Error: missing server id (%s) or nym id (%s)\n",
                              __FUNCTION__, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------
            if (0 == m_lTransactionNum)
            {
                OTLog::vError("%s: Error: Transaction number is 0, in payment inbox for server id (%s), nym id (%s)\n",
                              __FUNCTION__, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------
            const OTIdentifier theServerID(m_str_server_id), theNymID(m_str_nym_id);
            
            // Open the Nym's payments inbox.
            OTLedger * pInbox = OTAPI_Wrap::OTAPI()->LoadPaymentInbox(theServerID, theNymID);
            OTCleanup<OTLedger> theInboxAngel(pInbox);
            // ------------------------------------------
            if (NULL == pInbox)
            {
                OTLog::vError("%s: Error: Unable to load payment inbox for server id (%s), nym id (%s)\n",
                              __FUNCTION__, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------------------
            // Find the payment therein that correlates to this MTRecord.
            //
            int nIndex = pInbox->GetTransactionIndex(m_lTransactionNum);
            
            if ((-1) == nIndex)
            {
                OTLog::vError("%s: Error: Unable to find transaction %ld in payment inbox for server id (%s), nym id (%s)\n",
                              __FUNCTION__, m_lTransactionNum, m_str_server_id.c_str(), m_str_nym_id.c_str());
                return false;
            }
            // ------------------------------------------
            // Accept it.
            //
            OTString strIndices;
            strIndices.Format("%d", nIndex);
            const std::string str_indices(strIndices.Get());
            
            OT_ME madeEasy;
            int32_t nReturn = madeEasy.accept_from_paymentbox(str_into_acct, str_indices, "ANY");
            
            switch (nReturn)
            {
                case 0:
                    OTLog::vOutput(0, "%s: This instrument was expired, so it was moved to the record box.\n", __FUNCTION__);
                    return true;
                    
                case 1: // success
                    break;
                    // ----------------------------------
                default:
                    OTLog::vError("%s: Error while trying to accept this instrument.\n", __FUNCTION__);
                    return false;
            } // switch
        } // case: instrument
            break;
            // --------------------------------------------
        default:
            OTLog::vError("%s: Unexpected type: %s\n",
                          __FUNCTION__, this->GetInstrumentType().c_str());
            return false;
    }
    
    return true;
}
Esempio n. 9
0
// ---------------------------------------
bool MTRecord::FormatDescription(std::string & str_output)
{
    OTString strDescription, strStatus, strKind;
    
    if (IsRecord())
    {
        if (IsExpired())
            strStatus = "(EXPIRED)"; // How to tell difference between instrument that processed successfully and THEN expired, versus one that expired before processing successfully? (See next comment.)
        else if (IsInvoice())
            strStatus = "(payment sent)";  // TODO: need an "invalid records" box for expired and canceled. Otherwise we may falsely assume "payment sent" when actually it expired. (We may also falsely assume payment expired when actually it was sent.) Solution is a new box.
        else
            strStatus = "";
        //          strStatus = "(record)";
    }
    // -----------------------------
    else if (IsPending())
    {
        if (IsExpired())
            strStatus = "(EXPIRED)";
        else if (IsInvoice())
            strStatus = "(unpaid)";
        else if (!IsCash())
            strStatus = "(pending)";
    }
    // -----------------------------
    if (IsCanceled())
    {
        strStatus = "(CANCELED)";
        
        if (IsOutgoing() || IsReceipt())
            strKind.Format("%s", "sent ");
    }
    // -----------------------------
    else
    {
        if (IsOutgoing())
            strKind.Format("%s",
                           ((IsPending() && !IsCash()) ? "outgoing " : "sent "));
        else // incoming.
            strKind.Format("%s",
                           IsPending() ? "incoming " : (IsReceipt() ? "" : "received "));
    }
    // -----------------------------
    OTString strTransNumForDisplay;
    
    if (!IsCash())
        strTransNumForDisplay.Format(" #%ld", GetTransNumForDisplay());
    // -----------------------------
    if (IsRecord())
    {
        if (this->IsTransfer())
            strDescription.Format("%s%s%s %s", strKind.Get(), "transfer", strTransNumForDisplay.Get(), strStatus.Get());
        else if (this->IsVoucher())
            strDescription.Format("%s%s%s %s", strKind.Get(), "payment", strTransNumForDisplay.Get(), strStatus.Get());
        else if (this->IsReceipt())
        {
            std::string str_instrument_type;
            
            if (0 == GetInstrumentType().compare("transferReceipt"))
                str_instrument_type = "transfer";
            else if (0 == GetInstrumentType().compare("finalReceipt"))
                str_instrument_type = "final receipt (closed)";
            else if (0 == GetInstrumentType().compare("chequeReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);
                
                // I paid OUT when this chequeReceipt came through. It must be a normal cheque that I wrote.
                if (lAmount <= 0) // Notice less than OR EQUAL TO 0 -- that's because a canceled cheque has a 0 value.
                    str_instrument_type = "cheque";
                else // I GOT PAID when this chequeReceipt came through. It must be an invoice I wrote, that someone paid.
                {
                    if (IsCanceled())
                        str_instrument_type = "invoice";
                    else
                        str_instrument_type = "invoice (payment received)";
                }
            }
            else if (0 == GetInstrumentType().compare("voucherReceipt"))
            {
                str_instrument_type = "payment";
            }
            else if (0 == GetInstrumentType().compare("paymentReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);
                
                if (!IsCanceled() && (lAmount > 0))
                    strKind.Set("received ");
                
                str_instrument_type = "recurring payment";
            }
            
            strDescription.Format("%s%s%s %s", strKind.Get(), str_instrument_type.c_str(), strTransNumForDisplay.Get(), strStatus.Get());
        }
        else
            strDescription.Format("%s%s%s %s", strKind.Get(), GetInstrumentType().c_str(), strTransNumForDisplay.Get(), strStatus.Get());
    }
    else
    {
        if (this->IsTransfer())
            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), "transfer", strTransNumForDisplay.Get());
        else if (this->IsVoucher())
            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), "payment", strTransNumForDisplay.Get());
        
        else if (this->IsReceipt())
        {
            std::string str_instrument_type;
            
            if (0 == GetInstrumentType().compare("transferReceipt"))
            {
                if (IsCanceled())
                    str_instrument_type = "transfer";
                else
                    str_instrument_type = "transfer (receipt)";
            }
            else if (0 == GetInstrumentType().compare("finalReceipt"))
                str_instrument_type = "final receipt";
            else if (0 == GetInstrumentType().compare("chequeReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);
                
                // I paid OUT when this chequeReceipt came through. It must be a normal cheque that I wrote.
                if (lAmount <= 0) // Notice less than OR EQUAL TO 0 -- that's because a canceled cheque has a 0 value.
                {
                    if (IsCanceled())
                        str_instrument_type = "cheque";
                    else
                        str_instrument_type = "cheque (receipt)";
                }
                else // I GOT PAID when this chequeReceipt came through. It must be an invoice I wrote, that someone paid.
                {
                    if (IsCanceled())
                        str_instrument_type = "invoice";
                    else
                        str_instrument_type = "sent invoice (receipt: payment received)";
                }
            }
            else if (0 == GetInstrumentType().compare("voucherReceipt"))
            {
                if (IsCanceled())
                    str_instrument_type = "payment";
                else
                    str_instrument_type = "payment (receipt)";
            }
            else if (0 == GetInstrumentType().compare("paymentReceipt"))
            {
                const long lAmount = OTAPI_Wrap::It()->StringToLong(m_str_amount);
                
                if (!IsCanceled() && (lAmount > 0))
                    strKind.Set("received ");
                
                str_instrument_type = "recurring payment (receipt)";
            }
            
            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), str_instrument_type.c_str(), strTransNumForDisplay.Get());
        }
        else
            strDescription.Format("%s %s%s%s", strStatus.Get(), strKind.Get(), GetInstrumentType().c_str(), strTransNumForDisplay.Get());
    }
    // -----------------------------
    str_output = strDescription.Get();
    // -----------------------------
    return (!str_output.empty());
}
Esempio n. 10
0
// Used for making sure that certain necessary folders actually exist. (Creates them otherwise.)
//
// If you pass in "spent", then this function will make sure that "<path>/spent" actually exists, 
// or create it. WARNING: If what you want to pass is "spent/sub-folder-to-spent" then make SURE
// you call it with "spent" FIRST, so you are sure THAT folder has been created, otherwise the
// folder creation will definitely fail on the sub-folder call (if the primary folder wasn't
// already there, that is.)
//
bool OTLog::ConfirmOrCreateFolder(const char * szFolderName)
{
	OT_ASSERT_MSG(NULL != szFolderName, "OTLog::ConfirmOrCreateFolder: Assert failed: NULL != szFolderName");
	
    OTString strFolderName(szFolderName);
    
	// DIRECTORY IS PRESENT?
	struct stat st;
	
	OTString strRawPath;
    
    if (strFolderName.Compare("."))
        strRawPath.Format("%s", OTLog::Path());
    else
        strRawPath.Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), strFolderName.Get());
	
//	OTLog::vError("**** Path: %s  Foldername: %s    Total: %s \n",
//				  OTLog::Path(), szFolderName, strRawPath.Get());
	/*ACTUAL OUTPUT:
	 ****	Path: /Users/au/Library/Application  
			Foldername: nyms
			Total: "/Users/au/Library/Application/nyms" 

	 */
	
    
	OTString strPath;
    OTLog::TransformFilePath(strRawPath.Get(), strPath);
	
    OTLog::vOutput(1, "OTLog::ConfirmOrCreateFolder: Transformed %s into %s \n",
                   strRawPath.Get(), strPath.Get());
    
	bool bDirIsPresent = (0 == stat(strPath.Get(), &st));
	
	// ----------------------------------------------------------------------------
	
	// IF NO, CREATE IT
	if (!bDirIsPresent)
	{
#ifdef _WIN32
		if (_mkdir(strPath.Get()) == -1) 
#else
			if (mkdir(strPath.Get(), 0700) == -1) 
#endif
			{
				OTLog::vError("OTLog::ConfirmOrCreateFolder: Unable to create %s.\n",
							  strPath.Get());
				return false;
			}
		
		// Now we have created it, so let's check again...
		bDirIsPresent = (0 == stat(strPath.Get(), &st));
		
		if (bDirIsPresent)
			OTLog::vOutput(0, "Created folder: %s\n", strPath.Get());
	}
	
	// ----------------------------------------------------------------------------
	
	// At this point if the folder still doesn't exist, nothing we can do. We
	// already tried to create the folder, and SUCCEEDED, and then STILL failed 
	// to find it (if this is still false.)
	if (!bDirIsPresent)
	{
		OTLog::vError("OTLog::ConfirmOrCreateFolder: Unable to find newly-created folder: %s\n", 
					  strPath.Get());
		return false;
	}
	
	return true;
}