diff --git a/Password_manager/Password_manager.vcxproj b/Password_manager/Password_manager.vcxproj index 1dc1207..c2cbe6d 100644 --- a/Password_manager/Password_manager.vcxproj +++ b/Password_manager/Password_manager.vcxproj @@ -135,6 +135,7 @@ <ItemGroup> <ClCompile Include="source\buffer.cpp" /> <ClCompile Include="source\func.cpp" /> + <ClCompile Include="source\glob.cpp" /> <ClCompile Include="source\win.cpp" /> <ClCompile Include="source\cryptography.cpp" /> <ClCompile Include="source\main.cpp" /> @@ -142,6 +143,7 @@ <ItemGroup> <ClInclude Include="include\buffer.h" /> <ClInclude Include="include\func.h" /> + <ClInclude Include="include\glob.h" /> <ClInclude Include="include\win.h" /> <ClInclude Include="include\cryptography.h" /> </ItemGroup> diff --git a/Password_manager/Password_manager.vcxproj.filters b/Password_manager/Password_manager.vcxproj.filters index 0186117..9ee8c2a 100644 --- a/Password_manager/Password_manager.vcxproj.filters +++ b/Password_manager/Password_manager.vcxproj.filters @@ -30,6 +30,9 @@ <ClCompile Include="source\buffer.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="source\glob.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="include\win.h"> @@ -44,5 +47,8 @@ <ClInclude Include="include\func.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="include\glob.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file diff --git a/Password_manager/include/glob.h b/Password_manager/include/glob.h new file mode 100644 index 0000000..89dfe74 --- /dev/null +++ b/Password_manager/include/glob.h @@ -0,0 +1,13 @@ +#pragma once + + +enum class Glob_Result { + OOM_ERROR, + ENCODING_ERROR, + SYNTAX_ERROR, + UNMATCHED, + MATCHED, +} ; + +// https://github.com/tsoding/glob.h +Glob_Result glob(const char* pattern, const char* text); \ No newline at end of file diff --git a/Password_manager/source/func.cpp b/Password_manager/source/func.cpp index b226bcd..98751f4 100644 --- a/Password_manager/source/func.cpp +++ b/Password_manager/source/func.cpp @@ -1,4 +1,5 @@ #include "func.h" +#include "glob.h" Pass* find_password(Buffer* buff, char* label) { @@ -6,7 +7,7 @@ Pass* find_password(Buffer* buff, char* label) for (int i = 0; i < buff->taken / sizeof(Pass); i++) { - if (!strcmp(passwords[i].label, label)) + if (glob(label, passwords[i].label) == Glob_Result::MATCHED) { return &passwords[i]; } @@ -66,7 +67,7 @@ void print_usage() printf_s(" Note: <label> max len %d char\n\n", MAX_STRING_SIZE); printf_s(" Flags:\n\n"); printf_s(" -h \t print this message\n"); - printf_s(" <label> \t get password of this label\n"); + printf_s(" <label> \t get password of this label can use GLOB\n"); printf_s(" -g <label> \t generate or update password of this label\n"); printf_s(" -d <label> \t delete password of this label\n"); printf_s(" -i <label> \t input password for this label max %d char\n", MAX_STRING_SIZE); diff --git a/Password_manager/source/glob.cpp b/Password_manager/source/glob.cpp new file mode 100644 index 0000000..1b94528 --- /dev/null +++ b/Password_manager/source/glob.cpp @@ -0,0 +1,94 @@ +#include "glob.h" + +Glob_Result glob(const char* pattern, const char* text) +{ + while (*pattern != '\0' && *text != '\0') { + switch (*pattern) { + case '?': { + pattern += 1; + text += 1; + } + break; + + case '*': { + Glob_Result result = glob(pattern + 1, text); + if (result != Glob_Result::UNMATCHED) return result; + text += 1; + } + break; + + case '[': { + bool matched = false; + bool negate = false; + + pattern += 1; // skipping [ + if (*pattern == '\0') return Glob_Result::SYNTAX_ERROR; // unclosed [ + + if (*pattern == '!') { + negate = true; + pattern += 1; + if (*pattern == '\0') return Glob_Result::SYNTAX_ERROR; // unclosed [ + } + + char prev = *pattern; + matched |= prev == *text; + pattern += 1; + + while (*pattern != ']' && *pattern != '\0') { + switch (*pattern) { + case '-': { + pattern += 1; + switch (*pattern) { + case ']': + matched |= '-' == *text; + break; + case '\0': + return Glob_Result::SYNTAX_ERROR; // unclosed [ + default: { + matched |= prev <= *text && *text <= *pattern; + prev = *pattern; + pattern += 1; + } + } + } + break; + default: { + prev = *pattern; + matched |= prev == *text; + pattern += 1; + } + } + } + + if (*pattern != ']') return Glob_Result::SYNTAX_ERROR; // unclosed [ + if (negate) matched = !matched; + if (!matched) return Glob_Result::UNMATCHED; + + pattern += 1; + text += 1; + } + break; + + case '\\': + pattern += 1; + if (*pattern == '\0') return Glob_Result::SYNTAX_ERROR; // unfinished escape + // fallthrough + default: { + if (*pattern == *text) { + pattern += 1; + text += 1; + } + else { + return Glob_Result::UNMATCHED; + } + } + } + } + + if (*text == '\0') { + while (*pattern == '*') pattern += 1; + if (*pattern == '\0') return Glob_Result::MATCHED; + } + + return Glob_Result::UNMATCHED; +} \ No newline at end of file