Add QDir directory handling and final paths (#39)

This migrates all paths over to the correct XDG compatible paths that should be used across systems and moves the code that manages file paths over to using QDir to provide more cross platform support. I'd like to take another pass later that removes some of the manual index('/') logic but everything looks good for now.

Closes #32
main
Joel Smith 2020-09-11 16:26:45 -07:00 committed by GitHub
parent 58033a31b8
commit be12927b7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 56 additions and 58 deletions

View File

@ -119,27 +119,27 @@ When applying only one date, the range is unbounded on the other end. That is, d
You should never need to access these files outside of the application, however, for clarity, the following files are generate and maintained by this application:
| File type | Path | Notes |
| -------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Screenshots | `$eviRepo/$operationSlug/ashirt_screenshot_$randomCharacters.png` | Presently, random (english) characters tacked on to the end of a screenshot, to add uniqueness and prevent overwriting |
| Codeblocks | `$eviRepo/$operationSlug/ashirt_codeblock_$randomCharacters.json` | Presently, random (english) characters tacked on to the end of the codeblock filename, to add uniqueness and prevent overwriting |
| Configuration | `$userSettingsDirectory/ashirt/screenshot.json` | Manages connection info / configuration in "settings" menu |
| Local Database | `$userSettingsDirectory/ashirt/screenshot.sqlite` | |
| Settings | `$userSettingsDirectory/Verizon Media Group/AShirt Screenshot.conf` | Manages state info -- e.g. last used operation ; Managed by Qt |
| File type | Path | Notes |
| -------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Screenshots | `$eviRepo/$operationSlug/ashirt_screenshot_$randomCharacters.png` | Presently, random (english) characters tacked on to the end of a screenshot, to add uniqueness and prevent overwriting |
| Codeblocks | `$eviRepo/$operationSlug/ashirt_codeblock_$randomCharacters.json` | Presently, random (english) characters tacked on to the end of the codeblock filename, to add uniqueness and prevent overwriting |
| Configuration | `$userDataDirectory/ashirt/config.json` | Manages connection info / configuration in "settings" menu |
| Local Database | `$userDataDirectory/ashirt/evidence.sqlite` | |
| Settings | `$userDataDirectory/Unknown Organization/ashirt.conf` | Manages state info -- e.g. last used operation ; Managed by Qt |
### Variable locations
The above paths reference some variables. Some of these values change depending on what operating system is being used (or in how it is configured). The exact paths are unknown, but this may help you find these files:
| Path Variable | Notes |
| ------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `$userSettingsDirectory` | Where user-specific configuration/settings files are stored. |
| [For Linux] | On the command line, run `echo $XDG_CONFIG_HOME` (by default, this is typically the `~/.config` directory) |
| [For Mac OSX] | Check `/Users/(username)/Library/Preferences` |
| [For windows] | This may be in the System Registry |
| `$eviRepo` | The Evidence Repository value in the "settings" window |
| `$operationSlug` | The operation slug for a given operation. This is a unique representation of an operation name |
| `$randomCharacters` | Six random english characters, case-insensitive (for those operating systems that support this). e.g. `fTaNpS` |
| Path Variable | Notes |
| -------------------- | -------------------------------------------------------------------------------------------------------------- |
| `$userDataDirectory` | Where user-specific data files are stored. |
| [For Linux] | On the command line, run `echo $XDG_CONFIG_HOME` (by default, this is typically the `~/.config` directory) |
| [For Mac OSX] | Check `/Users/(username)/Application Support/` |
| [For windows] | Check `C:\Users\(username)\AppData\Local\` |
| `$eviRepo` | The Evidence Repository value in the "settings" window |
| `$operationSlug` | The operation slug for a given operation. This is a unique representation of an operation name |
| `$randomCharacters` | Six random english characters, case-insensitive (for those operating systems that support this). e.g. `fTaNpS` |
## Developer Notes

View File

@ -91,6 +91,7 @@ HEADERS += \
src/forms/evidence_filter/evidencefilterform.h \
src/forms/getinfo/getinfo.h \
src/helpers/clipboard/clipboardhelper.h \
src/helpers/constants.h \
src/helpers/ui_helpers.h \
src/models/codeblock.h \
src/helpers/file_helpers.h \
@ -104,7 +105,6 @@ HEADERS += \
src/helpers/jsonhelpers.h \
src/helpers/multipartparser.h \
src/helpers/netman.h \
src/helpers/pathseparator.h \
src/helpers/screenshot.h \
src/helpers/stopreply.h \
src/dtos/tag.h \

View File

@ -14,6 +14,7 @@
#include <stdexcept>
#include "exceptions/fileerror.h"
#include "helpers/constants.h"
// AppConfig is a singleton construct for accessing the application's configuration.
// singleton design borrowed from:
@ -49,8 +50,7 @@ class AppConfig {
}
}
QString saveLocation =
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/ashirt/screenshot.json";
QString saveLocation = Constants::configLocation();
void readConfig() {
QFile configFile(saveLocation);
@ -93,7 +93,7 @@ class AppConfig {
}
void writeDefaultConfig() {
evidenceRepo = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/ashirt";
evidenceRepo = Constants::defaultEvidenceRepo();
#ifdef Q_OS_MACOS
screenshotExec = "screencapture -s %file";

View File

@ -10,6 +10,7 @@
#include "exceptions/databaseerr.h"
#include "exceptions/fileerror.h"
#include "helpers/constants.h"
// DatabaseConnection constructs a connection to the database, unsurpringly. Note that the
// constructor can throw a error (see below). Additionally, many methods can throw a QSqlError,
@ -18,6 +19,7 @@
//
// Throws: DBDriverUnavailable if the required database driver does not exist
DatabaseConnection::DatabaseConnection() {
QString dbPath = Constants::dbLocation();
const QString DRIVER("QSQLITE");
if (QSqlDatabase::isDriverAvailable(DRIVER)) {
db = QSqlDatabase::addDatabase(DRIVER);

View File

@ -15,9 +15,6 @@
#include "forms/evidence_filter/evidencefilter.h"
#include "models/evidence.h"
static QString dbPath =
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/ashirt/screenshot.sqlite";
class DBQuery {
private:
QString _query;

View File

@ -343,7 +343,7 @@ void EvidenceManager::setRowText(int row, const model::Evidence& model) {
setColText(COL_CONTENT_TYPE, model.contentType);
setColText(COL_SUBMITTED, model.uploadDate.isNull() ? "No" : "Yes");
setColText(COL_FAILED, model.errorText == "" ? "" : "Yes");
setColText(COL_PATH, model.path);
setColText(COL_PATH, QDir::toNativeSeparators(model.path));
setColText(COL_ERROR_MSG, model.errorText);
auto uploadDateText = model.uploadDate.isNull() ? "Never" : model.uploadDate.toLocalTime().toString(dateFormat);

View File

@ -12,7 +12,6 @@
#include "appsettings.h"
#include "helpers/http_status.h"
#include "helpers/netman.h"
#include "helpers/pathseparator.h"
#include "helpers/stopreply.h"
#include "helpers/ui_helpers.h"
#include "hotkeymanager.h"
@ -185,7 +184,7 @@ void Settings::showEvent(QShowEvent *evt) {
eviRepoTextBox->setFocus(); //setting focus to prevent retaining focus for macs
// reset the form in case a user left junk in the text boxes and pressed "cancel"
eviRepoTextBox->setText(inst.evidenceRepo);
eviRepoTextBox->setText(QDir::toNativeSeparators(inst.evidenceRepo));
accessKeyTextBox->setText(inst.accessKey);
secretKeyTextBox->setText(inst.secretKey);
hostPathTextBox->setText(inst.apiURL);
@ -216,7 +215,7 @@ void Settings::onSaveClicked() {
AppConfig &inst = AppConfig::getInstance();
inst.evidenceRepo = eviRepoTextBox->text();
inst.evidenceRepo = QDir::fromNativeSeparators(eviRepoTextBox->text());
inst.accessKey = accessKeyTextBox->text();
inst.secretKey = secretKeyTextBox->text();
@ -249,7 +248,7 @@ void Settings::onBrowseClicked() {
auto filename = QFileDialog::getExistingDirectory(this, tr("Select a project directory"),
browseStart, QFileDialog::ShowDirsOnly);
if (filename != nullptr) {
eviRepoTextBox->setText(filename);
eviRepoTextBox->setText(QDir::toNativeSeparators(filename));
}
}

25
src/helpers/constants.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <QStandardPaths>
#include <QString>
#include <iostream>
class Constants {
public:
static QString configLocation() {
return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/config.json";
}
static QString dbLocation() {
return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/evidence.sqlite";
}
static QString defaultEvidenceRepo() {
return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/evidence";
}
};
#endif // CONSTANTS_H

View File

@ -12,7 +12,6 @@
#include "appconfig.h"
#include "appsettings.h"
#include "exceptions/fileerror.h"
#include "helpers/pathseparator.h"
class FileHelpers {
public:
@ -62,9 +61,9 @@ class FileHelpers {
static QString pathToEvidence() {
AppConfig &conf = AppConfig::getInstance();
auto op = AppSettings::getInstance().operationSlug();
auto root = conf.evidenceRepo + PATH_SEPARATOR;
auto root = conf.evidenceRepo + "/";
if (op != "") {
root += op + PATH_SEPARATOR;
root += op + "/";
}
QDir().mkpath(root);

View File

@ -1,20 +0,0 @@
// Copyright 2020, Verizon Media
// Licensed under the terms of MIT. See LICENSE file in project root for terms.
#ifndef PATHSEPARATOR_H
#define PATHSEPARATOR_H
// FROM:
// https://stackoverflow.com/questions/12971499/how-to-get-the-file-separator-symbol-in-standard-c-c-or
// Note: this is only going to work for Windows and (linux/mac). Boost may have the ability to
// resolve this Note2: We probably don't need this. Qt treats "/" as the universal path separator.
// We would only need this for reflecting the path to the user. See:
// https://doc.qt.io/qt-5/qdir.html
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
#endif // PATHSEPARATOR_H

View File

@ -15,7 +15,6 @@
#include "appconfig.h"
#include "helpers/file_helpers.h"
#include "helpers/pathseparator.h"
Screenshot::Screenshot(QObject *parent) : QObject(parent) {}
@ -39,11 +38,10 @@ void Screenshot::basicScreenshot(QString cmdProto) {
auto hasPath = QDir().mkpath(root);
if (hasPath) {
auto tempPath = FileHelpers::randomFilename(QDir::tempPath() + PATH_SEPARATOR +
"ashirt_screenshot_XXXXXX.png");
auto tempPath = FileHelpers::randomFilename(QDir::tempPath() + "/ashirt_screenshot_XXXXXX.png");
QString cmd = formatScreenshotCmd(std::move(cmdProto), tempPath);
auto lastSlash = tempPath.lastIndexOf(PATH_SEPARATOR) + 1;
auto lastSlash = tempPath.lastIndexOf("/") + 1;
QString tempName = tempPath.right(tempPath.length() - lastSlash);
system(cmd.toStdString().c_str());

View File

@ -56,9 +56,7 @@ int main(int argc, char* argv[]) {
Q_INIT_RESOURCE(res_migrations);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setOrganizationName("Verizon Media Group");
QCoreApplication::setOrganizationDomain("verizon.com");
QCoreApplication::setApplicationName("AShirt Screenshot");
QCoreApplication::setApplicationName("ashirt");
DatabaseConnection* conn;
try {