General clean (#174)

* more tagWidgetCleanup
* Try not, Do
* remove qStringtoByteArray
* rm stdStringtoQByteArray use QByteArray::fromStdString()
* Clean up Credits More
* Hotkeys use QList
* Simplify Constants
* misc
* Use value() calls

Co-authored-by: Chris Rizzitello <crizzitello@ics.com>
main
crizzitello 2022-05-06 14:23:57 -04:00 committed by GitHub
parent 16afdb7d3b
commit 3b0823547a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 172 additions and 325 deletions

View File

@ -55,19 +55,14 @@ class AppConfig {
/// readConfig attempts to read the provided path and parse the configuration file.
/// If successful, the config file is loaded. If the config file is missing, then a
/// default file will be generated. If some other error occurs, a FileError is thrown.
void readConfig(QString location=Constants::configLocation()) {
void readConfig(QString location = Constants::configLocation) {
QFile configFile(location);
if (!configFile.open(QIODevice::ReadOnly)) {
if (configFile.exists()) {
throw FileError::mkError("Error reading config file", location.toStdString(),
configFile.error());
}
try {
writeDefaultConfig();
}
catch (...) {
// ignoring -- just trying to generate an empty config
}
writeDefaultConfig();
return;
}
@ -89,19 +84,14 @@ class AppConfig {
/// writeDefaultConfig attempts to write a basic configuration to disk.
/// This is useful on first runs/when no config data is set.
void writeDefaultConfig() {
evidenceRepo = Constants::defaultEvidenceRepo();
evidenceRepo = Constants::defaultEvidenceRepo;
#ifdef Q_OS_MACOS
screenshotExec = "screencapture -s %file";
captureWindowExec = "screencapture -w %file";
screenshotExec = QStringLiteral("screencapture -s %file");
captureWindowExec = QStringLiteral("screencapture -w %file");
#endif
try {
writeConfig();
}
catch (...) {
// ignoring error -- best effort approach
}
writeConfig();
}
public:
@ -118,7 +108,7 @@ class AppConfig {
QPair<QString, QString*>(QStringLiteral("captureWindowExec"), &captureWindowExec),
QPair<QString, QString*>(QStringLiteral("captureWindowShortcut"), &captureWindowShortcut),
QPair<QString, QString*>(QStringLiteral("captureCodeblockShortcut"), &captureCodeblockShortcut),
};
};
for (auto fieldPair : fields) {
QJsonValue val = src.value(fieldPair.first);
@ -145,8 +135,8 @@ class AppConfig {
/// writeConfig serializes the running config, and writes the assoicated file to the given path.
/// The path defaults to Constants::configLocation()
void writeConfig(QString alternateSavePath="") {
QString writeLoc = alternateSavePath == "" ? Constants::configLocation() : alternateSavePath;
void writeConfig(QString alternateSavePath = QString()) {
QString writeLoc = alternateSavePath.isEmpty() ? Constants::configLocation : alternateSavePath;
auto configContent = QJsonDocument(serializeConfig()).toJson();

View File

@ -71,7 +71,7 @@ CodeEditor::CodeEditor(QWidget *parent)
// customize for text/code editing
setLineWrapMode(LineWrapMode::NoWrap);
setTabChangesFocus(false);
QFont font(Constants::codeFont());
QFont font(Constants::codeFont);
font.setStyleHint(QFont::TypeWriter);
setFont(font);
@ -83,7 +83,7 @@ void CodeEditor::keyReleaseEvent(QKeyEvent *e) { QPlainTextEdit::keyReleaseEvent
int CodeEditor::lineNumberAreaWidth() {
int digits = 1;
int max = qMax(1, blockCount());
int max = std::max(1, blockCount());
while (max >= 10) {
max /= 10;
++digits;

View File

@ -48,7 +48,7 @@ void TagView::removeWidget(TagWidget* tagWidget) {
// remove from includedTags
auto itr = std::find(includedTags.begin(), includedTags.end(), tagWidget);
if(itr != includedTags.cend()) {
if(itr != includedTags.end()) {
auto last = includedTags.end()-1;
std::iter_swap(itr, last);
includedTags.pop_back();

View File

@ -46,26 +46,19 @@ void TagWidget::buildTag() {
int labelWidth = labelSize.width();
int innerTagHeight = std::max(labelSize.height(), removeSize.height()); //tag height without the buffer
int labelTopOffset = ((innerTagHeight - labelSize.height())/2) + smBuffer;
int removeLeftOffset = lgBuffer + labelWidth;
int removeTopOffset = ((innerTagHeight - removeSize.height())/2) + smBuffer;
int tagHeightBuffer = 12; // space around the top/bottom (real size is half as much)
int tagWidthBuffer = 12; // space around the outer left/right edges (real size is half as much)
int innerBuffer = 6; // space between each segment
int labelLeftOffset = tagWidthBuffer/2;
int labelTopOffset = ((innerTagHeight - labelSize.height())/2) + (tagHeightBuffer/2);
int removeLeftOffset = labelLeftOffset + labelWidth + innerBuffer;
int removeTopOffset = ((innerTagHeight - removeSize.height())/2) + (tagHeightBuffer/2);
int fullTagWidth = labelWidth + tagWidthBuffer;
int fullTagHeight = innerTagHeight + tagHeightBuffer;
int fullTagWidth = labelWidth + lgBuffer;
int fullTagHeight = innerTagHeight + lgBuffer;
// set bounds for mouse release event
labelArea = QRectF(0, 0, removeLeftOffset, fullTagHeight);
removeArea = QRectF(-1, -1, 0, 0); // set to dummy value in case we don't have a remove area
if (!readonly) {
fullTagWidth += removeSize.width() + innerBuffer;
fullTagWidth += removeSize.width() + smBuffer;
removeArea = QRectF(removeLeftOffset, 0, fullTagWidth - removeLeftOffset, fullTagHeight);
}
@ -92,7 +85,7 @@ void TagWidget::buildTag() {
painter.setPen(fontColor);
// draw label
painter.drawText(QRectF(QPointF(labelLeftOffset, labelTopOffset), labelSize), Qt::AlignCenter, tag.name);
painter.drawText(QRectF(QPointF(smBuffer, labelTopOffset), labelSize), Qt::AlignCenter, tag.name);
// draw remove (if needed)
if(!readonly) {

View File

@ -76,4 +76,6 @@ class TagWidget : public QLabel {
{QStringLiteral("lightViolet"), QColor(0xC274C2)},
};
inline static QStringList allColorNames = colorMap.keys();
inline static int smBuffer = 6;
inline static int lgBuffer = 12;
};

View File

@ -44,7 +44,7 @@ class DatabaseConnection {
* interaction is localized and infrequent.
* @param dbPath The path to the database file
* @param dbName The name of the database connection (can be anything, but should be unique.
* Specifically, it should NOT be the value from Constants::databaseName())
* Specifically, it should NOT be the value from Constants::databaseName)
* @param actions A function that will execute after a connection is established. This is where
* all db interactions should occur.
*/

View File

@ -19,7 +19,7 @@ class CheckConnection {
cc.parsedCorrectly = false;
if (err.error == QJsonParseError::NoError) {
QJsonValue val = doc["ok"];
QJsonValue val = doc.object().value(QStringLiteral("ok"));
if (!val.isUndefined()) {
cc.parsedCorrectly = true;
cc.ok = val.toBool();

View File

@ -104,22 +104,21 @@ class GithubRelease {
private:
static GithubRelease fromJson(QJsonObject obj) {
GithubRelease release;
release.url = obj["url"].toString();
release.htmlURL = obj["html_url"].toString();
release.assetsURL = obj["assets_url"].toString();
release.uploadURL = obj["upload_url"].toString();
release.tarballURL = obj["tarball_url"].toString();
release.zipballURL = obj["zipball_url"].toString();
release.tagName = obj["tag_name"].toString();
release.body = obj["body"].toString();
release.releaseName = obj["name"].toString();
release.publishedAt = obj["published_at"].toString();
release.draft = obj["draft"].toBool();
release.prerelease = obj["prerelease"].toBool();
release.url = obj.value(QStringLiteral("url")).toString();
release.htmlURL = obj.value(QStringLiteral("html_url")).toString();
release.assetsURL = obj.value(QStringLiteral("assets_url")).toString();
release.uploadURL = obj.value(QStringLiteral("upload_url")).toString();
release.tarballURL = obj.value(QStringLiteral("tarball_url")).toString();
release.zipballURL = obj.value(QStringLiteral("zipball_url")).toString();
release.tagName = obj.value(QStringLiteral("tag_name")).toString();
release.body = obj.value(QStringLiteral("body")).toString();
release.releaseName = obj.value(QStringLiteral("name")).toString();
release.publishedAt = obj.value(QStringLiteral("published_at")).toString();
release.draft = obj.value(QStringLiteral("draft")).toBool();
release.prerelease = obj.value(QStringLiteral("prerelease")).toBool();
// missing a number of fields here that maybe aren't relevant
release.id = obj["id"].toVariant().toLongLong();
release.id = obj.value(QStringLiteral("id")).toVariant().toLongLong();
return release;
}

View File

@ -51,11 +51,10 @@ class Operation {
// provides a Operation from a given QJsonObject
static Operation fromJson(QJsonObject obj) {
Operation o;
o.slug = obj["slug"].toString();
o.name = obj["name"].toString();
o.numUsers = obj["numUsers"].toInt();
o.status = static_cast<OperationStatus>(obj["status"].toInt());
o.slug = obj.value(QStringLiteral("slug")).toString();
o.name = obj.value(QStringLiteral("name")).toString();
o.numUsers = obj.value(QStringLiteral("numUsers")).toInt();
o.status = static_cast<OperationStatus>(obj.value(QStringLiteral("status")).toInt());
return o;
}
};

View File

@ -16,10 +16,9 @@ class Tag {
~Tag() = default;
Tag(const Tag &) = default;
Tag(QString name, QString colorName) {
this->name = name;
this->colorName = colorName;
}
Tag(QString name, QString colorName)
: name(name)
, colorName(colorName) { }
public:
static Tag parseData(QByteArray data) { return parseJSONItem<Tag>(data, Tag::fromJson); }
@ -46,10 +45,9 @@ class Tag {
// provides a Tag from a given QJsonObject
static Tag fromJson(QJsonObject obj) {
Tag t;
t.id = obj["id"].toVariant().toLongLong();
t.colorName = obj["colorName"].toString();
t.name = obj["name"].toString();
t.id = obj.value(QStringLiteral("id")).toVariant().toLongLong();
t.colorName = obj.value(QStringLiteral("colorName")).toString();
t.name = obj.value(QStringLiteral("name")).toString();
return t;
}

View File

@ -5,127 +5,21 @@
#include <QDateTime>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QTextBrowser>
#include "helpers/constants.h"
#include "helpers/netman.h"
struct Attribution {
std::string library;
std::string libraryUrl;
std::string authors;
std::string license;
std::string licenseUrl;
Attribution() = default;
Attribution(std::string library, std::string libraryUrl, std::string authors, std::string license,
std::string licenseUrl) {
this->library = library;
this->libraryUrl = libraryUrl;
this->authors = authors;
this->license = license;
this->licenseUrl = licenseUrl;
}
};
static std::string hyperlinkMd(std::string label, std::string url) {
return "[" + label + "](" + url + ")";
}
static std::string attributionMarkdown() {
QList<Attribution> attribs = {
Attribution("Qt", "http://qt.io", "The Qt Company", "LGPLv3",
"https://www.gnu.org/licenses/lgpl-3.0.html"),
Attribution("QProgressIndicator", "https://github.com/mojocorp/QProgressIndicator",
"Mojocorp, et al", "MIT License",
"https://github.com/mojocorp/QProgressIndicator/blob/master/LICENSE"),
Attribution("MultipartEncoder", "https://github.com/AndsonYe/MultipartEncoder", "Ye Yangang",
"MIT License",
"https://github.com/AndsonYe/MultipartEncoder/blob/master/LICENSE"),
Attribution("UGlobalHotkey", "https://github.com/joelatdeluxe/UGlobalHotkey",
"Anton Konstantinov, et al", "Public Domain", ""),
Attribution("AspectRatioPixmapLabel", "https://stackoverflow.com/a/22618496/4262552",
"phyatt, et al", "CC BY-SA 3.0",
"https://creativecommons.org/licenses/by-sa/3.0/"),
};
std::string msg =
"This application uses the following open source software:\n\n"
"| Project/Library | Authors | License |\n"
"| --------------- | ------- | ------- |\n";
for (const auto& attrib : attribs) {
std::string license;
std::string suffix;
if (!attrib.licenseUrl.empty()) {
license += "[";
suffix = "](" + attrib.licenseUrl + ")";
}
license += attrib.license + suffix;
// clang-format off
msg += "| " + hyperlinkMd(attrib.library, attrib.libraryUrl) +
" | " + attrib.authors +
" | " + license +
" |\n";
// clang-format on
}
return msg;
}
static std::string copyrightDate() {
int initialYear = 2020;
int currentYear = QDateTime::currentDateTime().date().year();
auto rtn = std::to_string(initialYear);
if (currentYear != initialYear) {
rtn += "-" + std::to_string(currentYear);
}
return rtn;
}
static std::string preambleMarkdown() {
const std::string lf = "\n\n"; // double linefeed to add in linebreaks in markdown
// clang-format off
return "Version: " + Constants::releaseTag().toStdString() +
lf + "Commit Hash: " + Constants::commitHash().toStdString() +
lf + "Copyright " + copyrightDate() + ", Verizon Media" +
lf + "Licensed under the terms of [MIT](https://github.com/theparanoids/ashirt/blob/master/LICENSE)" +
lf + "A short user guide can be found " + hyperlinkMd("here", Constants::userGuideUrl().toStdString()) +
lf + "Report issues " + hyperlinkMd("here", Constants::reportAnIssueUrl().toStdString()) +
lf;
// clang-format on
}
static std::string normalBodyMarkdown() {
// clang-format off
return "# ASHIRT\n\n"
+ preambleMarkdown()
+ "## Credits\n"
+ attributionMarkdown();
// clang-format on
}
Credits::Credits(QWidget* parent)
: AShirtDialog(parent, AShirtDialog::commonWindowFlags)
, updateLabel(new QLabel(this))
: AShirtDialog(parent, AShirtDialog::commonWindowFlags)
, updateLabel(new QLabel(this))
{
buildUi();
wireUi();
}
setWindowTitle("About");
connect(&NetMan::getInstance(), &NetMan::releasesChecked, this, &Credits::onReleasesUpdate);
void Credits::updateRelease() {
if (updateDigest.hasUpgrade()) {
updateLabel->setText(baseUpdateText.arg(Constants::releasePageUrl()));
}
else {
updateLabel->clear();
}
}
void Credits::buildUi() {
updateLabel->setVisible(false);
updateLabel->setOpenExternalLinks(true);
updateLabel->setTextFormat(Qt::RichText);
updateLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
@ -136,39 +30,30 @@ void Credits::buildUi() {
auto creditsArea = new QTextBrowser(this);
creditsArea->setOpenExternalLinks(true);
creditsArea->setReadOnly(true);
creditsArea->setMarkdown(normalBodyMarkdown().c_str());
creditsArea->setMarkdown(normalBodyMarkdown);
// Layout
/* 0
+------------------------------------+
0 | update label |
+------------------------------------+
| |
1 | Credits Area |
| |
+------------------------------------+
2 | Dialog button Box{close} |
+------------------------------------+
*/
auto gridLayout = new QGridLayout(this);
gridLayout->addWidget(updateLabel, 0, 0);
gridLayout->addWidget(creditsArea, 1, 0);
gridLayout->addWidget(buttonBox, 2, 0);
auto gridLayout = new QVBoxLayout(this);
gridLayout->addWidget(updateLabel);
gridLayout->addWidget(creditsArea);
gridLayout->addWidget(buttonBox);
setLayout(gridLayout);
resize(450, 500);
setWindowTitle("About");
setMinimumSize(425, 500);
}
void Credits::wireUi() {
connect(&NetMan::getInstance(), &NetMan::releasesChecked, this, &Credits::onReleasesUpdate);
void Credits::updateRelease() {
if (updateDigest.hasUpgrade()) {
updateLabel->setVisible(true);
updateLabel->setText(baseUpdateText.arg(Constants::releasePageUrl));
}
else {
updateLabel->setVisible(false);
updateLabel->clear();
}
}
void Credits::onReleasesUpdate(bool success, QList<dto::GithubRelease> releases) {
if (!success) {
return; //doesn't matter if this fails
}
if (!success)
return;
auto digest = dto::ReleaseDigest::fromReleases(Constants::releaseTag(), releases);
updateDigest = digest;

View File

@ -5,6 +5,7 @@
#include "ashirtdialog/ashirtdialog.h"
#include "dtos/github_release.h"
#include "helpers/constants.h"
class QLabel;
@ -19,10 +20,6 @@ class Credits : public AShirtDialog {
void onReleasesUpdate(bool success, QList<dto::GithubRelease> releases);
private:
/// buildUi creates the window structure.
void buildUi();
/// wireUi connects the components to each other.
void wireUi();
/// updateRelease waits for an update on a new version, if any. If called, and a new version does exist
/// this will update the updateLabel to have a link to the new release
void updateRelease();
@ -30,5 +27,46 @@ class Credits : public AShirtDialog {
private:
QLabel* updateLabel = nullptr;
dto::ReleaseDigest updateDigest;
inline static const auto attribBLOB_splitChar = QStringLiteral(">");
inline static const auto attrib_splitChar = QStringLiteral("~");
inline static const auto hyperlinkMd = QStringLiteral("[%1](%2)");
inline static const auto creditLine = QStringLiteral("| %1 | %2 | %3 |\n");
inline static const QString baseUpdateText = QStringLiteral("A new update is available! Click <a href=\"%1\">here</a> for more details.");
inline static const auto attribBLOB
= QStringLiteral(
"Qt~http://qt.io~The Qt Company~LGPLv3~https://www.gnu.org/licenses/lgpl-3.0.html"
">QProgressIndicator~https://github.com/mojocorp/QProgressIndicator~Mojocorp, et al~MIT License~https://github.com/mojocorp/QProgressIndicator/blob/master/LICENSE"
">MultipartEncoder~https://github.com/AndsonYe/MultipartEncoder~Ye Yangang~MIT License~https://github.com/AndsonYe/MultipartEncoder/blob/master/LICENSE"
">UGlobalHotkey~https://github.com/joelatdeluxe/UGlobalHotkey~Anton Konstantinov, et al~Public Domain~https://fairuse.stanford.edu/overview/public-domain/welcome"
">AspectRatioPixmapLabel~https://stackoverflow.com/a/22618496/4262552~phyatt, et al~CC BY-SA 3.0~https://creativecommons.org/licenses/by-sa/3.0/"
);
inline static const auto preambleMarkdown
= QStringLiteral("Version: %1 \n\n"
"Commit Hash: %2\n\n"
"Copyright %3, Verizon Media\n\n"
"Licensed under the terms of %4\n\n"
"A short user guide can be found %5\n\n"
"Report issues %6\n\n")
.arg(Constants::releaseTag()
, Constants::commitHash
, QStringLiteral("2020 - %1").arg(QDateTime::currentDateTime().date().year())
, hyperlinkMd.arg(QStringLiteral("MIT"), QStringLiteral("https://github.com/theparanoids/ashirt/blob/master/LICENSE"))
, hyperlinkMd.arg(QStringLiteral("here"), Constants::userGuideUrl)
, hyperlinkMd.arg(QStringLiteral("here"), Constants::reportAnIssueUrl));
static QString attributionMarkdown() {
const QStringList attribs = attribBLOB.split(attribBLOB_splitChar);
auto msg =
QStringLiteral("This application uses the following open source software:\n\n"
"| Project/Library | Authors | License |\n"
"| --------------- | ------- | ------- |\n");
for (const auto& attrib: attribs) {
const QStringList credit = attrib.split(attrib_splitChar);
auto library = hyperlinkMd.arg(credit.at(0), credit.at(1));
auto copyright = hyperlinkMd.arg(credit.at(3), credit.at(4));
msg.append(creditLine.arg(library, credit.at(2), copyright));
}
return msg;
}
inline static const auto normalBodyMarkdown = QStringLiteral("# ASHIRT\n\n %1 ## Credits\n %2").arg(preambleMarkdown, attributionMarkdown());
};

View File

@ -163,7 +163,7 @@ void PortingDialog::doExport(porting::SystemManifest* manifest, const QString& e
// Qt db access is limited to single-thread access. A new connection needs to be made, hence
// the withconnection here that connects to the same database. Note: we shouldn't write to the db
// in this thread, if possible.
QString threadedDbName = Constants::defaultDbName() + "_mt_forExport";
QString threadedDbName = QStringLiteral("%1_mt_forExport").arg(Constants::defaultDbName);
DatabaseConnection::withConnection(
db->getDatabasePath(), threadedDbName, [this, &manifest, exportPath, options](DatabaseConnection conn){
try {
@ -198,7 +198,7 @@ void PortingDialog::doImport(porting::SystemManifest* manifest) {
options.importDb = portEvidenceCheckBox->isChecked() ? options.Merge : options.None;
options.importConfig = portConfigCheckBox->isChecked();
QString threadedDbName = QStringLiteral("%1_mt_forImport").arg(Constants::defaultDbName());
QString threadedDbName = QStringLiteral("%1_mt_forImport").arg(Constants::defaultDbName);
DatabaseConnection::withConnection(
db->getDatabasePath(), threadedDbName, [this, &manifest, options](DatabaseConnection conn){
try {

View File

@ -162,8 +162,7 @@ void Settings::checkForDuplicateShortcuts(const QKeySequence& keySequence, QKeyS
bool alreadyUsed = usesKeySequence(captureWindowShortcutTextBox)
|| usesKeySequence(recordCodeblockShortcutTextBox)
|| usesKeySequence(captureAreaShortcutTextBox)
;
|| usesKeySequence(captureAreaShortcutTextBox);
if(alreadyUsed) {
parentComponent->clear();
@ -231,12 +230,9 @@ void Settings::onSaveClicked() {
inst.captureWindowShortcut = captureWindowShortcutTextBox->keySequence().toString();
inst.captureCodeblockShortcut = recordCodeblockShortcutTextBox->keySequence().toString();
try {
inst.writeConfig();
}
catch (std::exception &e) {
couldNotSaveSettingsMsg->showMessage(tr("Unable to save settings. Error: %1").arg(e.what()));
}
inst.writeConfig();
if(!inst.errorText.isEmpty())
couldNotSaveSettingsMsg->showMessage(tr("Unable to save settings. Error: %1").arg(inst.errorText));
hotkeyManager->updateHotkeys();
close();

View File

@ -1,35 +1,28 @@
#pragma once
#include <QRegularExpression>
#include <QStandardPaths>
#include <QString>
#include <iostream>
#include <QRegularExpression>
class Constants {
public:
static QString unknownRepoValue() {
return QStringLiteral("???");
}
static QString unknownOwnerValue() {
return QStringLiteral("???");
}
static QString configLocation() {
inline static const auto unknownValue = QStringLiteral("???");
inline static const auto dbLocation = QStringLiteral("%1/evidence.sqlite").arg(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
inline static const auto defaultEvidenceRepo = QStringLiteral("%1/evidence").arg(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
inline static const auto commitHash = QStringLiteral("%1").arg(COMMIT_HASH);
inline static const auto userGuideUrl = QStringLiteral("https://www.github.com/theparanoids/ashirt/blob/master/README.md");
inline static const auto reportAnIssueUrl = QStringLiteral("https://www.github.com/theparanoids/ashirt/issues");
inline static const auto releasePageUrl = QStringLiteral("https://github.com/theparanoids/ashirt/releases");
/// defaultDbName returns a string storing the "name" of the database for Qt identification
/// purposes. This _value_ should not be reused for other db connections.
inline static const auto defaultDbName = QStringLiteral("evidence");
#ifdef Q_OS_MACOS
return QStringLiteral("%1/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
inline static const auto configLocation = QStringLiteral("%1/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
inline static const auto codeFont = QStringLiteral("monaco");
#else
return QStringLiteral("%1/ashirt/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation));
inline static const auto configLocation = QStringLiteral("%1/ashirt/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation));
inline static const auto codeFont = QStringLiteral("source code pro");
#endif
}
static QString dbLocation() {
return QStringLiteral("%1/evidence.sqlite").arg(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
}
static QString defaultEvidenceRepo() {
return QStringLiteral("%1/evidence").arg(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
}
static QString releaseOwner() {
return parseRepo(RepoField::owner);
@ -39,49 +32,17 @@ class Constants {
return parseRepo(RepoField::repo);
}
static QString commitHash() {
return QStringLiteral("%1").arg(COMMIT_HASH);
}
static QString releaseTag() {
static QString parsedReleaseTag;
if (parsedReleaseTag.isEmpty()) {
QRegularExpression compiledTagRegex(QStringLiteral("(?:tags/)?v(.*)"));
auto rawVersion = QStringLiteral("%1").arg(VERSION_TAG);
QRegularExpressionMatch match = compiledTagRegex.match(rawVersion);
parsedReleaseTag = match.hasMatch() ? QStringLiteral("v") + match.captured(1) : QStringLiteral("v0.0.0-unversioned");
}
return parsedReleaseTag;
}
static QString userGuideUrl() {
return QStringLiteral("https://www.github.com/theparanoids/ashirt/blob/master/README.md");
}
static QString reportAnIssueUrl() {
return QStringLiteral("https://www.github.com/theparanoids/ashirt/issues");
}
static QString releasePageUrl() {
return QStringLiteral("https://github.com/theparanoids/ashirt/releases");
}
static QString codeFont() {
#ifdef Q_OS_MACX
return QStringLiteral("monaco");
#endif
return QStringLiteral("source code pro");
}
/// defaultDbName returns a string storing the "name" of the database for Qt identification
/// purposes. This _value_ should not be reused for other db connections.
static QString defaultDbName() {
return QStringLiteral("evidence");
}
private:
enum RepoField {
owner = 0,
@ -91,15 +52,14 @@ class Constants {
static QString parseRepo(RepoField field) {
static QString parsedRepo;
static QString parsedOwner;
if (parsedRepo.isEmpty()) {
auto rawRepo = QStringLiteral("%1").arg(SOURCE_CONTROL_REPO);
QRegularExpression ownerRegex(QStringLiteral("^([^/]+)/(.*)"));
QRegularExpressionMatch match = ownerRegex.match(rawRepo);
// Note that the specific values for the error cases below don't matter
// They are set to avoid rerunning the parsing (since these values won't change mid-run)
parsedOwner = match.hasMatch() ? match.captured(1) : unknownOwnerValue();
parsedRepo = match.hasMatch() ? match.captured(2) : unknownRepoValue();
parsedOwner = match.hasMatch() ? match.captured(1) : unknownValue;
parsedRepo = match.hasMatch() ? match.captured(2) : unknownValue;
}
return field == RepoField::owner ? parsedOwner : parsedRepo;
}

View File

@ -55,23 +55,10 @@ class FileHelpers {
return templateStr.replace(templateIndex, replaceToken.length(), replacement);
}
/// converts a c++ std string into QByteArray, ensuring proper encoding
static QByteArray stdStringToByteArray(std::string str) {
return QByteArray(str.c_str(), str.size());
}
/**
* @brief qstringToByteArray converts a QString into a QByteArray, ensuring proper encoding. Only
* safe for ascii content.
* @param q The string to convert
* @return the QString as a QByteArray
*/
static QByteArray qstringToByteArray(QString q) { return stdStringToByteArray(q.toStdString()); }
/// writeFile write the provided content to the provided path.
/// @throws a FileError if there are issues opening or writing to the file.
static void writeFile(QString path, QString content) {
writeFile(path, qstringToByteArray(content));
writeFile(path, content.toUtf8());
}
/// writeFile write the provided content to the provided path.

View File

@ -123,9 +123,8 @@ inline size_t QtKeyToWin(Qt::Key key)
return key;
}
#elif defined(Q_OS_LINUX)
#include "ukeysequence.h"
#include <unordered_map>
#include <QMap>
#include "xcb/xcb.h"
#include "xcb/xcb_keysyms.h"
#include "X11/keysym.h"
@ -135,7 +134,7 @@ struct UKeyData {
int mods;
};
static std::unordered_map<uint32_t, uint32_t> KEY_MAP = {
inline const static QMap<uint32_t, uint32_t> KEY_MAP = {
{Qt::Key_Escape, XK_Escape},
{Qt::Key_Tab, XK_Tab},
{Qt::Key_Backspace, XK_BackSpace},
@ -163,15 +162,15 @@ inline UKeyData QtKeyToLinux(const UKeySequence &keySeq)
auto key = keySeq.getSimpleKeys();
if (key.size() > 0) {
data.key = key[0];
data.key = key.first();
} else {
qWarning() << "Invalid hotkey";
return data;
}
// Key conversion
// Misc Keys
if (KEY_MAP.find(key[0]) != KEY_MAP.end()) {
data.key = KEY_MAP[key[0]];
if (KEY_MAP.find(key.first()) != KEY_MAP.end()) {
data.key = KEY_MAP.value(key.first());
} else if (data.key >= Qt::Key_F1 && data.key <= Qt::Key_F35) { // Qt's F keys need conversion
const size_t DIFF = Qt::Key_F1 - XK_F1;
data.key -= DIFF;
@ -198,18 +197,19 @@ inline UKeyData QtKeyToLinux(const UKeySequence &keySeq)
return data;
}
xcb_connection_t *X11Connection;
xcb_window_t X11Wid;
xcb_key_symbols_t *X11KeySymbs;
#elif defined(Q_OS_MAC)
#include "ukeysequence.h"
#include <Carbon/Carbon.h>
#include <unordered_map>
#include <QMap>
struct UKeyData {
uint32_t key;
uint32_t mods;
};
static std::unordered_map<uint32_t, uint32_t> KEY_MAP = {
static QMap<uint32_t, uint32_t> KEY_MAP = {
{Qt::Key_A, kVK_ANSI_A},
{Qt::Key_B, kVK_ANSI_B},
{Qt::Key_C, kVK_ANSI_C},
@ -263,7 +263,7 @@ static std::unordered_map<uint32_t, uint32_t> KEY_MAP = {
{Qt::Key_Print, kVK_F14},
};
static std::unordered_map<uint32_t, uint32_t> MOD_MAP = {
static QMap<uint32_t, uint32_t> MOD_MAP = {
{Qt::Key_Shift, shiftKey},
{Qt::Key_Alt, optionKey},
{Qt::Key_Control, controlKey},
@ -277,8 +277,8 @@ inline UKeyData QtKeyToMac(const UKeySequence &keySeq)
auto key = keySeq.getSimpleKeys();
auto mods = keySeq.getModifiers();
if (key.size() == 1 && KEY_MAP.find(key[0]) != KEY_MAP.end()) {
data.key = KEY_MAP[key[0]];
if (key.size() == 1 && KEY_MAP.find(key.first()) != KEY_MAP.end()) {
data.key = KEY_MAP.value(key.first());
} else {
qWarning() << "Invalid hotkey";
return data;
@ -288,9 +288,9 @@ inline UKeyData QtKeyToMac(const UKeySequence &keySeq)
if (MOD_MAP.find(mod) == MOD_MAP.end())
return data;
data.mods += MOD_MAP[mod];
data.mods += MOD_MAP.value(mod);
}
return data;
}
QHash<size_t, EventHotKeyRef> HotkeyRefs;
#endif

View File

@ -22,8 +22,8 @@ void UKeySequence::fromString(const QString &str)
QString UKeySequence::toString()
{
const QVector<Qt::Key> simpleKeys = getSimpleKeys();
const QVector<Qt::Key> modifiers = getModifiers();
const QList<Qt::Key> simpleKeys = getSimpleKeys();
const QList<Qt::Key> modifiers = getModifiers();
QStringList result;
for (auto mod : modifiers)
result.append(keyToStr(mod));
@ -34,9 +34,9 @@ QString UKeySequence::toString()
return result.join('+');
}
QVector<Qt::Key> UKeySequence::getSimpleKeys() const
QList<Qt::Key> UKeySequence::getSimpleKeys() const
{
QVector<Qt::Key> result;
QList<Qt::Key> result;
for (auto key : qAsConst(mKeys)) {
if (!isModifier(key)) {
result.append(key);
@ -45,9 +45,9 @@ QVector<Qt::Key> UKeySequence::getSimpleKeys() const
return result;
}
QVector<Qt::Key> UKeySequence::getModifiers() const
QList<Qt::Key> UKeySequence::getModifiers() const
{
QVector<Qt::Key> result;
QList<Qt::Key> result;
for (auto key : qAsConst(mKeys)) {
if (isModifier(key)) {
result.append(key);

View File

@ -2,7 +2,7 @@
#include <QObject>
#include <QString>
#include <QVector>
#include <QList>
#include <QStringList>
#include <QKeyEvent>
@ -34,11 +34,11 @@ public:
return mKeys[n];
}
QVector<Qt::Key> getSimpleKeys() const;
QVector<Qt::Key> getModifiers() const;
QList<Qt::Key> getSimpleKeys() const;
QList<Qt::Key> getModifiers() const;
private:
QVector<Qt::Key> mKeys;
QList<Qt::Key> mKeys;
inline static bool isModifier(Qt::Key key)
{

View File

@ -115,10 +115,10 @@ class NetMan : public QObject {
}
QMessageAuthenticationCode code(QCryptographicHash::Sha256);
QByteArray key = QByteArray::fromBase64(FileHelpers::qstringToByteArray(secretKeyCopy));
QByteArray key = QByteArray::fromBase64(secretKeyCopy.toUtf8());
code.setKey(key);
code.addData(FileHelpers::stdStringToByteArray(msg));
code.addData(QByteArray::fromStdString(msg));
return code.result().toBase64();
}
@ -178,7 +178,7 @@ class NetMan : public QObject {
parser.AddFile("file", evidence.path.toStdString());
auto body = FileHelpers::stdStringToByteArray(parser.GenBodyContent());
auto body = QByteArray::fromStdString(parser.GenBodyContent());
auto builder = ashirtFormPost(QStringLiteral("/api/operations/%1/evidence").arg(evidence.operationSlug), body, parser.boundary().c_str());
addASHIRTAuth(builder);
@ -256,7 +256,7 @@ class NetMan : public QObject {
/// checkForNewRelease retrieves the recent releases from github for the provided owner/repo project.
/// Callers should retrieve the result by listening for the releasesChecked signal
void checkForNewRelease(QString owner, QString repo) {
if (owner == Constants::unknownOwnerValue() || repo == Constants::unknownRepoValue()) {
if (owner == Constants::unknownValue || repo == Constants::unknownValue) {
std::cerr << "Skipping release check: no owner or repo set." << std::endl;
return;
}

View File

@ -149,7 +149,7 @@ class RequestBuilder {
QNetworkRequest req;
for(const auto& header : rawHeaders) {
req.setRawHeader(FileHelpers::qstringToByteArray(header.first), FileHelpers::qstringToByteArray(header.second));
req.setRawHeader(header.first.toUtf8(), header.second.toUtf8());
}
for(const auto& header : knownHeaders) {

View File

@ -34,7 +34,7 @@ int main(int argc, char* argv[]) {
DatabaseConnection* conn;
try {
conn = new DatabaseConnection(Constants::dbLocation(), Constants::defaultDbName());
conn = new DatabaseConnection(Constants::dbLocation, Constants::defaultDbName);
conn->connect();
}
catch (FileError& err) {

View File

@ -10,11 +10,11 @@
static Codeblock fromJson(QJsonObject obj) {
Codeblock rtn;
rtn.content = obj["content"].toVariant().toString();
rtn.subtype = obj["contentSubtype"].toString();
QJsonObject meta = obj["metadata"].toObject();
rtn.content = obj.value(QStringLiteral("content")).toVariant().toString();
rtn.subtype = obj.value(QStringLiteral("contentSubtype")).toString();
QJsonObject meta = obj.value(QStringLiteral("metadata")).toObject();
if (!meta.empty()) {
rtn.source = meta["source"].toString();
rtn.source = obj.value(QStringLiteral("source")).toString();
}
return rtn;

View File

@ -30,7 +30,7 @@ void SystemManifest::migrateConfig() {
}
}
AppConfig::getInstance().applyConfig(src);
return "";
return QString();
});
AppConfig::getInstance().writeConfig(); // save updated config
}

View File

@ -317,7 +317,7 @@ QIcon TrayManager::getTrayIcon()
void TrayManager::onTrayMessageClicked() {
switch(currentTrayMessage) {
case UPGRADE:
QDesktopServices::openUrl(Constants::releasePageUrl());
QDesktopServices::openUrl(Constants::releasePageUrl);
break;
case OPEN_PATH:
QDesktopServices::openUrl(openServicesPath);