feat!: Add support for FingerPrintDatabase

This commit is contained in:
Vamshi Maskuri
2025-01-28 23:13:46 +05:30
committed by Nick Bolton
parent 59ebb6fde4
commit 8f219b735e
12 changed files with 466 additions and 1 deletions

View File

@ -15,6 +15,7 @@ add_library(base STATIC
FunctionEventJob.h
FunctionJob.cpp
FunctionJob.h
finally.h
IEventJob.h
IEventQueue.h
IEventQueueBuffer.h

51
src/lib/base/finally.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <utility>
namespace deskflow {
// this implements a common pattern of executing an action at the end of function
template <class Callable> class FinalAction
{
public:
FinalAction() noexcept
{
}
FinalAction(Callable callable) noexcept : callable_{callable}
{
}
~FinalAction() noexcept
{
if (!invoked_) {
callable_();
}
}
FinalAction(FinalAction &&other) noexcept : callable_{std::move(other.callable_)}
{
std::swap(invoked_, other.invoked_);
}
FinalAction(const FinalAction &) = delete;
FinalAction &operator=(const FinalAction &) = delete;
private:
bool invoked_ = false;
Callable callable_;
};
template <class Callable> inline FinalAction<Callable> finally(Callable &&callable) noexcept
{
return FinalAction<Callable>(std::forward<Callable>(callable));
}
} // namespace deskflow

View File

@ -4,6 +4,8 @@
# SPDX-License-Identifier: MIT
add_library(io STATIC
filesystem.cpp
filesystem.h
IStream.h
StreamBuffer.cpp
StreamBuffer.h
@ -12,3 +14,11 @@ add_library(io STATIC
XIO.cpp
XIO.h
)
# Windows-specific files
if(WIN32)
target_sources(io PRIVATE
win32/encoding_utilities.cpp
win32/encoding_utilities.h
)
endif()

57
src/lib/io/filesystem.cpp Normal file
View File

@ -0,0 +1,57 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
// TODO: remove dead code if not used in PR #7931
#include "filesystem.h"
#include "common/common.h"
#if SYSAPI_WIN32
#include "io/win32/encoding_utilities.h"
#endif
#include <fstream>
namespace deskflow {
namespace {
template <class Stream> void openUtf8PathImpl(Stream &stream, const fs::path &path, std::ios_base::openmode mode)
{
stream.open(path.native().c_str(), mode);
}
} // namespace
void openUtf8Path(std::ifstream &stream, const fs::path &path, std::ios_base::openmode mode)
{
openUtf8PathImpl(stream, path, mode);
}
void openUtf8Path(std::ofstream &stream, const fs::path &path, std::ios_base::openmode mode)
{
openUtf8PathImpl(stream, path, mode);
}
void openUtf8Path(std::fstream &stream, const fs::path &path, std::ios_base::openmode mode)
{
openUtf8PathImpl(stream, path, mode);
}
std::FILE *fopenUtf8Path(const fs::path &path, const std::string &mode)
{
#if SYSAPI_WIN32
std::wstring wpath = path.native();
std::wstring wmode(mode.begin(), mode.end());
return _wfopen(wpath.c_str(), wmode.c_str());
#else
return std::fopen(path.native().c_str(), mode.c_str());
#endif
}
} // namespace deskflow

28
src/lib/io/filesystem.h Normal file
View File

@ -0,0 +1,28 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
// TODO: remove dead code if not used in PR #7931
#pragma once
#include <cstdio>
#include <filesystem>
#include <ios>
#include <iosfwd>
namespace deskflow {
namespace fs = std::filesystem;
void openUtf8Path(std::ifstream &stream, const fs::path &path, std::ios_base::openmode mode = std::ios_base::in);
void openUtf8Path(std::ofstream &stream, const fs::path &path, std::ios_base::openmode mode = std::ios_base::out);
void openUtf8Path(
std::fstream &stream, const fs::path &path, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out
);
std::FILE *fopenUtf8Path(const fs::path &path, const std::string &mode);
} // namespace deskflow

View File

@ -0,0 +1,35 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
// TODO: remove dead code if not used in PR #7931
#include "encoding_utilities.h"
#include <stringapiset.h>
namespace deskflow {
// TODO: use this function in PR #7931 or delete it
std::string winWcharToUtf8(const WCHAR *utfStr)
{
int utfLength = lstrlenW(utfStr);
int mbLength = WideCharToMultiByte(CP_UTF8, 0, utfStr, utfLength, NULL, 0, NULL, NULL);
std::string mbStr(mbLength, 0);
WideCharToMultiByte(CP_UTF8, 0, utfStr, utfLength, &mbStr[0], mbLength, NULL, NULL);
return mbStr;
}
// TODO: use this function in PR #7931 or delete it
std::vector<WCHAR> utf8ToWinChar(const std::string &str)
{
int result_len = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0);
std::vector<WCHAR> result;
result.resize(result_len + 1, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), result.data(), result_len);
return result;
}
} // namespace deskflow

View File

@ -0,0 +1,21 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
// TODO: remove dead code if not used in PR #7931
#pragma once
#include <string>
#include <vector>
#include <windows.h>
namespace deskflow {
std::string winWcharToUtf8(const WCHAR *utfStr);
std::vector<WCHAR> utf8ToWinChar(const std::string &str);
} // namespace deskflow

View File

