diff --git a/CertInfo.pro b/CertInfo.pro index 0c4bf3d..ddf9b98 100644 --- a/CertInfo.pro +++ b/CertInfo.pro @@ -6,7 +6,7 @@ QT += quick sql widgets quickcontrols2 QMAKE_CXXFLAGS = -Wno-deprecated-declarations -VERSION = 2024.01.1.0 # major.minor.patch.build +VERSION = 2024.01.2.0 # major.minor.patch.build DEFINES += APP_VERSION=\\\"$$VERSION\\\" QMAKE_TARGET_PRODUCT = "CertInfo" QMAKE_TARGET_COMPANY = "Sparkling Network" @@ -64,6 +64,7 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin include(src/thirdparty/SortFilterProxyModel/SortFilterProxyModel.pri) DISTFILES += \ + README.md \ certinfo.ico diff --git a/src/+qt5/ImportHostsFileDialog.qml b/src/+qt5/ImportHostsFileDialog.qml index eb36d04..421e8d2 100644 --- a/src/+qt5/ImportHostsFileDialog.qml +++ b/src/+qt5/ImportHostsFileDialog.qml @@ -7,7 +7,7 @@ FileDialog { required property var db required property var txt id: root - title: isTextFile ? "Choose a txt file with one domain per line" : isFirefox ? "Please choose the Firefox places.sqlite file" : "Please choose the Chrome History file" + title: isTextFile ? "Choose a txt file with one domain per line" : isFirefox ? "Please choose the Firefox places.sqlite file" : "Please choose the Chrome/Edge History file" nameFilters: isTextFile ? [ "text file (*.txt)", "All files (*)" ] : isFirefox ? [ "places.sqlite (places.sqlite)", "All files (*)" ] : [ "History (History)", "All files (*)" ] folder: shortcuts.home onAccepted: { @@ -24,5 +24,4 @@ FileDialog { } } } - Component.onCompleted: console.log("Using Qt 5 FileDialog") } diff --git a/src/+qt6/ImportHostsFileDialog.qml b/src/+qt6/ImportHostsFileDialog.qml index 119dbc2..55210bf 100644 --- a/src/+qt6/ImportHostsFileDialog.qml +++ b/src/+qt6/ImportHostsFileDialog.qml @@ -7,7 +7,7 @@ FileDialog { required property var db required property var txt id: root - title: isTextFile ? "Choose a txt file with one domain per line" : isFirefox ? "Please choose the Firefox places.sqlite file" : "Please choose the Chrome History file" + title: isTextFile ? "Choose a txt file with one domain per line" : isFirefox ? "Please choose the Firefox places.sqlite file" : "Please choose the Chrome/Edge History file" nameFilters: isTextFile ? [ "text file (*.txt)", "All files (*)" ] : isFirefox ? [ "places.sqlite (places.sqlite)", "All files (*)" ] : [ "History (History)", "All files (*)" ] onAccepted: { txt.hostnames = "" @@ -23,5 +23,4 @@ FileDialog { } } } - Component.onCompleted: console.log("Using Qt 6 FileDialog") } diff --git a/src/listmodel/caissuerlistmodel.cpp b/src/listmodel/caissuerlistmodel.cpp index 708383e..c09b52a 100644 --- a/src/listmodel/caissuerlistmodel.cpp +++ b/src/listmodel/caissuerlistmodel.cpp @@ -19,28 +19,28 @@ CACertificateListModel::CACertificateListModel(QObject* parent) : GenericListModel(parent) { - addValueSelector("subject", [](const Certificate &i) { return i.subject; }); - addValueSelector("subjectInfo", [](const Certificate &i) { return QVariant::fromValue(i.subjectInfo); }); - addValueSelector("string", [](const Certificate &i) { return QString::fromStdString(i.toString()); }); - addValueSelector("issuer", [](const Certificate &i) { return i.issuer; }); - addValueSelector("issuerInfo", [](const Certificate &i) { return QVariant::fromValue(i.issuerInfo); }); - addValueSelector("validFromDate", [](const Certificate &i) { return i.validFromDate.toString(); }); - addValueSelector("validUntilDate", [](const Certificate &i) { return i.validUntilDate.toString(); }); - addValueSelector("count", [](const Certificate &i) { return i.count; }); - addValueSelector("isca", [](const Certificate &i) { return i.isCA; }); - addValueSelector("istrustedrootca", [](const Certificate &i) { return i.isSystemTrustedRootCA; }); - addValueSelector("domains", [](const Certificate &i) { return i.domains.join(" "); }); - addValueSelector("subjectAlternativeNames", [](const Certificate &i) { return i.subjectAlternativeNames.join(" "); }); - addValueSelector("isselfsigned", [](const Certificate &i) { return i.isSelfSigned; }); - addValueSelector("errors", [](const Certificate &i) { return i.errors.join(" "); }); + addSelector("subject", [](const Certificate &i) { return i.subject; }); + addSelector("subjectInfo", [](const Certificate &i) { return QVariant::fromValue(i.subjectInfo); }); + addSelector("string", [](const Certificate &i) { return QString::fromStdString(i.toString()); }); + addSelector("issuer", [](const Certificate &i) { return i.issuer; }); + addSelector("issuerInfo", [](const Certificate &i) { return QVariant::fromValue(i.issuerInfo); }); + addSelector("validFromDate", [](const Certificate &i) { return i.validFromDate.toString(); }); + addSelector("validUntilDate", [](const Certificate &i) { return i.validUntilDate.toString(); }); + addSelector("count", [](const Certificate &i) { return i.count; }); + addSelector("isca", [](const Certificate &i) { return i.isCA; }); + addSelector("istrustedrootca", [](const Certificate &i) { return i.isSystemTrustedRootCA; }); + addSelector("domains", [](const Certificate &i) { return i.domains.join(" "); }); + addSelector("subjectAlternativeNames", [](const Certificate &i) { return i.subjectAlternativeNames.join(" "); }); + addSelector("isselfsigned", [](const Certificate &i) { return i.isSelfSigned; }); + addSelector("errors", [](const Certificate &i) { return i.errors.join(" "); }); } void CACertificateListModel::addOrUpdateItem(const Certificate &item, const QString& findBySubject) { - auto it = std::find_if(_listObjects.begin(), _listObjects.end(), [&findBySubject](const Certificate& c){ return c.subject == findBySubject;}); - if(it != _listObjects.end()) + auto it = std::find_if(m_listObjects.begin(), m_listObjects.end(), [&findBySubject](const Certificate& c){ return c.subject == findBySubject;}); + if(it != m_listObjects.end()) { - int index = std::distance(_listObjects.begin(), it); + int index = std::distance(m_listObjects.begin(), it); updateRow(index, item); } else { addRow(item); diff --git a/src/listmodel/domaincountlistmodel.cpp b/src/listmodel/domaincountlistmodel.cpp index d8fc9f2..bc5be23 100644 --- a/src/listmodel/domaincountlistmodel.cpp +++ b/src/listmodel/domaincountlistmodel.cpp @@ -19,6 +19,6 @@ domainCountListModel::domainCountListModel(QObject* parent) : GenericListModel(parent) { - addValueSelector("domain", [](const QIntPair &m) { return m.first; }); - addValueSelector("count", [](const QIntPair &m) { return m.second; }); + addSelector("domain", [](const QIntPair &m) { return m.first; }); + addSelector("count", [](const QIntPair &m) { return m.second; }); } diff --git a/src/listmodel/genericlistmodel.h b/src/listmodel/genericlistmodel.h index 1594891..1c68b93 100644 --- a/src/listmodel/genericlistmodel.h +++ b/src/listmodel/genericlistmodel.h @@ -40,29 +40,29 @@ class GenericListModel : public QAbstractListModelWithRowCountSignal int rowCount(const QModelIndex &parent = QModelIndex()) const override; virtual void move(int from, int to); - int addValueSelector(QByteArray name, std::function valueSelector); - int addValueSelector(QByteArray name, std::function valueSelector); - int addValueSelector(QByteArray name, std::function valueSelector, std::function valueSetter); - int addValueSelector(QByteArray name, std::function valueSelector, std::function valueSetter); + int addSelector(QByteArray name, std::function selector); + int addSelector(QByteArray name, std::function selector); + int addSelector(QByteArray name, std::function selector, std::function valueSetter); + int addSelector(QByteArray name, std::function selector, std::function valueSetter); QVariant dataByRoleName(const QModelIndex &index, const QString &name) const; void resync(); int getRoleIdByName(const QString &name) const; QVariantMap getRowByField(const QString &fieldName, const QVariant &value) const; protected: - QList _listObjects; - QMap>> _valueSelectorMap; - QMap>> _valueSetterMap; + QList m_listObjects; + QMap>> m_selectors; + QMap>> m_valueSetters; }; template void GenericListModel::updateFromVector(const std::vector &newObjects) { beginResetModel(); - _listObjects.clear(); + m_listObjects.clear(); for (const TObject &item : newObjects) { - _listObjects << item; + m_listObjects << item; } endResetModel(); } @@ -72,7 +72,7 @@ template void GenericListModel::updateFromQList(const QList &newObjects) { beginResetModel(); - _listObjects = newObjects; + m_listObjects = newObjects; endResetModel(); } @@ -80,7 +80,7 @@ template void GenericListModel::clear() { beginResetModel(); - _listObjects.clear(); + m_listObjects.clear(); endResetModel(); } @@ -88,7 +88,7 @@ template QHash GenericListModel::roleNames() const { QHash roles; - for (auto it = _valueSelectorMap.begin(); it != _valueSelectorMap.end(); ++it) + for (auto it = m_selectors.begin(); it != m_selectors.end(); ++it) { roles[it.key()] = it->first; } @@ -103,10 +103,10 @@ QVariant GenericListModel::data(const QModelIndex &index, int role) con return QVariant(); } - const TObject &object = _listObjects[index.row()]; - auto valueSelectorIterator = _valueSelectorMap.find(role); - if (valueSelectorIterator != _valueSelectorMap.end()) - return valueSelectorIterator->second(object, index); + const TObject &object = m_listObjects[index.row()]; + auto selectorIterator = m_selectors.find(role); + if (selectorIterator != m_selectors.end()) + return selectorIterator->second(object, index); return QVariant(); } @@ -117,9 +117,9 @@ bool GenericListModel::setData(const QModelIndex &index, const QVariant return false; bool result = false; - TObject &object = _listObjects[index.row()]; - auto valueSetterIterator = _valueSetterMap.find(role); - if (valueSetterIterator != _valueSetterMap.end()) + TObject &object = m_listObjects[index.row()]; + auto valueSetterIterator = m_valueSetters.find(role); + if (valueSetterIterator != m_valueSetters.end()) { result = valueSetterIterator->second(object, value); if (result) @@ -135,45 +135,44 @@ int GenericListModel::rowCount(const QModelIndex &index) const { return 0; } - return _listObjects.count(); + return m_listObjects.count(); } template void GenericListModel::move(int from, int to) { - _listObjects.move(from, to); + m_listObjects.move(from, to); } template -int GenericListModel::addValueSelector(QByteArray name, std::function valueSelector) +int GenericListModel::addSelector(QByteArray name, std::function selector) { - // std::bind ignores extra arguments, (I.E. QModelIndex) - std::function newValueSelector = std::bind(valueSelector, std::placeholders::_1); - return addValueSelector(name, newValueSelector); + std::function newselector = std::bind(selector, std::placeholders::_1); + return addSelector(name, newselector); } template -int GenericListModel::addValueSelector(QByteArray name, std::function valueSelector, std::function valueSetter) +int GenericListModel::addSelector(QByteArray name, std::function selector, std::function valueSetter) { - int roleNumber = addValueSelector(name, valueSelector); - _valueSetterMap[roleNumber] = QPair> {name, valueSetter}; + int roleNumber = addSelector(name, selector); + m_valueSetters[roleNumber] = QPair> {name, valueSetter}; return roleNumber; } template -int GenericListModel::addValueSelector(QByteArray name, std::function valueSelector, std::function valueSetter) +int GenericListModel::addSelector(QByteArray name, std::function selector, std::function valueSetter) { - int roleNumber = addValueSelector(name, valueSelector); - _valueSetterMap[roleNumber] = QPair> {name, valueSetter}; + int roleNumber = addSelector(name, selector); + m_valueSetters[roleNumber] = QPair> {name, valueSetter}; return roleNumber; } template -int GenericListModel::addValueSelector(QByteArray name, std::function valueSelector) +int GenericListModel::addSelector(QByteArray name, std::function selector) { - int roleNumber = Qt::UserRole + _valueSelectorMap.size() + 1; - _valueSelectorMap[roleNumber] = QPair> {name, valueSelector}; + int roleNumber = Qt::UserRole + m_selectors.size() + 1; + m_selectors[roleNumber] = QPair> {name, selector}; return roleNumber; } @@ -185,8 +184,8 @@ QVariant GenericListModel::dataByRoleName(const QModelIndex &index, con return QVariant(); } - const TObject &object = _listObjects[index.row()]; - for (const QPair> &mapEntry : _valueSelectorMap) + const TObject &object = m_listObjects[index.row()]; + for (const QPair> &mapEntry : m_selectors) { if (mapEntry.first == roleName) return mapEntry.second(object, index); @@ -198,7 +197,7 @@ template void GenericListModel::resync() { std::vector copiedListObjects; - std::copy(_listObjects.begin(), _listObjects.end(), std::back_inserter(copiedListObjects)); + std::copy(m_listObjects.begin(), m_listObjects.end(), std::back_inserter(copiedListObjects)); updateFromVector(copiedListObjects); } @@ -206,9 +205,9 @@ void GenericListModel::resync() template void GenericListModel::addRow(const TObject& newRow) { - auto size = _listObjects.size(); + auto size = m_listObjects.size(); emit beginInsertRows(QModelIndex(), size, size); - _listObjects.push_back(newRow); + m_listObjects.push_back(newRow); emit endInsertRows(); } @@ -216,9 +215,9 @@ void GenericListModel::addRow(const TObject& newRow) template void GenericListModel::updateRow(int rowNr, const TObject& newRow) { - if (rowNr >= _listObjects.size()) + if (rowNr >= m_listObjects.size()) return; - _listObjects[rowNr] = newRow; + m_listObjects[rowNr] = newRow; emit dataChanged(index(rowNr), index(rowNr)); } diff --git a/src/main.qml b/src/main.qml index 44403d0..d2d1069 100644 --- a/src/main.qml +++ b/src/main.qml @@ -115,7 +115,7 @@ Window { anchors.margins: 5 width: 300 enabled: !proc.busy - text: "Open Firefox History file (places.sqlite)" + text: "Open Firefox History file " onClicked: firefoxFileDialog.open() } @@ -126,7 +126,7 @@ Window { anchors.margins: 5 width: 300 enabled: !proc.busy - text: "Open Chrome History file (history)" + text: "Open Chrome/Edge History file" onClicked: chromeFileDialog.open() } @@ -583,17 +583,29 @@ Under the `Application Basics` section next to `Profile Folder`, click `Open Fol
-# Where is my chrome history? +# Where is my Chrome history? The path to your Chrome profile folder which contains the history file -named `history` (no extension) is: `%LOCALAPPDATA%\Google\Chrome\User Data`. +named `History` (no extension) is: `%LOCALAPPDATA%\Google\Chrome\User Data\Default`. Via Chrome you can navigate to `chrome://version`, then look for the `Profile Path` +# Where is my Edge history + +Since Edge is based on Chrome, the file format is the same. The + +`History` file is located here: + +`%LOCALAPPDATA%\Microsoft\Edge\User Data\Default` + + +Please note that old versions of Edge (not based on Chrome) + +are not supported. # A list of domains @@ -789,9 +801,6 @@ GNU Lesser General Public License v2.1 ] } - // ADD SYSTEM ROOT CA LIST AND REMOVE ALL FOUND CERTS, - // LEAVING ONLY A LIST OF UNUSED ROOT CA'S - DomainsListTextFile { id: txt }