add password reader

This commit is contained in:
Paul Pan 2023-11-03 21:05:08 +08:00
parent 351154f3a1
commit 78cd9404c5
3 changed files with 168 additions and 0 deletions

68
CMakeLists.txt Normal file
View File

@ -0,0 +1,68 @@
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
include(FetchContent)
project(password-analyzer CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=mold -Wno-unused-command-line-argument")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined")
message(STATUS "[DEPS] Processing spdlog")
FetchContent_Declare(
spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog
GIT_TAG v1.12.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(spdlog)
message(STATUS "[DEPS] Processing Catch2")
find_package(Catch2 3 CONFIG)
if (NOT Catch2_FOUND)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.4.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(Catch2)
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
endif ()
message(STATUS "[DEPS] Processing MagicEnum")
FetchContent_Declare(
magic_enum
GIT_REPOSITORY https://github.com/Neargye/magic_enum
GIT_TAG v0.9.3
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(magic_enum)
message(STATUS "[DEPS] Processing generator")
file(DOWNLOAD
"https://raw.githubusercontent.com/lewissbaker/generator/master/include/__generator.hpp"
"${CMAKE_BINARY_DIR}/external/generator.hpp")
include_directories(password-analyzer PRIVATE ${CMAKE_BINARY_DIR}/external)
set(COMMON_SOURCES
defs.hpp
utils.cpp
)
set(COMMON_LIBRARIES
magic_enum::magic_enum
spdlog::spdlog
)
add_executable(password-analyzer ${COMMON_SOURCES} analyzer.cpp)
target_link_libraries(password-analyzer PRIVATE ${COMMON_LIBRARIES})

24
defs.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef DEFS_HPP
#define DEFS_HPP
#include <string>
#if __has_include(<generator>)
#include <generator>
#else
#include "generator.hpp"
#endif
#include "spdlog/spdlog.h"
#include "magic_enum.hpp"
using std::operator""s;
using std::operator""sv;
enum class DataSource { CSDN, YAHOO };
bool is_num(char c);
bool is_alpha(char c);
std::generator<std::string> passwords(const DataSource &source);
#endif // DEFS_HPP

76
utils.cpp Normal file
View File

@ -0,0 +1,76 @@
#include <cctype>
#include <fstream>
#include <ranges>
#include <string>
#include <utility>
#include "defs.hpp"
bool is_num(char c) { return c >= '0' && c <= '9'; }
bool is_alpha(char c) { return std::isalpha(c); }
static std::vector<std::string> data_buf[2];
enum class BufStatus { INIT, FILLING, DONE };
static BufStatus data_buf_ok[2] = {BufStatus::INIT, BufStatus::INIT};
std::generator<std::string> passwords(const DataSource &source) {
if (data_buf_ok[magic_enum::enum_integer(source)] == BufStatus::DONE) {
for (auto const &password : data_buf[magic_enum::enum_integer(source)]) {
co_yield password;
}
co_return;
}
if (data_buf_ok[magic_enum::enum_integer(source)] == BufStatus::INIT)
data_buf_ok[magic_enum::enum_integer(source)] = BufStatus::FILLING;
auto filename = "data/"s + (source == DataSource::CSDN ? "www.csdn.net.sql"s : "plaintxt_yahoo.txt"s);
std::ifstream is(filename);
if (!is.is_open()) {
spdlog::error("failed to open {}", filename);
co_return;
}
switch (source) {
case DataSource::CSDN: {
constexpr auto delim{" # "sv};
std::string line;
while (std::getline(is, line)) {
auto segments = line | std::views::split(delim);
auto second = *std::ranges::next(segments.begin(), 1);
auto password = std::string(second.begin(), second.end());
if (data_buf_ok[magic_enum::enum_integer(source)] == BufStatus::FILLING)
data_buf[magic_enum::enum_integer(source)].push_back(password);
co_yield password;
}
} break;
case DataSource::YAHOO: {
constexpr auto delim{":"sv};
std::string line;
while (std::getline(is, line)) {
std::erase(line, '\r');
if (line.empty() || !is_num(line[0])) continue;
if (is_num(line[0]) && line[1] == '.') continue;
auto segments = line | std::views::split(delim);
auto third = *std::ranges::next(segments.begin(), 2);
auto password = std::string(third.begin(), third.end());
if (password.empty()) continue;
if (data_buf_ok[magic_enum::enum_integer(source)] == BufStatus::FILLING)
data_buf[magic_enum::enum_integer(source)].push_back(password);
co_yield password;
}
} break;
default: std::unreachable();
}
data_buf_ok[magic_enum::enum_integer(source)] = BufStatus::DONE;
is.close();
co_return;
}