Skip to content

Commit f28ab5c

Browse files
committed
Extract cmdline handling from main.cpp
1 parent cbaa8eb commit f28ab5c

File tree

4 files changed

+275
-245
lines changed

4 files changed

+275
-245
lines changed

lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ XcaProgress.h XcaWarningCore.cpp XcaWarningCore.h
3838
PwDialogCore.cpp PwDialogCore.h digest.h
3939
digest.cpp pki_export.cpp debug_info.h
4040
func_base.cpp func_base.h debug_info.cpp
41+
cmdline.cpp
4142
)
4243

4344
macro(ExpandSources target)

lib/cmdline.cpp

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
/* vi: set sw=4 ts=4:
2+
*
3+
* Copyright (C) 2023 Christian Hohnstaedt.
4+
*
5+
* All rights reserved.
6+
*/
7+
8+
#include <QString>
9+
#include <QFile>
10+
#include <stdio.h>
11+
12+
#include "func.h"
13+
#include "database_model.h"
14+
#include "debug_info.h"
15+
#include "pki_multi.h"
16+
#include "pki_evp.h"
17+
#include "pki_base.h"
18+
#include "pki_x509.h"
19+
#include "pki_crl.h"
20+
#include "arguments.h"
21+
#include "pki_export.h"
22+
#include "PwDialogCore.h"
23+
#include "BioByteArray.h"
24+
#include "db_x509.h"
25+
#include "db_crl.h"
26+
27+
static const char *xca_name = "xca";
28+
static void cmd_version(FILE *fp)
29+
{
30+
console_write(fp, QString(XCA_TITLE "\nVersion %1\n")
31+
.arg(version_str(false)).toUtf8());
32+
}
33+
34+
static int cmd_help(int exitcode = EXIT_SUCCESS, const char *msg = NULL)
35+
{
36+
FILE *fp = exitcode == EXIT_SUCCESS ? stdout : stderr;
37+
QString s;
38+
39+
cmd_version(fp);
40+
s = QString("\nUsage %1 <options> <file-to-import> ...\n\n%2\n")
41+
.arg(xca_name).arg(arguments::help());
42+
if (msg)
43+
s += QString("\nError: %1\n").arg(msg);
44+
45+
console_write(fp, s.toUtf8());
46+
return exitcode;
47+
}
48+
49+
static Passwd acquire_password(QString source)
50+
{
51+
Passwd pass;
52+
pass.append(source.toUtf8());
53+
54+
if (source == "stdin")
55+
source = "fd:0";
56+
if (source.startsWith("pass:")) {
57+
pass = source.mid(5).toLatin1();
58+
} else if (source.startsWith("file:")) {
59+
XFile f(source.mid(5));
60+
f.open_read();
61+
pass = f.readLine(128).trimmed();
62+
} else if (source.startsWith("env:")) {
63+
pass = getenv(source.mid(4).toLocal8Bit());
64+
} else if (source.startsWith("fd:")) {
65+
int fd = source.mid(3).toInt();
66+
QFile f;
67+
f.open(fd, QIODevice::ReadOnly);
68+
pass = f.readLine(128).trimmed();
69+
}
70+
return pass;
71+
}
72+
73+
static bool compare_pki_base(pki_base* a, pki_base* b)
74+
{
75+
return (a->getSqlItemId().toULongLong() <
76+
b->getSqlItemId().toULongLong());
77+
}
78+
79+
int read_cmdline(int argc, char *argv[], bool console_only,
80+
pki_multi **_cmdline_items)
81+
{
82+
pki_multi *cmdline_items;
83+
84+
if (argc > 0)
85+
xca_name = argv[0];
86+
arguments cmd_opts(argc, argv);
87+
PwDialogCore::cmdline_passwd = acquire_password(cmd_opts["password"]);
88+
Passwd sqlpw = acquire_password(cmd_opts["sqlpass"]);
89+
90+
if (cmd_opts.has("verbose")) {
91+
QString all = cmd_opts["verbose"];
92+
debug_info::set_debug(all.isEmpty() ? QString("all") : all);
93+
}
94+
if (console_only)
95+
database_model::open_without_password = true;
96+
97+
if (cmd_opts.has("database"))
98+
Database.open(cmd_opts["database"], sqlpw);
99+
100+
*_cmdline_items = cmdline_items = new pki_multi();
101+
102+
foreach(QString file, cmd_opts.getFiles()) {
103+
qDebug() << "Probe" << file;
104+
cmdline_items->probeAnything(file);
105+
}
106+
QStringList names = cmd_opts["import-names"].split(";");
107+
foreach(pki_base *pki, cmdline_items->get()) {
108+
if (names.isEmpty())
109+
break;
110+
QString name = names.takeFirst();
111+
if (!name.isEmpty())
112+
pki->setIntName(name);
113+
}
114+
if (cmdline_items->failed_files.size() > 0) {
115+
XCA_WARN(QString("Failed to import from '%1'")
116+
.arg(cmdline_items->failed_files.join("' '")));
117+
}
118+
if (cmd_opts.needDb() && !Database.isOpen()) {
119+
/* We need a database for the following operations
120+
* but there is none, yet. Try the default database */
121+
try {
122+
Database.open(QString());
123+
} catch (errorEx &err) {
124+
return cmd_help(EXIT_FAILURE, CCHAR(err.getString()));
125+
} catch (enum open_result opt) {
126+
static const char * const msg[] = {
127+
/* pw_cancel */ "Password input aborted",
128+
/* pw_ok */ "Password accepted??",
129+
/* pw_exit */ "Exit selected",
130+
/* open_abort*/ "No database given",
131+
};
132+
return cmd_help(EXIT_FAILURE, msg[opt]);
133+
}
134+
}
135+
database_model::open_without_password = false;
136+
137+
if (cmd_opts.has("list-curves")) {
138+
QStringList list;
139+
foreach(const builtin_curve &c, builtinCurves) {
140+
list << QString(COL_YELL "%1" COL_RESET "%2")
141+
.arg(OBJ_nid2sn(c.nid), -26)
142+
.arg(c.comment);
143+
}
144+
console_write(stdout, list.join("\n").toUtf8() + '\n');
145+
}
146+
if (cmd_opts.has("list-items")) {
147+
QStringList list;
148+
QList<pki_base*> items = Store.getAll<pki_base>();
149+
std::sort(items.begin(), items.end(), compare_pki_base);
150+
foreach(pki_base *pki, items) {
151+
list << QString(COL_YELL "%1 " COL_GREEN "%2 "
152+
COL_RESET "%3")
153+
.arg(pki->getSqlItemId().toString(), 7)
154+
.arg(pki->getTypeString(), -27)
155+
.arg(pki->getIntName());
156+
}
157+
console_write(stdout, list.join("\n").toUtf8() + '\n');
158+
}
159+
if (!cmd_opts["index"].isEmpty()) {
160+
qDebug() << cmd_opts["index"];
161+
db_x509 *certs = Database.model<db_x509>();
162+
certs->writeIndex(cmd_opts["index"], false);
163+
XCA_INFO(QObject::tr("Index file written to '%1'")
164+
.arg(cmd_opts["index"]));
165+
}
166+
if (!cmd_opts["hierarchy"].isEmpty()) {
167+
qDebug() << cmd_opts["hierarchy"];
168+
db_x509 *certs = Database.model<db_x509>();
169+
certs->writeIndex(cmd_opts["hierarchy"], true);
170+
XCA_INFO(QObject::tr("Index hierarchy written to '%1'")
171+
.arg(cmd_opts["hierarchy"]));
172+
}
173+
if (cmd_opts.has("help"))
174+
cmd_help();
175+
176+
if (cmd_opts.has("version"))
177+
cmd_version(stdout);
178+
179+
if (cmd_opts.has("keygen")) {
180+
keyjob task(cmd_opts["keygen"]);
181+
if (!task.isValid()) {
182+
Database.close();
183+
throw errorEx(QObject::tr("Unknown key type %1")
184+
.arg(cmd_opts["keygen"]));
185+
}
186+
db_key *keys = Database.model<db_key>();
187+
pki_key *pki = keys->newKey(task, cmd_opts["name"]);
188+
if (pki)
189+
cmdline_items->append_item(pki);
190+
}
191+
if (cmd_opts.has("issuers")) {
192+
QStringList out;
193+
db_x509 *certs = Database.model<db_x509>();
194+
QList<pki_x509*>issuers = certs->getAllIssuers();
195+
std::sort(issuers.begin(), issuers.end(), compare_pki_base);
196+
foreach(pki_x509 *iss, issuers) {
197+
pki_key *key = iss->getRefKey();
198+
QString keytype = key ? key->getTypeString() : "";
199+
out << QString(COL_YELL "%1 " COL_GREEN "%2 "
200+
COL_RESET "%3")
201+
.arg(iss->getSqlItemId().toULongLong(), 7)
202+
.arg(keytype, -13)
203+
.arg(iss->getIntName());
204+
}
205+
console_write(stdout, out.join("\n").toUtf8() + '\n');
206+
}
207+
if (cmd_opts.has("crlgen")) {
208+
db_crl *crls = Database.model<db_crl>();
209+
db_x509 *certs = Database.model<db_x509>();
210+
QList<pki_x509*>issuers = certs->getAllIssuers();
211+
pki_x509 *issuer = NULL;
212+
QString ca = cmd_opts["crlgen"];
213+
foreach(pki_x509 *iss, issuers) {
214+
if (iss->getIntName() == ca ||
215+
iss->getSqlItemId().toString() == ca)
216+
{
217+
issuer = iss;
218+
break;
219+
}
220+
}
221+
if (!issuer) {
222+
XCA_ERROR(QString("Issuer '%1' not found")
223+
.arg(cmd_opts["crlgen"]));
224+
} else {
225+
crljob task(issuer);
226+
pki_crl *crl = crls->newCrl(task, cmd_opts["name"]);
227+
if (crl)
228+
cmdline_items->append_item(crl);
229+
}
230+
}
231+
if (!cmd_opts["select"].isEmpty()) {
232+
foreach(QString item, cmd_opts["select"].split(",")) {
233+
bool ok;
234+
qDebug() << "Select" << item;
235+
qulonglong id = item.toULongLong(&ok);
236+
pki_base *pki = Store.lookupPki<pki_base>(QVariant(id));
237+
if (pki)
238+
cmdline_items->append_item(pki);
239+
}
240+
}
241+
242+
BioByteArray bba;
243+
foreach(pki_base *pki, cmdline_items->get()) {
244+
QString filename = pki->getFilename();
245+
if ((cmd_opts.has("text") || cmd_opts.has("print")) &&
246+
filename.size() > 0)
247+
{
248+
bba += QString("\n" COL_GREEN COL_UNDER "File: %1"
249+
COL_RESET "\n").arg(filename).toUtf8();
250+
}
251+
if (cmd_opts.has("print"))
252+
pki->print(bba, pki_base::print_coloured);
253+
if (cmd_opts.has("text"))
254+
pki->print(bba, pki_base::print_openssl_txt);
255+
if (cmd_opts.has("pem"))
256+
pki->print(bba, pki_base::print_pem);
257+
}
258+
if (bba.size() > 0)
259+
console_write(stdout, bba);
260+
if (cmd_opts.has("import")) {
261+
Database.insert(cmdline_items);
262+
cmdline_items = NULL;
263+
}
264+
return EXIT_SUCCESS;
265+
}
266+

lib/debug_info.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77

88
#include <QStringList>
99
#include <QDebug>
10+
#include <QElapsedTimer>
1011
#include <stdlib.h>
1112

1213
#include "debug_info.h"
14+
#include "base.h"
15+
#include "func.h"
1316

1417
QList<dbg_pattern> debug_info::patternlist;
1518
bool debug_info::all = false;

0 commit comments

Comments
 (0)