Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
opentxs.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * opentxs.cpp
4  *
5  */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "opentxs/core/stdafx.hpp"
134 
135 #include "opentxs.hpp"
136 
137 #include "opentxs/client/OTAPI.hpp"
143 
146 #include "opentxs/core/OTLog.hpp"
150 #include "opentxs/core/Version.hpp"
151 
152 #include <anyoption/anyoption.hpp>
153 
154 #include <algorithm>
155 #include <cctype>
156 #include <functional>
157 
158 using namespace opentxs;
159 using namespace std;
160 
161 const char* categoryName[] = {
162  "Category Error", "Advanced utilities", "The user wallet",
163  "Misc", "Markets (bid/ask)", "Asset accounts",
164  "Dealing with other users", "Financial instruments", "Basket currencies",
165  "Pseudonyms"};
166 
169  "accept all incoming transfers, receipts, payments, invoices."},
171  "accept all incoming transfers and receipts in MyAcct's inbox."},
173  "pay all invoices in MyNym's payments inbox."},
175  "accept all incoming transfers and payments into MyAcct."},
177  "accept all incoming payments in MyNym's payments inbox."},
179  "accept all receipts in MyAcct's inbox."},
181  "accept all incoming transfers in MyAcct's inbox."},
183  "paste an existing asset contract, import into your wallet."},
185  "paste an existing server contract, import into your wallet."},
187  "add a signature to a contract without releasing others."},
189  "cancel an uncashed outgoing instrument from outpayment box."},
191  "change the master passphrase for the wallet."},
193  "download a nym's public key based on his ID."},
195  "clear all expired records."},
197  "clear all archived records and receipts."},
199  "confirm your agreement to a smart contract or payment plan."},
201  "OT-base64-decode out of armor."},
203  "decrypt ciphertext using nym's private key."},
205  "delete an in-mail item."},
207  "delete an out-mail item."},
209  "deposit cash, cheque, voucher, or invoice."},
211  "discard an uncashed incoming instrument from payments inbox."},
213  "edit an asset account label, as it appears in your wallet."},
215  "edit a currency contract label, as it appears in your wallet."},
217  "edit the nym label, as it appears in your wallet."},
219  "edit a server contract label, as it appears in your wallet."},
221  "OT-base64-encode into armor."},
223  "encrypt plaintext to a nym's public key."},
225  "exchange in/out of a basket currency."},
227  "export a cash purse."},
229  "export an OT Nym as a single importable file."},
231  "download an asset or server contract by its ID."},
233  "download the list of markets."},
235  "download mynym's list of market offers."},
237  "download the list of market offers."},
239  "downloads a box receipt based on transaction ID."},
241  "import a cash purse."},
243  "import an OT Nym that was previously exported."},
245  "show inbox of a particular account."},
247  "show in-mail for a particular nym."},
249  "show contents of incoming payments box."},
251  "issue a currency contract onto an OT server."},
253  "kill an active recurring market offer."},
255  "kill an active recurring payment plan."},
257  "create a new asset account."},
259  "create a new asset contract."},
261  "create a new basket currency."},
263  "create a new credential for a specific nym."},
265  "create a new symmetric key."},
266  {"newnym", OT_Command::mainNewNym, Opentxs::catNyms, "create a new nym."},
268  "create a new market offer."},
270  "create a new server contract."},
272  "show outbox of a particular account."},
274  "show out-mail for a particular nym."},
276  "show contents of outgoing payments box."},
278  "password-decrypt a ciphertext using a symmetric key."},
280  "password-encrypt a plaintext using a symmetric key."},
282  "dividend payout, sent to all shareholders (in voucher form.)"},
284  "pay an invoice."},
286  "as merchant, propose a payment plan to a customer."},
288  "performs both refreshnym and refreshaccount."},
290  "download latest intermediary files for myacct."},
292  "download latest intermediary files for mynym."},
294  "register a nym onto an OT server."},
296  "revoke one of a nym's credentials."},
298  "send cash from mypurse to recipient, withdraw if necessary."},
300  "write a cheque and then send it to the recipient."},
302  "write an invoice and then send it to the recipient."},
304  "send a message to another nym's in-mail."},
306  "withdraw a voucher and then send it to the recipient."},
308  "show account stats for a single account."},
310  "show the asset accounts in the wallet."},
312  "show the active cron item IDs, or the details of one by ID."},
314  "show the currency contracts in the wallet."},
316  "show balance for a specific account."},
318  "show basket currencies available in the wallet."},
320  "show a specific credential in detail."},
322  "show the credentials for a specific nym."},
324  "show contents of expired record box."},
326  "show the list of markets."},
328  "show mint file for specific asset ID. Download if necessary."},
330  "show mynym's offers on a particular server and market."},
332  "show the statistics for a specific nym."},
334  "show the nyms in the wallet."},
336  "show all offers on a particular server and market."},
338  "show the details of an incoming payment in the payments inbox."},
340  "show contents of cash purse."},
342  "show contents of record box."},
344  "show the server contracts in the wallet."},
346  "show wallet contents."},
348  "sign a contract, releasing all other signatures first."},
350  "send a transfer from myacct to hisacct."},
352  "trigger a clause on a running smart contract."},
354  "verify your intermediary files against last signed receipt."},
356  "verify a signature on a contract."},
358  "withdraw cash. (From acct on server into local purse.)"},
359  {"withdrawvoucher", OT_Command::mainWithdrawVoucher,
361  "withdraw from myacct as a voucher (cashier's cheque.)"},
363  "write a cheque and print it out to the screen."},
365  "write an invoice and print it out to the screen."},
366  {nullptr, nullptr, Opentxs::catError, nullptr}};
367 
369 {
371 }
372 
374 {
376 }
377 
378 string& Opentxs::ltrim(string& s)
379 {
380  s.erase(s.begin(),
381  find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace))));
382  return s;
383 }
384 
385 string& Opentxs::rtrim(string& s)
386 {
387  s.erase(
388  find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(),
389  s.end());
390  return s;
391 }
392 
393 string& Opentxs::trim(string& s)
394 {
395  return ltrim(rtrim(s));
396 }
397 
398 void Opentxs::handleCommandLineArguments(int argc, char* argv[], AnyOption& opt)
399 {
400  OTString configPath(OTPaths::AppDataFolder());
401  bool configPathFound = configPath.Exists() && 3 < configPath.GetLength();
402  OT_ASSERT_MSG(configPathFound,
403  "RegisterAPIWithScript: Must set Config Path first!\n");
404  otWarn << "Using configuration path: " << configPath << "\n";
405 
406  opt.addUsage("");
407  opt.addUsage(" Opentxs CLI Usage: ");
408  opt.addUsage("");
409 
410  opt.setCommandFlag("echocommand");
411  opt.setCommandFlag("echoexpand");
412  opt.setCommandFlag("errorlist");
413  opt.setCommandFlag("noprompt");
414  opt.setCommandFlag("test");
415 
416  opt.setCommandOption("args");
417  opt.setCommandOption("myacct");
418  opt.setCommandOption("mynym");
419  opt.setCommandOption("mypurse");
420  opt.setCommandOption("hisacct");
421  opt.setCommandOption("hisnym");
422  opt.setCommandOption("hispurse");
423  opt.setCommandOption("server");
424 
425  // for options that will be checked only from the CLI option file
426  opt.setFileOption("defaultserver");
427  opt.setFileOption("defaultmyacct");
428  opt.setFileOption("defaultmynym");
429  opt.setFileOption("defaultmypurse");
430  opt.setFileOption("defaulthisacct");
431  opt.setFileOption("defaulthisnym");
432  opt.setFileOption("defaulthispurse");
433 
434  OTString optionsFile("command-line-ot.opt"), iniFileExact;
435  bool buildFullPathSuccess =
436  OTPaths::RelativeToCanonical(iniFileExact, configPath, optionsFile);
437  OT_ASSERT_MSG(buildFullPathSuccess, "Unable to set Full Path");
438 
439  opt.processFile(iniFileExact.Get());
440  opt.processCommandArgs(argc, argv);
441 }
442 
443 const char* Opentxs::getOption(AnyOption& opt, const char* optionName,
444  const char* defaultName)
445 {
446  // can we get the default value from the command line?
447  const char* value = opt.getValue(optionName);
448  if (value != nullptr) {
449  otWarn << "Option " << optionName << ": " << value << "\n";
450  return value;
451  }
452 
453  // can we get the default value from the options file?
454  if (nullptr != defaultName) {
455  value = opt.getValue(defaultName);
456  if (value != nullptr) {
457  otWarn << "Default " << optionName << ": " << value << "\n";
458  return value;
459  }
460  }
461 
462  // clear option value
463  return "";
464 }
465 
466 OTVariable* Opentxs::setGlobalVar(OT_ME& madeEasy, const string& name,
467  const string& value)
468 {
469  if (value.size() == 0) {
470  otInfo << "Variable " << name << " isn't set\n";
471  return nullptr;
472  }
473 
474  otWarn << "Variable " << name << " has value: " << value << "\n";
475 
476  OTVariable* var = new OTVariable(name, value, OTVariable::Var_Constant);
477  OT_ASSERT(var != nullptr);
478  madeEasy.AddVariable(name, *var);
479  return var;
480 }
481 
482 int Opentxs::processCommand(OT_ME& madeEasy, AnyOption& opt)
483 {
484  // process command line values such as account ID, Nym ID, etc.
485  // Also available as defaults in a config file in the ~/.ot folder
486  argArgs = getOption(opt, "args", "defaultargs");
487  argHisAcct = getOption(opt, "hisacct", "defaulthisacct");
488  argHisNym = getOption(opt, "hisnym", "defaulthisnym");
489  argHisPurse = getOption(opt, "hispurse", "defaulthispurse");
490  argMyAcct = getOption(opt, "myacct", "defaultmyacct");
491  argMyNym = getOption(opt, "mynym", "defaultmynym");
492  argMyPurse = getOption(opt, "mypurse", "defaultmypurse");
493  argServer = getOption(opt, "server", "defaultserver");
494 
495  OTWallet* wallet = OTAPI_Wrap::OTAPI()->GetWallet();
496 
498  wallet != nullptr,
499  "The wallet object is still nullptr, somehow. Please load it.\n");
500 
501  OTServerContract* serverContract = nullptr;
502  if (argServer.size() > 0) {
503  serverContract = wallet->GetServerContract(argServer);
504  if (serverContract == nullptr) {
505  serverContract = wallet->GetServerContractPartialMatch(argServer);
506  if (serverContract == nullptr) {
507  otOut << "Unknown default server contract for --server "
508  << argServer << "\n";
509  }
510  }
511  if (serverContract != nullptr) {
512  OTString tmp;
513  serverContract->GetIdentifier(tmp);
514  argServer = tmp.Get();
515  otOut << "Using as server: " << argServer << "\n";
516  }
517  }
518 
519  OTPseudonym* myNym = nullptr;
520  if (argMyNym.size() > 0) {
521  myNym = wallet->GetNymByID(argMyNym);
522  if (myNym == nullptr) {
523  myNym = wallet->GetNymByIDPartialMatch(argMyNym);
524  if (myNym == nullptr) {
525  otOut << "Unknown default nym for --mynym " << argMyNym << "\n";
526  }
527  }
528  if (myNym != nullptr) {
529  OTString tmp;
530  myNym->GetIdentifier(tmp);
531  argMyNym = tmp.Get();
532  otOut << "Using as mynym: " << argMyNym << "\n";
533  }
534  }
535 
536  OTAccount* myAccount = nullptr;
537  if (argMyAcct.size() > 0) {
538  myAccount = wallet->GetAccount(argMyAcct);
539  if (myAccount == nullptr) {
540  myAccount = wallet->GetAccountPartialMatch(argMyAcct);
541  if (myAccount == nullptr) {
542  otOut << "Unknown default account for --myacct " << argMyAcct
543  << "\n";
544  }
545  }
546  if (myAccount != nullptr) {
547  OTString tmp;
548  myAccount->GetPurportedAccountID().GetString(tmp);
549  argMyAcct = tmp.Get();
550  otOut << "Using as myacct: " << argMyAcct << "\n";
551  }
552  }
553 
554  OTPseudonym* hisNym = nullptr;
555  if (argHisNym.size() > 0) {
556  hisNym = wallet->GetNymByID(argHisNym);
557  if (hisNym == nullptr) {
558  hisNym = wallet->GetNymByIDPartialMatch(argHisNym);
559  if (hisNym == nullptr) {
560  otOut << "Unknown default nym for --hisnym " << argHisNym
561  << "\n";
562  }
563  }
564  if (hisNym != nullptr) {
565  OTString tmp;
566  hisNym->GetIdentifier(tmp);
567  argHisNym = tmp.Get();
568  otOut << "Using as hisnym: " << argHisNym << "\n";
569  }
570  }
571 
572  OTAccount* hisAccount = nullptr;
573  if (argHisAcct.size() > 0) {
574  hisAccount = wallet->GetAccount(argHisAcct);
575  if (hisAccount == nullptr) {
576  hisAccount = wallet->GetAccountPartialMatch(argHisAcct);
577  if (hisAccount == nullptr) {
578  otOut << "Unknown default account for --hisacct " << argHisAcct
579  << "\n";
580  }
581  }
582  if (hisAccount != nullptr) {
583  OTString tmp;
584  hisAccount->GetPurportedAccountID().GetString(tmp);
585  argHisAcct = tmp.Get();
586  otOut << "Using as hisacct: " << argHisAcct << "\n";
587  }
588  }
589 
590  OTIdentifier purseAssetTypeID;
591  OTAssetContract* myAssetContract = nullptr;
592  if (argMyPurse.size() > 0) {
593  myAssetContract = wallet->GetAssetContract(argMyPurse);
594  if (myAssetContract == nullptr) {
595  myAssetContract = wallet->GetAssetContractPartialMatch(argMyPurse);
596  if (myAssetContract == nullptr) {
597  otOut << "Unknown default purse for --mypurse " << argMyPurse
598  << "\n";
599  }
600  }
601  if (myAssetContract != nullptr) {
602  myAssetContract->GetIdentifier(purseAssetTypeID);
603  OTString tmp;
604  myAssetContract->GetIdentifier(tmp);
605  argMyPurse = tmp.Get();
606  otOut << "Using as mypurse: " << argMyPurse << "\n";
607  }
608  }
609 
610  OTIdentifier hisPurseAssetTypeID;
611  OTAssetContract* hisAssetContract = nullptr;
612  if (argHisPurse.size() > 0) {
613  hisAssetContract = wallet->GetAssetContract(argHisPurse);
614  if (hisAssetContract == nullptr) {
615  hisAssetContract =
616  wallet->GetAssetContractPartialMatch(argHisPurse);
617  if (hisAssetContract == nullptr) {
618  otOut << "Unknown default purse for --hispurse " << argHisPurse
619  << "\n";
620  }
621  }
622  if (hisAssetContract != nullptr) {
623  hisAssetContract->GetIdentifier(hisPurseAssetTypeID);
624  OTString tmp;
625  hisAssetContract->GetIdentifier(tmp);
626  argHisPurse = tmp.Get();
627  otOut << "Using as hispurse: " << argHisPurse << "\n";
628  }
629  }
630 
631  if (serverContract != nullptr && myNym != nullptr) {
633  *serverContract, *myNym,
634  OTAPI_Wrap::OTAPI()->GetTransportCallback());
635  }
636 
637  string command = "list";
638  if (opt.getArgc() == 1) {
639  command = opt.getArgv(0);
640  }
641  else {
642  otOut << "Expecting a single opentxs command:\n\n";
643  }
644 
645  typedef unique_ptr<OTVariable> GlobalVar;
646  GlobalVar varArgs(setGlobalVar(madeEasy, "Args", argArgs));
647  GlobalVar varHisAcct(setGlobalVar(madeEasy, "HisAcct", argHisAcct));
648  GlobalVar varHisNym(setGlobalVar(madeEasy, "HisNym", argHisNym));
649  GlobalVar varHisPurse(setGlobalVar(madeEasy, "HisPurse", argHisPurse));
650  GlobalVar varMyAcct(setGlobalVar(madeEasy, "MyAcct", argMyAcct));
651  GlobalVar varMyNym(setGlobalVar(madeEasy, "MyNym", argMyNym));
652  GlobalVar varMyPurse(setGlobalVar(madeEasy, "MyPurse", argMyPurse));
653  GlobalVar varServer(setGlobalVar(madeEasy, "Server", argServer));
654 
656 
657  otWarn << "Script output:\n\n";
658 
659  int result = opentxsCommand(command);
660  return opt.getArgc() == 1 ? result : -2;
661 }
662 
663 int Opentxs::opentxsCommand(const string& command)
664 {
665  if ("exit" == command || "quit" == command) {
666  return -2;
667  }
668 
669  if ("version" == command) {
670  otOut << "opentxs " << OPENTXS_VERSION_STRING << "\n";
671  otOut << "Copyright (C) 2014 Open Transactions Developers\n";
672  return 0;
673  }
674 
675  if ("list" == command) {
676  otOut << "\nCommands:\n\n";
677  for (int32_t i = 0; commands[i].command != nullptr; i++) {
678  CommandEntry& cmd = commands[i];
679  otOut << (cmd.command + spaces18).substr(0, 18);
680  if (i % 4 == 3) {
681  otOut << "\n";
682  }
683  }
684  otOut << "\n";
685  return 0;
686  }
687 
688  if ("help" == command) {
689  // create category groups
690  string categoryGroup[catLast];
691  for (int i = 1; i < catLast; i++) {
692  categoryGroup[i] = string("\n ") + categoryName[i] + ":\n";
693  }
694 
695  // add commands to their category group
696  otOut << "\nCommands:\n";
697  for (int32_t i = 0; commands[i].command != nullptr; i++) {
698  CommandEntry& cmd = commands[i];
699  categoryGroup[cmd.category] +=
700  (cmd.command + spaces18).substr(0, 18) + cmd.helpText + "\n";
701  }
702 
703  // print all category groups
704  for (int i = 1; i < catLast; i++) {
705  otOut << categoryGroup[i];
706  }
707 
708  return 0;
709  }
710 
711  // all other commands.
712  for (int32_t i = 0; commands[i].command != nullptr; i++) {
713  CommandEntry& cmd = commands[i];
714  if (cmd.command == command) {
715  int32_t returnValue = (*cmd.function)();
716  switch (returnValue) {
717  case 0: // no action performed, return success
718  return 0;
719  case 1: // success
720  return 0;
721  case -1: // failed
722  return -1;
723  default: // should not happen
724  otOut << "\nUndefined error code: \"" << returnValue
725  << "\".\n\n";
726  return -1;
727  }
728  break;
729  }
730  }
731 
732  otOut << "\nUndefined command: \"" << command << "\" -- Try 'list'.\n\n";
733  return -1;
734 }
735 
736 int Opentxs::run(int argc, char* argv[])
737 {
738  if (OTAPI_Wrap::OTAPI() == nullptr) return -1;
739 
741 
742  map<string, string> macros;
743  vector<int> errorLineNumbers;
744  vector<string> errorCommands;
745 
746  OT_ME madeEasy;
747 
748  AnyOption opt;
749  handleCommandLineArguments(argc, argv, opt);
750 
751  if (opt.getArgc() != 0) {
752  return processCommand(madeEasy, opt);
753  }
754 
755  int lineNumber = 0;
756  bool echoCommand = opt.getFlag("echocommand") || opt.getFlag("test");
757  bool echoExpand = opt.getFlag("echoexpand") || opt.getFlag("test");
758  bool noPrompt = opt.getFlag("noprompt") || opt.getFlag("test");
759  int processed = 0;
760  while (true) {
761  // get next command line from input stream
762  if (!noPrompt) {
763  cout << "\nopentxs> ";
764  }
765  string cmd;
766  getline(cin, cmd);
767 
768  // end of file stops processing commands
769  if (cin.eof()) {
770  break;
771  }
772 
773  lineNumber++;
774 
775  // quit/exit the command loop?
776  cmd = trim(cmd);
777  if (echoCommand) {
778  cout << cmd << endl;
779  }
780 
781  if (cmd == "quit" || cmd == "exit") {
782  break;
783  }
784 
785  // empty lines and lines starting with a hash character are seen as
786  // comments
787  if (cmd.size() == 0 || cmd[0] == '#') {
788  continue;
789  }
790 
791  string originalCmd = cmd;
792 
793  // lines starting with a dollar sign character denote the definition of
794  // a macro of the form: $macroName = macroValue
795  // whitespace around the equal sign is optional
796  // <macroName> can be any combination of A-Z, a-z, 0-9, or _
797  // <macroValue> is anything after the equal sign and whitespace-trimmed
798  // note that <macroValue> can be an empty string
799  // note that the dollar sign itself is part of the immediately following
800  // macro name
801  // note that a macro value stays valid for the entire lifetime of the
802  // command loop
803  // note that macro expansion is done on the command line before
804  // processing the line this means that a macro is allowed to contain
805  // command line escape characters
806  // note that macro expansion is recursive until no expansions are found
807  // any more this means that a macro is allowed to contain other macros
808  if (cmd[0] == '$') {
809  // determine the macro name
810  size_t nameLength = 1;
811  while (nameLength < cmd.length() &&
812  (isalnum(cmd[nameLength]) || cmd[nameLength] == '_')) {
813  nameLength++;
814  }
815  string macroName = cmd.substr(0, nameLength);
816 
817  // skip whitespace
818  size_t i = nameLength;
819  while (i < cmd.length() && isspace(cmd[i])) {
820  i++;
821  }
822 
823  if (i == cmd.length() || cmd[i] != '=') {
824  otOut << "\n\n***ERROR***\n"
825  "Expected macro definition of the form: "
826  "$macroName = macroValue\n"
827  "Command was: " << cmd;
828  continue;
829  }
830 
831  // remainder of line after trimming whitespace is macro value
832  string macroValue = cmd.substr(i + 1);
833  macros[macroName] = trim(macroValue);
834  continue;
835  }
836 
837  // now replace any macro in the command line with its value
838  // unknown macro names will cause an error message instead of command
839  // execution
840  // note that all macro names are 'maximum munch'
841  int expansions = 0;
842  for (size_t macro = cmd.find_first_of("$"); macro != string::npos;
843  macro = cmd.find_first_of("$", macro + 1)) {
844  // first see if this is an escaped literal
845  if (macro > 0 && cmd[macro - 1] == '\\') {
846  continue;
847  }
848 
849  // gather rest of macro name 'maximum munch'
850  size_t macroEnd = macro + 1;
851  while (macroEnd < cmd.length() &&
852  (isalnum(cmd[macroEnd]) || cmd[macroEnd] == '_')) {
853  macroEnd++;
854  }
855 
856  // has this macro been defined?
857  string macroName = cmd.substr(macro, macroEnd - macro);
858  auto found = macros.find(macroName);
859  if (found == macros.end()) {
860  otOut << "\n\n***ERROR***\n"
861  "Macro expansion failed.\n"
862  "Unknown macro: " << macroName
863  << "\n"
864  "Command was: " << cmd;
865  expansions = 100;
866  break;
867  }
868 
869  string& macroValue = found->second;
870 
871  // limit to 100 expansions to avoid endless recusion loop
872  expansions++;
873  if (expansions > 100) {
874  otOut << "\n\n***ERROR***\n"
875  "Macro expansion failed.\n"
876  "Too many expansions at macro: " << macroName
877  << "\n"
878  "Command was: " << cmd;
879  break;
880  }
881 
882  // limit to 10000 characters to avoid crazy recursive expansions
883  if (cmd.length() + macroValue.length() > 10000) {
884  otOut << "\n\n***ERROR***\n"
885  "Macro expansion failed.\n"
886  "Command length exceeded at macro: " << macroName
887  << "\n"
888  "Macro value is: " << macroValue
889  << "\n"
890  "Command was: " << cmd;
891  expansions = 100;
892  break;
893  }
894 
895  // expand the command line
896  cmd = cmd.substr(0, macro) + macroValue + cmd.substr(macroEnd);
897  }
898 
899  if (echoExpand && cmd != originalCmd) {
900  otOut << cmd << endl;
901  }
902 
903  // skip command when anything during macro expansion failed
904  if (expansions > 99) {
905  continue;
906  }
907 
908  // '!' indicates that we expect this command to fail
909  // which is very useful for running a test script
910  bool expectFailure = cmd[0] == '!';
911 
912  // Parse command string into its separate parts so it can be passed as
913  // an argc/argv combo
914  // Whitespace separates args as usual.
915  // To include whitespace in an arg surround the entire arg with double
916  // quotes
917  // An unterminated double-quoted arg will auto-terminate at end of line
918  // All characters are taken literal except for: double quote, dollar
919  // sign, and backslash
920  // To take any character literal, precede it with a backslash
921  vector<string> arguments;
922 
923  // add original command name
924  arguments.push_back(argv[0]);
925 
926  // set up buffer that will receive the separate arguments
927  char* buf = new char[cmd.length() + 1];
928  char* arg = buf;
929 
930  // start at actual command
931  size_t i = expectFailure ? 1 : 0;
932  while (i < cmd.length()) {
933  // skip any whitespace
934  while (i < cmd.length() && isspace(cmd[i])) {
935  i++;
936  }
937  if (i == cmd.length()) {
938  // it was trailing whitespace; we're done
939  break;
940  }
941 
942  // remember where we start this new argument in the buffer
943  char* start = arg;
944 
945  // unquoted argument?
946  if (cmd[i] != '"') {
947  // take everything until end of line or next whitespace
948  while (i < cmd.length() && !isspace(cmd[i])) {
949  // unescaped literal character?
950  if (cmd[i] != '\\') {
951  // yep, add to buffer and go for next
952  *arg++ = cmd[i++];
953  continue;
954  }
955 
956  // take next character literal unless it was the end of line
957  // in which case we simply add the backslash as a literal
958  // character
959  *arg++ = i < cmd.length() ? cmd[i++] : '\\';
960  }
961 
962  // end of argument reached, terminate an add to arguments array
963  *arg++ = '\0';
964  arguments.push_back(start);
965 
966  // look for next argument
967  continue;
968  }
969 
970  // double quoted argument, skip the quote
971  i++;
972 
973  // take everything until end of line or next double quote
974  while (i < cmd.length() && cmd[i] != '"') {
975  // unescaped literal character?
976  if (cmd[i] != '\\') {
977  // yep, add to buffer and go for next
978  *arg++ = cmd[i++];
979  continue;
980  }
981 
982  // take next character literal unless it was the end of line
983  // in which case we simply add the backslash as a literal
984  // character
985  *arg++ = i < cmd.length() ? cmd[i++] : '\\';
986  }
987 
988  // end of argument reached, terminate an add to arguments array
989  *arg++ = '\0';
990  arguments.push_back(start);
991 
992  // skip terminating double quote or end of line
993  i++;
994  }
995 
996  // set up a new argc/argv combo
997  int newArgc = arguments.size();
998  char** newArgv = new char* [newArgc];
999  for (int i = 0; i < newArgc; i++) {
1000  newArgv[i] = const_cast<char*>(arguments[i].c_str());
1001  }
1002 
1003  // preprocess the command line
1004  AnyOption opt;
1005  handleCommandLineArguments(newArgc, newArgv, opt);
1006 
1007  cout << "\n";
1008  if (expectFailure != (0 != processCommand(madeEasy, opt))) {
1009  errorLineNumbers.push_back(lineNumber);
1010  errorCommands.push_back(originalCmd);
1011  otOut << "\n\n***ERROR***\n"
1012  << (expectFailure ? "Expected command to fail.\nSucceeding"
1013  : "Failed") << " command was: " << cmd;
1014  }
1015 
1016  delete[] newArgv;
1017  delete[] buf;
1018 
1019  otOut << "\n\n";
1020  processed++;
1021  }
1022 
1023  int failed = errorLineNumbers.size();
1024  cout << "\n\n" << processed << " commands were processed.\n" << failed
1025  << " commands failed.\n" << endl;
1026 
1027  if (opt.getFlag("errorList") || opt.getFlag("test")) {
1028  for (size_t i = 0; i < errorLineNumbers.size(); i++) {
1029  cout << "\nFailed line " << errorLineNumbers[i] << ": "
1030  << errorCommands[i] << endl;
1031  }
1032  }
1033 
1034  return failed == 0 ? 0 : -1;
1035 }
EXPORT static OT_COMMANDS_OT int32_t mainEditAccount()
EXPORT static OT_COMMANDS_OT int32_t mainOutbox()
const char * command
Definition: opentxs.hpp:168
EXPORT bool SetFocusToServerAndNym(OTServerContract &theServerContract, OTPseudonym &theNym, TransportCallback *pCallback) const
Definition: OTClient.cpp:13747
EXPORT static OT_COMMANDS_OT int32_t mainKillOffer()
EXPORT static OT_COMMANDS_OT int32_t mainImportNym()
EXPORT static OT_COMMANDS_OT int32_t mainNewKey()
static EXPORT bool AppCleanup()
Definition: OTAPI.cpp:189
EXPORT static OT_COMMANDS_OT int32_t mainVerifyReceipt()
EXPORT static OT_COMMANDS_OT int32_t mainShowMarkets()
EXPORT static OT_COMMANDS_OT int32_t mainInbox()
EXPORT static OT_COMMANDS_OT int32_t mainPayDividend()
EXPORT static OT_COMMANDS_OT int32_t mainPayInvoice()
EXPORT static OT_COMMANDS_OT int32_t mainNewCredential()
OTClient * GetClient() const
EXPORT static OT_COMMANDS_OT int32_t mainShowAccounts()
EXPORT static OT_COMMANDS_OT int32_t mainKillPlan()
EXPORT static OT_COMMANDS_OT int32_t mainImportCash()
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
EXPORT OTAccount * GetAccountPartialMatch(std::string PARTIAL_ID)
Definition: OTWallet.cpp:613
EXPORT static OT_COMMANDS_OT int32_t mainWithdrawVoucher()
EXPORT static OT_COMMANDS_OT int32_t mainVerifySignature()
EXPORT static OT_COMMANDS_OT int32_t mainShowNyms()
EXPORT static OT_OTAPI_OT void CopyVariables()
EXPORT static OT_COMMANDS_OT int32_t mainSendCheque()
EXPORT static OT_COMMANDS_OT int32_t mainWithdrawCash()
EXPORT static OT_COMMANDS_OT int32_t mainDeleteInmail()
EXPORT static OT_COMMANDS_OT int32_t mainExchangeBasket()
EXPORT static OT_COMMANDS_OT int32_t mainWriteCheque()
EXPORT OTAssetContract * GetAssetContract(const OTIdentifier &theContractID)
Definition: OTWallet.cpp:1203
EXPORT static OT_COMMANDS_OT int32_t mainEncrypt()
EXPORT static OT_COMMANDS_OT int32_t mainShowAccount()
EXPORT static OT_COMMANDS_OT int32_t mainSignContract()
EXPORT static OT_COMMANDS_OT int32_t mainDecode()
EXPORT OTWallet * GetWallet(const char *szFuncName=nullptr) const
EXPORT static OT_COMMANDS_OT int32_t mainAddSignature()
EXPORT static OT_COMMANDS_OT int32_t mainRefresh()
EXPORT OTPseudonym * GetNymByIDPartialMatch(std::string PARTIAL_ID)
Definition: OTWallet.cpp:291
OTLOG_IMPORT OTLogStream otOut
EXPORT static OT_COMMANDS_OT int32_t mainGetContract()
EXPORT static OT_COMMANDS_OT int32_t mainClearExpired()
EXPORT bool GetAccount(int32_t iIndex, OTIdentifier &THE_ID, OTString &THE_NAME)
Definition: OTWallet.cpp:431
EXPORT static OT_COMMANDS_OT int32_t mainSendCash()
EXPORT static OT_COMMANDS_OT int32_t mainAddAsset()
EXPORT static OT_COMMANDS_OT int32_t mainShowBasket()
EXPORT static OT_COMMANDS_OT int32_t mainSendMessage()
EXPORT static OT_COMMANDS_OT int32_t mainShowMyOffers()
EXPORT static OT_COMMANDS_OT int32_t mainChangePw()
static EXPORT bool RelativeToCanonical(OTString &out_strCanonicalPath, const OTString &strBasePath, const OTString &strRelativePath)
Definition: OTPaths.cpp:1280
EXPORT static OT_COMMANDS_OT int32_t mainConfirm()
EXPORT static OT_COMMANDS_OT int32_t mainDiscard()
EXPORT static OT_COMMANDS_OT int32_t mainNewServer()
int run(int argc, char *argv[])
Definition: opentxs.cpp:736
static EXPORT const OTString & AppDataFolder()
Definition: OTPaths.cpp:254
EXPORT static OT_COMMANDS_OT int32_t mainShowExpired()
EXPORT static OT_COMMANDS_OT int32_t mainAcceptTransfers()
EXPORT static OT_COMMANDS_OT int32_t mainAcceptPayments()
EXPORT static OT_COMMANDS_OT int32_t mainShowWallet()
EXPORT static OT_COMMANDS_OT int32_t mainRefreshAccount()
EXPORT bool LoadWallet() const
EXPORT static OT_COMMANDS_OT int32_t mainNewOffer()
EXPORT static OT_COMMANDS_OT int32_t mainDeposit()
EXPORT static OT_COMMANDS_OT int32_t mainOutpayment()
EXPORT static OT_COMMANDS_OT int32_t mainIssueAsset()
EXPORT static OT_COMMANDS_OT int32_t mainRefreshNym()
EXPORT static OT_COMMANDS_OT int32_t mainGetOffers()
EXPORT static OT_COMMANDS_OT int32_t mainExportCash()
EXPORT static OT_COMMANDS_OT int32_t mainShowMint()
EXPORT OTPseudonym * GetNymByID(const OTIdentifier &NYM_ID)
Definition: OTWallet.cpp:275
EXPORT static OT_COMMANDS_OT int32_t mainAddServer()
EXPORT static OT_COMMANDS_OT int32_t mainAcceptMoney()
EXPORT static OT_COMMANDS_OT int32_t mainAcceptAll()
#define OPENTXS_VERSION_STRING
Definition: Version.hpp:14
EXPORT static OT_COMMANDS_OT int32_t mainShowNym()
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT static OT_COMMANDS_OT int32_t mainGetReceipt()
EXPORT OTAssetContract * GetAssetContractPartialMatch(std::string PARTIAL_ID)
Definition: OTWallet.cpp:1218
EXPORT static OT_COMMANDS_OT int32_t mainEditServer()
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
EXPORT static OT_COMMANDS_OT int32_t mainEditAsset()
EXPORT static OT_COMMANDS_OT int32_t mainShowAssets()
static EXPORT bool AppInit()
Definition: OTAPI.cpp:179
OTLOG_IMPORT OTLogStream otInfo
EXPORT static OT_COMMANDS_OT int32_t mainCancel()
EXPORT static OT_COMMANDS_OT int32_t mainDecrypt()
const char * categoryName[]
Definition: opentxs.cpp:161
EXPORT static OT_COMMANDS_OT int32_t mainAcceptReceipts()
virtual EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
Definition: OTContract.cpp:317
EXPORT static OT_COMMANDS_OT int32_t mainShowCredentials()
EXPORT static OT_COMMANDS_OT int32_t mainRegisterNym()
EXPORT static OT_COMMANDS_OT int32_t mainNewAccount()
EXPORT static OT_COMMANDS_OT int32_t mainRevokeCredential()
EXPORT static OT_COMMANDS_OT int32_t mainTriggerClause()
EXPORT static OT_COMMANDS_OT int32_t mainExportNym()
Definition: opentxs.hpp:166
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
EXPORT static OT_COMMANDS_OT int32_t mainNewNym()
const OTIdentifier & GetPurportedAccountID() const
Opentxs::CommandEntry commands[]
Definition: opentxs.cpp:167
EXPORT static OT_COMMANDS_OT int32_t mainShowOffers()
EXPORT static OT_COMMANDS_OT int32_t mainShowPurse()
EXPORT static OT_COMMANDS_OT int32_t mainShowBalance()
EXPORT static OT_COMMANDS_OT int32_t mainDeleteOutmail()
EXPORT void AddVariable(const std::string &str_var_name, OTVariable &theVar)
Definition: OT_ME.cpp:1131
EXPORT static OT_COMMANDS_OT int32_t mainEditNym()
EXPORT static OT_COMMANDS_OT int32_t mainPasswordDecrypt()
EXPORT void GetString(OTString &theStr) const
EXPORT static OT_COMMANDS_OT int32_t mainAcceptInvoices()
EXPORT static OT_COMMANDS_OT int32_t mainSendInvoice()
EXPORT static OT_COMMANDS_OT int32_t mainGetMarkets()
EXPORT static OT_COMMANDS_OT int32_t mainSendVoucher()
virtual ~Opentxs()
Definition: opentxs.cpp:373
EXPORT static OT_COMMANDS_OT int32_t mainShowActive()
EXPORT static OT_COMMANDS_OT int32_t mainCheckNym()
EXPORT OTServerContract * GetServerContractPartialMatch(std::string PARTIAL_ID)
Definition: OTWallet.cpp:685
static EXPORT OT_API * OTAPI()
Definition: OTAPI.cpp:244
EXPORT static OT_COMMANDS_OT int32_t mainShowCredential()
EXPORT static OT_COMMANDS_OT int32_t mainClearRecords()
EXPORT OTServerContract * GetServerContract(const OTIdentifier &SERVER_ID)
Definition: OTWallet.cpp:667
EXPORT static OT_COMMANDS_OT int32_t mainInpayments()
EXPORT static OT_COMMANDS_OT int32_t mainShowServers()
EXPORT static OT_COMMANDS_OT int32_t mainProposePlan()
EXPORT static OT_COMMANDS_OT int32_t mainShowRecords()
EXPORT static OT_COMMANDS_OT int32_t mainNewBasket()
EXPORT static OT_COMMANDS_OT int32_t mainInmail()
EXPORT static OT_COMMANDS_OT int32_t mainOutmail()
EXPORT static OT_COMMANDS_OT int32_t mainGetMyOffers()
EXPORT static OT_COMMANDS_OT int32_t mainWriteInvoice()
EXPORT static OT_COMMANDS_OT int32_t mainShowPayment()
EXPORT static OT_COMMANDS_OT int32_t mainNewAsset()
EXPORT static OT_COMMANDS_OT int32_t mainAcceptInbox()
EXPORT static OT_COMMANDS_OT int32_t mainTransfer()
EXPORT static OT_COMMANDS_OT int32_t mainPasswordEncrypt()
const char * helpText
Definition: opentxs.hpp:171
EXPORT static OT_COMMANDS_OT int32_t mainEncode()