diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f44102..a748bef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ include_directories(password-analyzer PRIVATE ${CMAKE_BINARY_DIR}/external) set(COMMON_SOURCES defs.hpp utils.cpp + stat_date.cpp stat_keystroke.cpp stat_length.cpp stat_struct.cpp diff --git a/analyzer.cpp b/analyzer.cpp index 13b7c0a..7e436c3 100644 --- a/analyzer.cpp +++ b/analyzer.cpp @@ -10,5 +10,8 @@ int main() { stat_keystroke(DataSource::YAHOO); stat_keystroke(DataSource::CSDN); + stat_date(DataSource::YAHOO); + stat_date(DataSource::CSDN); + return 0; } diff --git a/defs.hpp b/defs.hpp index 10c8207..02fcec9 100644 --- a/defs.hpp +++ b/defs.hpp @@ -26,6 +26,7 @@ bool is_alpha(char c); std::generator passwords(const DataSource &source); +void stat_date(const DataSource &source); void stat_keystroke(const DataSource &source); void stat_length(const DataSource &source); void stat_struct(const DataSource &source); diff --git a/stat_date.cpp b/stat_date.cpp new file mode 100644 index 0000000..9072210 --- /dev/null +++ b/stat_date.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include "defs.hpp" + +const std::regex date_match[] = { + // YYYY MM DD + std::regex(R"((?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"((?:19|20)\d{2}\.(?:0[1-9]|1[0-2])\.(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"((?:19|20)\d{2}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"((?:19|20)\d{2}/(?:0[1-9]|1[0-2])/(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + // MM DD YYYY + std::regex(R"((?:0[1-9]|1[0-2])(?:0[1-9]|[1-2][0-9]|3[0-1])(?:19|20)\d{2})"), + std::regex(R"((?:0[1-9]|1[0-2])\.(?:0[1-9]|[1-2][0-9]|3[0-1])\.(?:19|20)\d{2})"), + std::regex(R"((?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])-(?:19|20)\d{2})"), + std::regex(R"((?:0[1-9]|1[0-2])/(?:0[1-9]|[1-2][0-9]|3[0-1])/(?:19|20)\d{2})"), + // YY MM DD + std::regex(R"(\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"(\d{2}\.(?:0[1-9]|1[0-2])\.(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"(\d{2}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"(\d{2}/(?:0[1-9]|1[0-2])/(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + // MM DD YY + std::regex(R"((?:0[1-9]|1[0-2])(?:0[1-9]|[1-2][0-9]|3[0-1])\d{2})"), + std::regex(R"((?:0[1-9]|1[0-2])\.(?:0[1-9]|[1-2][0-9]|3[0-1])\.\d{2})"), + std::regex(R"((?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])-\d{2})"), + std::regex(R"((?:0[1-9]|1[0-2])/(?:0[1-9]|[1-2][0-9]|3[0-1])/\d{2})"), + // MM DD + std::regex(R"((?:0[1-9]|1[0-2])(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"((?:0[1-9]|1[0-2])\.(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"((?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1]))"), + std::regex(R"((?:0[1-9]|1[0-2])/(?:0[1-9]|[1-2][0-9]|3[0-1]))"), +}; + +void stat_date(const DataSource &source) { + spdlog::info("stat_date({})", magic_enum::enum_name(source)); + + std::map date_map; + std::map type_map; + + for (auto const &password : passwords(source)) { + for (int i = 0; i < sizeof(date_match) / sizeof(date_match[0]); i++) { + const auto &match = date_match[i]; + auto bgn = std::sregex_iterator(password.begin(), password.end(), match); + auto end = std::sregex_iterator(); + + if (bgn != end) { + auto date = bgn->str(); + date_map[date]++; + type_map[i]++; + break; + } + } + } + + std::vector> date_vec(date_map.begin(), date_map.end()); + std::vector> type_vec(type_map.begin(), type_map.end()); + std::sort(date_vec.begin(), date_vec.end(), [](auto const &a, auto const &b) { return a.second > b.second; }); + std::sort(type_vec.begin(), type_vec.end(), [](auto const &a, auto const &b) { return a.second > b.second; }); + + for (auto &&[date, count] : date_vec | std::views::take(10)) { + spdlog::info("{}: {}", date, count); + } + + for (auto &&[type, count] : type_vec | std::views::take(10)) { + spdlog::info("{}: {}", type, count); + } +}