Skip to content

Commit

Permalink
Add code for ignore rules for secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
Slackadays committed Mar 11, 2024
1 parent 991689b commit 1f84e72
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 22 deletions.
3 changes: 3 additions & 0 deletions src/cb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ set(THREADS_PREFER_PTHREAD_FLAG True)
find_package(Threads REQUIRED)
target_link_libraries(cb Threads::Threads)

find_package(OpenSSL REQUIRED)
target_link_libraries(cb OpenSSL::Crypto)

install(TARGETS cb DESTINATION bin)

if(X11WL OR APPLE)
Expand Down
69 changes: 68 additions & 1 deletion src/cb/src/actions/ignore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
#include "../clipboard.hpp"
#include <openssl/sha.h>

namespace PerformAction {

Expand Down Expand Up @@ -80,8 +81,74 @@ void ignoreRegex() {
if (pattern != regexes.back()) fprintf(stderr, ", ");
}
fprintf(stderr, "%s", formatColors("[blank]\n").data());
path.applyIgnoreRegexes();
path.applyIgnoreRules();
exit(EXIT_SUCCESS);
}

void ignoreSecret() {
std::vector<std::string> secrets;
if (io_type == IOType::Pipe)
secrets.emplace_back(pipedInContent());
else
std::transform(copying.items.begin(), copying.items.end(), std::back_inserter(secrets), [](const auto& item) { return item.string(); });

if (secrets.empty()) {
if (fs::exists(path.metadata.ignore_secret) && !fs::is_empty(path.metadata.ignore_secret)) {
std::vector<std::string> ignoreSecrets(fileLines(path.metadata.ignore_secret));

if (is_tty.out) {
stopIndicator();
fprintf(stderr, "%s", formatColors("[info]โ”ƒ Ignore secrets for this clipboard: [help]").data());
for (const auto& secret : ignoreSecrets)
fprintf(stderr, "%s%s", secret.data(), secret != ignoreSecrets.back() ? ", " : "");
fprintf(stderr, "%s", formatColors("[blank]\n").data());
} else {
for (const auto& secret : ignoreSecrets)
printf("%s%s", secret.data(), secret != ignoreSecrets.back() ? ", " : "");
}
} else {
stopIndicator();
fprintf(stderr, "%s", formatColors("[info]โ”ƒ There are no ignore secrets for this clipboard.[blank]\n").data());
}
return;
}

if (secrets.size() == 1 && (secrets.at(0) == "" || secrets.at(0) == "\n")) {
fs::remove(path.metadata.ignore_secret);
if (output_silent || confirmation_silent) return;
stopIndicator();
fprintf(stderr, "%s", formatColors("[success][inverse] โœ” [noinverse] Removed ignore secrets\n").data());
exit(EXIT_SUCCESS);
}

std::string writeToFileContent;
for (const auto& secret : secrets) {
std::array<unsigned char, SHA512_DIGEST_LENGTH> hash;
SHA512(reinterpret_cast<const unsigned char*>(secret.data()), secret.size(), hash.data());
std::stringstream ss;
for (const auto& byte : hash)
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
writeToFileContent += ss.str() + "\n";
}

writeToFile(path.metadata.ignore_secret, writeToFileContent);

stopIndicator();
fprintf(stderr, "%s", formatColors("[success][inverse] โœ” [noinverse] Saved ignore secrets [bold]").data());
for (const auto& secret : secrets) {
fprintf(stderr, "%s", secret.data());
if (secret != secrets.back()) fprintf(stderr, ", ");
}
fprintf(stderr, "%s", formatColors("[blank]\n").data());
path.applyIgnoreRules();
exit(EXIT_SUCCESS);
}

void ignore() {
if (secret_selection)
ignoreSecret();
else
ignoreRegex();
}

} // namespace PerformAction
2 changes: 1 addition & 1 deletion src/cb/src/actions/load.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void load() {
}
}

destination.applyIgnoreRegexes();
destination.applyIgnoreRules();