@ -4,6 +4,10 @@
# SPDX-License-Identifier: MIT
add_library(net STATIC
FingerprintData.cpp
FingerprintData.h
FingerprintDatabase.cpp
FingerprintDatabase.h
IDataSocket.cpp
IDataSocket.h
IListenSocket.h
@ -51,5 +55,5 @@ target_link_libraries(
PRIVATE mt io)
if(WIN32)
target_link_libraries(net PRIVATE Crypt32 ws2_32)
target_link_libraries(net PRIVATE Crypt32 ws2_32 OpenSSL::applink)
endif()

View File

@ -0,0 +1,45 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "FingerprintDatabase.h"
#include "io/filesystem.h"
#include <algorithm>
#include <fstream>
namespace deskflow {
bool FingerprintData::operator==(const FingerprintData &other) const
{
return algorithm == other.algorithm && data == other.data;
}
const char *fingerprintTypeToString(FingerprintType type)
{
switch (type) {
case FingerprintType::INVALID:
return "invalid";
case FingerprintType::SHA1:
return "sha1";
case FingerprintType::SHA256:
return "sha256";
default:
break;
}
return "invalid";
}
FingerprintType fingerprintTypeFromString(const std::string &type)
{
if (type == "sha1") {
return FingerprintType::SHA1;
}
if (type == "sha256") {
return FingerprintType::SHA256;
}
return FingerprintType::INVALID;
}
} // namespace deskflow

View File

@ -0,0 +1,38 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <cstdint>
#include <string>
#include <vector>
namespace deskflow {
enum FingerprintType
{
INVALID,
SHA1, // deprecated
SHA256,
};
struct FingerprintData
{
std::string algorithm;
std::vector<std::uint8_t> data;
bool valid() const
{
return !algorithm.empty();
}
bool operator==(const FingerprintData &other) const;
};
const char *fingerprintTypeToString(FingerprintType type);
FingerprintType fingerprintTypeFromString(const std::string &type);
} // namespace deskflow

View File

@ -0,0 +1,129 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
// TODO: remove dead code if not used in PR #7931
#include "FingerprintDatabase.h"
#include "base/String.h"
#include "io/filesystem.h"
#include <algorithm>
#include <fstream>
namespace deskflow {
void FingerprintDatabase::read(const fs::path &path)
{
std::ifstream file;
openUtf8Path(file, path, std::ios_base::in);
readStream(file);
}
void FingerprintDatabase::write(const fs::path &path)
{
std::ofstream file;
openUtf8Path(file, path, std::ios_base::out);
writeStream(file);
}
void FingerprintDatabase::readStream(std::istream &stream)
{
if (!stream.good()) {
return;
}
std::string line;
while (std::getline(stream, line)) {
if (line.empty()) {
continue;
}
auto fingerprint = parseDbLine(line);
if (!fingerprint.valid()) {
continue;
}
m_fingerprints.push_back(fingerprint);
}
}
void FingerprintDatabase::writeStream(std::ostream &stream)
{
if (!stream.good()) {
return;
}
for (const auto &fingerprint : m_fingerprints) {
stream << toDbLine(fingerprint) << "\n";
}
}
void FingerprintDatabase::clear()
{
m_fingerprints.clear();
}
void FingerprintDatabase::addTrusted(const FingerprintData &fingerprint)
{
if (isTrusted(fingerprint)) {
return;
}
m_fingerprints.push_back(fingerprint);
}
bool FingerprintDatabase::isTrusted(const FingerprintData &fingerprint)
{
auto found = std::find(m_fingerprints.begin(), m_fingerprints.end(), fingerprint);
return found != m_fingerprints.end();
}
FingerprintData FingerprintDatabase::parseDbLine(const std::string &line)
{
FingerprintData result;
// legacy v1 certificate handling
if (std::count(line.begin(), line.end(), ':') == 19 && line.size() == 40 + 19) {
auto data = string::fromHex(line);
if (data.empty()) {
return result;
}
result.algorithm = fingerprintTypeToString(FingerprintType::SHA1);
result.data = data;
return result;
}
auto versionEndPos = line.find(':');
if (versionEndPos == std::string::npos) {
return result;
}
if (line.substr(0, versionEndPos) != "v2") {
return result;
}
auto algoStartPos = versionEndPos + 1;
auto algoEndPos = line.find(':', algoStartPos);
if (algoEndPos == std::string::npos) {
return result;
}
auto algorithm = line.substr(algoStartPos, algoEndPos - algoStartPos);
auto data = string::fromHex(line.substr(algoEndPos + 1));
if (data.empty()) {
return result;
}
result.algorithm = algorithm;
result.data = data;
return result;
}
std::string FingerprintDatabase::toDbLine(const FingerprintData &fingerprint)
{
std::string fingerprintStr(fingerprint.data.begin(), fingerprint.data.end());
return "v2:" + fingerprint.algorithm + ":" + string::toHex(fingerprintStr, 2);
}
} // namespace deskflow

View File

@ -0,0 +1,46 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
// TODO: remove dead code if not used in PR #7931
#pragma once
#include "FingerprintData.h"
#include "io/filesystem.h"
#include <iosfwd>
#include <string>
#include <vector>
namespace deskflow {
class FingerprintDatabase
{
public:
void read(const fs::path &path);
void write(const fs::path &path);
void readStream(std::istream &stream);
void writeStream(std::ostream &stream);
void clear();
void addTrusted(const FingerprintData &fingerprint);
bool isTrusted(const FingerprintData &fingerprint);
const std::vector<FingerprintData> &getFingerprints() const
{
return m_fingerprints;
}
static FingerprintData parseDbLine(const std::string &line);
static std::string toDbLine(const FingerprintData &fingerprint);
private:
std::vector<FingerprintData> m_fingerprints;
};
} // namespace deskflow