successes.clipboards++;
} catch (const fs::filesystem_error& e) {
Expand Down
54 changes: 43 additions & 11 deletions src/cb/src/clipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
#include "clipboard.hpp"
#include <openssl/sha.h>

Clipboard::Clipboard(const std::string& clipboard_name, const unsigned long& clipboard_entry) {
this_name = clipboard_name;
Expand Down Expand Up @@ -44,6 +45,7 @@ Clipboard::Clipboard(const std::string& clipboard_name, const unsigned long& cli
metadata.originals = metadata / constants.original_files_name;
metadata.lock = metadata / constants.lock_name;
metadata.ignore = metadata / constants.ignore_regex_name;
metadata.ignore_secret = metadata / constants.ignore_secret_name;

fs::create_directories(data);
fs::create_directories(metadata);
Expand Down Expand Up @@ -95,6 +97,10 @@ bool Clipboard::holdsIgnoreRegexes() {
return fs::exists(metadata.ignore) && !fs::is_empty(metadata.ignore);
}

bool Clipboard::holdsIgnoreSecrets() {
return fs::exists(metadata.ignore_secret) && !fs::is_empty(metadata.ignore_secret);
}

std::vector<std::regex> Clipboard::ignoreRegexes() {
std::vector<std::regex> regexes;
if (!holdsIgnoreRegexes()) return regexes;
Expand All @@ -103,18 +109,44 @@ std::vector<std::regex> Clipboard::ignoreRegexes() {
return regexes;
}

void Clipboard::applyIgnoreRegexes() {
if (!holdsIgnoreRegexes()) return;
auto regexes = ignoreRegexes();
if (holdsRawDataInCurrentEntry()) {
std::vector<std::string> Clipboard::ignoreSecrets() {
std::vector<std::string> secrets;
if (!holdsIgnoreSecrets()) return secrets;
for (const auto& line : fileLines(metadata.ignore_secret))
secrets.emplace_back(line);
return secrets;
}

void Clipboard::applyIgnoreRules() {
if (holdsIgnoreRegexes()) {
auto regexes = ignoreRegexes();
if (holdsRawDataInCurrentEntry()) {
auto content = fileContents(data.raw).value();
for (const auto& regex : regexes)
content = std::regex_replace(content, regex, "");
writeToFile(data.raw, content);
} else
for (const auto& regex : regexes)
for (const auto& entry : fs::directory_iterator(data))
if (std::regex_match(entry.path().filename().string(), regex)) fs::remove_all(entry.path());
}

if (holdsIgnoreSecrets()) {
auto secrets = ignoreSecrets();
if (!holdsRawDataInCurrentEntry()) return;
auto content = fileContents(data.raw).value();
for (const auto& regex : regexes)
content = std::regex_replace(content, regex, "");
writeToFile(data.raw, content);
} else
for (const auto& regex : regexes)
for (const auto& entry : fs::directory_iterator(data))
if (std::regex_match(entry.path().filename().string(), regex)) fs::remove_all(entry.path());
std::array<unsigned char, SHA512_DIGEST_LENGTH> hash;
for (const auto& secret : secrets) {
SHA512(reinterpret_cast<const unsigned char*>(content.data()), content.size(), hash.data());
std::stringstream ss;
for (const auto& byte : hash)
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
if (ss.str() == secret) {
writeToFile(data.raw, "");
break;
}
}
}
}

bool Clipboard::isUnused() {
Expand Down
9 changes: 8 additions & 1 deletion src/cb/src/clipboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ struct Constants {
std::string_view metadata_directory = "metadata";
std::string_view import_export_directory = "Exported_Clipboards";
std::string_view ignore_regex_name = "ignore";
std::string_view ignore_secret_name = "ignore.secret";
};
constexpr Constants constants;

Expand Down Expand Up @@ -177,6 +178,7 @@ extern bool progress_silent;
extern bool confirmation_silent;
extern bool no_color;
extern bool all_option;
extern bool secret_selection;

extern std::string preferred_mime;
extern std::vector<std::string> available_mimes;
Expand Down Expand Up @@ -284,6 +286,7 @@ class Clipboard {
fs::path originals;
fs::path lock;
fs::path ignore;
fs::path ignore_secret;
operator fs::path() { return root; }
operator fs::path() const { return root; }
auto operator=(const auto& other) { return root = other; }
Expand All @@ -302,8 +305,10 @@ class Clipboard {
bool holdsRawDataInCurrentEntry() const;
bool holdsDataInCurrentEntry();
bool holdsIgnoreRegexes();
bool holdsIgnoreSecrets();
std::vector<std::regex> ignoreRegexes();
void applyIgnoreRegexes();
std::vector<std::string> ignoreSecrets();
void applyIgnoreRules();
bool isUnused();
bool isLocked() { return fs::exists(metadata.lock); }
void getLock();
Expand Down Expand Up @@ -485,7 +490,9 @@ void swap();
void importClipboards();
void exportClipboards();
void infoJSON();
void ignore();
void ignoreRegex();
void ignoreSecret();
void statusJSON();
void history();
void historyJSON();
Expand Down
10 changes: 10 additions & 0 deletions src/cb/src/externalclipboards.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "clipboard.hpp"
#include <climits>
#include <fstream>
#include <openssl/sha.h>

#if defined(_WIN32) || defined(_WIN64)
#define STDIN_FILENO 0
Expand Down Expand Up @@ -113,6 +114,15 @@ void convertFromGUIClipboard(const std::string& text) {
auto regexes = path.ignoreRegexes();
for (const auto& regex : regexes)
if (std::regex_match(text, regex)) return;
auto secrets = path.ignoreSecrets();
std::array<unsigned char, SHA512_DIGEST_LENGTH> hash;
for (const auto& secret : secrets) {
SHA512(reinterpret_cast<const unsigned char*>(text.data()), text.size(), hash.data());
std::stringstream ss;
for (const auto& byte : hash)
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
if (ss.str() == secret) return;
}
path.makeNewEntry();
writeToFile(path.data.raw, text);
}
Expand Down
2 changes: 1 addition & 1 deletion src/cb/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int main(int argc, char* argv[]) {

performAction();

if (isAWriteAction()) path.applyIgnoreRegexes();
if (isAWriteAction()) path.applyIgnoreRules();

copying.mime = getMIMEType();

Expand Down
32 changes: 25 additions & 7 deletions src/cb/src/utils/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <iterator>
#include <locale>
#include <mutex>
#include <openssl/sha.h>
#include <optional>
#include <regex>
#include <sstream>
Expand All @@ -51,6 +52,7 @@ bool progress_silent = false;
bool confirmation_silent = false;
bool no_color = false;
bool all_option = false;
bool secret_selection = false;

std::string maximumHistorySize;

Expand Down Expand Up @@ -160,11 +162,26 @@ unsigned long numberLength(const unsigned long& number) {
}

void ignoreItemsPreemptively(std::vector<fs::path>& items) {
if (!path.holdsIgnoreRegexes() || copying.items.empty() || action == Action::Ignore || io_type == IOType::Pipe) return;
auto regexes = path.ignoreRegexes();
for (const auto& regex : regexes)
for (const auto& item : items)
if (std::regex_match(item.string(), regex)) items.erase(std::find(items.begin(), items.end(), item));
if (copying.items.empty() || action == Action::Ignore || io_type == IOType::Pipe) return;
if (path.holdsIgnoreRegexes()) {
auto regexes = path.ignoreRegexes();
for (const auto& regex : regexes)
for (const auto& item : items)
if (std::regex_match(item.string(), regex)) items.erase(std::find(items.begin(), items.end(), item));
}
if (path.holdsIgnoreSecrets()) {
auto secrets = path.ignoreSecrets();
std::array<unsigned char, SHA512_DIGEST_LENGTH> hash;
for (const auto& secret : secrets) {
for (const auto& item : items) {
SHA512(reinterpret_cast<const unsigned char*>(item.string().data()), item.string().size(), hash.data());
std::stringstream ss;
for (const auto& byte : hash)
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
if (ss.str() == secret) items.erase(std::find(items.begin(), items.end(), item));
}
}
}
}

bool userIsARobot() {
Expand Down Expand Up @@ -444,6 +461,7 @@ void setFlags() {
if (auto flag = flagIsPresent<std::string>("-m"); flag != "") preferred_mime = flag;
if (flagIsPresent<bool>("--no-progress") || flagIsPresent<bool>("-np")) progress_silent = true;
if (flagIsPresent<bool>("--no-confirmation") || flagIsPresent<bool>("-nc")) confirmation_silent = true;
if (flagIsPresent<bool>("--secret") || flagIsPresent<bool>("-s")) secret_selection = true;
if (flagIsPresent<bool>("--bachata")) {
printf("%s", formatColors("[info]Here's some nice bachata music from Aventura! [help]https://www.youtube.com/watch?v=RxIM2bMBhCo\n[blank]").data());
printf("%s", formatColors("[info]How about some in English? [help]https://www.youtube.com/watch?v=jnD8Av4Dl4o\n[blank]").data());
Expand Down Expand Up @@ -631,7 +649,7 @@ void performAction() {
else if (action == Remove)
removeRegex();
else if (action == Ignore)
ignoreRegex();
ignore();
else if (action == Status)
statusJSON();
else if (action == Load)
Expand All @@ -654,7 +672,7 @@ void performAction() {
else if (action == Info)
info();
else if (action == Ignore)
ignoreRegex();
ignore();
else if (action == Import)
importClipboards();
else if (action == Export)
Expand Down

0 comments on commit 1f84e72

Please sign in to comment.