浏览代码

feat: 添加从文件读取账户信息的功能

可以从文件中一次性读取多条账户信息
SongZihuan 3 年之前
父节点
当前提交
19a6644329
共有 3 个文件被更改,包括 293 次插入28 次删除
  1. 282 27
      main.c
  2. 10 0
      main.h
  3. 1 1
      passwd_file.c

+ 282 - 27
main.c

@@ -1,6 +1,7 @@
 #include "main.h"
 #include "argument.h"
 #include <stdio.h>
+#include <ctype.h>
 
 #ifndef INCLUDE_KEY
 char *key = NULL;
@@ -9,14 +10,17 @@ char *key = INCLUDE_KEY;
 #endif
 
 #define TIPS_SIZE (30)
+#define IO_READ_SIZE (20)
+#define PATH_SIZE (100)
 
-char *name = NULL;
+char *program_name = NULL;
 struct arg_define arg[] = {
         {.ch='v', .name="version", .flat='v', .argument=no_argument},
         {.ch='h', .name="help", .flat='h', .argument=no_argument},
         {.ch='s', .name="set-pw", .flat='s', .argument=no_argument},
         {.ch='g', .name="get-pw", .flat='g', .argument=no_argument},
         {.ch='t', .name="tips", .flat='t', .argument=no_argument},
+        {.ch='f', .name="file", .flat='f', .argument=can_argument},
 #ifdef INCLUDE_KEY
         {.ch='c', .name="check-key", .flat='c', .argument=must_argument},
 #else
@@ -28,12 +32,15 @@ struct arg_define arg[] = {
 #endif
         {.ch=0},
 };
+
 enum {
     no = 0,
     set_pw,
     get_pw,
     del_pw,
+    set_pw_file,
 } work = no;
+
 bool in_file = false;  // 是否在文件中工作
 bool print_passwd = false;  // 是否打印content
 bool del_old = false;
@@ -41,6 +48,7 @@ bool del_old = false;
 void printVersion(void);
 void printHelp(void);
 bool setPassWd(void);
+bool setPassWdFromFile(char *path);
 bool getPassWd(void);
 bool delPassWd(void);
 char *getTipsFromStdin(void);
@@ -48,12 +56,13 @@ char *getTipsFromStdin(void);
 int main(int argc, char **argv) {
     bool print_tips = false;
     bool set_tips = false;
+    char *read_path = NULL;
 
-    printf("Welecome to use H-Password.\n");
+    printf("Welcome to use H-Password.\n");
 #ifdef INCLUDE_KEY
     printf("Exclusive custom user: %s\n", UserName);
 #endif
-    name = argv[0];
+    program_name = argv[0];
     randomInit();
     initOpt(true, argc, argv, arg);
 
@@ -95,6 +104,25 @@ int main(int argc, char **argv) {
             case 'i':
                 in_file = true;
                 break;
+            case 'f':
+                if (work != no)
+                    goto what_do;
+                work = set_pw_file;
+                if (opt_val == NULL || strcmp(opt_val, "stdin") == 0) {
+                    char *enter_flat;
+                    read_path = calloc(PATH_SIZE + 1, sizeof(char));
+                    printf("Enter the file path[< %d]:", PATH_SIZE);
+                    fgets(read_path, PATH_SIZE + 1, stdin);
+                    if ((enter_flat = strchr(read_path, '\n')) == NULL) {
+                        free(enter_flat);
+                        fprintf(stdin, "Path too long[> %d].\n", PATH_SIZE);
+                        exit(EXIT_FAILURE);
+                    }
+                } else {
+                    read_path = calloc(strlen(opt_val) + 1, sizeof(char));
+                    strcpy(read_path, opt_val);
+                }
+                break;
             case 't':
 #ifdef INCLUDE_KEY
                 printf("Tips: %s\n", KeyTips);
@@ -159,6 +187,8 @@ int main(int argc, char **argv) {
 
         if (set_tips) {
             char *tips = getTipsFromStdin();
+            if (tips == NULL)
+                exit(EXIT_FAILURE);
             setFileTips(tips);
             free(tips);
         }
@@ -179,13 +209,16 @@ int main(int argc, char **argv) {
             exit(EXIT_FAILURE);
         }
         status = delPassWd();
-    }
+    } else if (work == set_pw_file)
+        status = setPassWdFromFile(read_path);
     else if (in_file && print_passwd)
         printContent();
 
 #ifndef INCLUDE_KEY
     free(key);
 #endif
+
+    free(read_path);
     if (!status)
         return EXIT_FAILURE;
 
@@ -193,6 +226,7 @@ int main(int argc, char **argv) {
         if (!writePasswdFile())  // 写入数据
             return EXIT_FAILURE;
     }
+
     return EXIT_SUCCESS;
 
     little_exit:
@@ -203,11 +237,11 @@ int main(int argc, char **argv) {
 }
 
 void printVersion(void) {
-    printf("%s Version:\n%s\n%s\n", name, VERSION, VERSION_INFO);
+    printf("%s Version:\n%s\n%s\n", program_name, VERSION, VERSION_INFO);
 }
 
 void printHelp(void) {
-    printf("Usage: %s <[option]..> [key]\n", name);
+    printf("Usage: %s <[option]..> [key]\n", program_name);
     printf("Option: \n");
     printf(" -v --version       Show version.\n");
     printf(" -h --help          Show help.\n");
@@ -248,19 +282,181 @@ void printHelp(void) {
     printf("Tips: [0 - %d]\n\n", TIPS_SIZE);
 
     printf("Name origin:\n");
-    printf("I'm super Huan. H in h-password is Huan in superhuan. \n"
+    printf("I'm super Huan. H in h-password is Huan in SuperHuan. \n"
            "Password means that the software is password software.\n\n");
 
 }
 
-#define READ_WORD(key, len, key_name, re) do { printf("Please Enter The " key_name ":"); \
-    (key) = calloc((len) + 10, sizeof(char )); \
-    fgets((key), (len) + 10, stdin); \
-    if (strchr((key), '\n') == NULL) { \
-        fprintf(stderr, key_name " too long for stdin.\n"); \
-        goto re; \
-    } else {*strchr((key), '\n') = 0;} \
-}while(0)
+#define GRAMMAR_INFO    "File format:\n" \
+                        "[account] [passwd] \"note\" \"name\"\n"
+
+#define INVALID_INFO    "Invalid file format\n" \
+                         GRAMMAR_INFO \
+                        "Note: Only three Spaces are allowed, \"name\" is not required.\n"
+
+static char *readNoteFromFile(FILE *fp) {  // 读取note和name
+    char *buf = calloc(IO_READ_SIZE + 1, sizeof(char ));
+    int size = IO_READ_SIZE;
+    int index = 0;
+    int ch;
+
+    if ((ch = getc(fp)) != '"') {
+        ungetc(ch, fp);
+        fprintf(stderr, "You need to start and end with a quote.\n");
+        fprintf(stderr, GRAMMAR_INFO);
+        return false;
+    }
+
+    while ((ch = getc(fp)) != '"') {
+        if (ch == '\n' || ch == EOF) {
+            fprintf(stderr, INVALID_INFO);
+            return NULL;
+        }
+
+        buf[index] = (char)ch;
+        index++;
+
+        if (index == size) {
+            char *new_buf = calloc(size + IO_READ_SIZE + 1, sizeof(char ));
+            strcpy(new_buf, buf);
+            free(buf);
+            buf = new_buf;
+        }
+    }
+
+    return buf;
+}
+
+
+static char *readAccountFromFile(FILE *fp) {  // 读取账号或者密码的函数
+    char *buf = calloc(IO_READ_SIZE + 1, sizeof(char ));
+    int size = IO_READ_SIZE;
+    int index = 0;
+    int ch;
+
+    while ((ch = getc(fp)) != ' ') {
+        if (ch == '\n' || ch == EOF) {
+            fprintf(stderr, INVALID_INFO);
+            return NULL;
+        }
+
+        buf[index] = (char)ch;
+        index++;
+
+        if (index == size) {
+            char *new_buf = calloc(size + IO_READ_SIZE + 1, sizeof(char ));
+            strcpy(new_buf, buf);
+            free(buf);
+            buf = new_buf;
+        }
+    }
+
+    return buf;
+}
+
+bool setPassWdFromFile(char *path) {
+    FILE *fp = fopen(path, "r");
+    if (fp == NULL) {
+        fprintf(stderr, "File not fount: %s\n", path);
+        return false;
+    }
+
+    int ch;
+    while ((ch = getc(fp)) != EOF) {
+        char *account = NULL;
+        char *passwd = NULL;
+        char *note = NULL;
+        char *in_file_name = NULL;
+        char *passwd_str = NULL;
+
+        ungetc(ch, fp);
+        account = readAccountFromFile(fp);
+        if (account == NULL)
+            goto ERROR1;
+
+        passwd = readAccountFromFile(fp);
+        if (passwd == NULL)
+            goto ERROR2;
+
+        note = readNoteFromFile(fp);
+        if (note == NULL)
+            goto ERROR3;
+
+        if ((ch = getc(fp)) == ' ') {
+            in_file_name = readNoteFromFile(fp);
+            if (in_file_name == NULL)
+                goto ERROR4;
+            ch = getc(fp);
+        }
+
+        if (ch == '\r')
+            ch = getc(fp);  // 跳过/r
+
+        if (ch != '\n' && ch != EOF) {
+            fprintf(stderr, INVALID_INFO);
+            goto ERROR5;
+        }
+
+        if (in_file_name == NULL)
+            in_file_name = note;  // 指针复制
+
+        passwd_str = makePasswordString(account, passwd, note);
+        if (passwd_str == NULL)
+            goto ERROR5;
+
+        printf("********************\n");
+        fflush(stdout);
+        printPasswdStr(account, passwd, note, passwd_str);
+
+        if (in_file) {
+            if (del_old)
+                delContentByName(in_file_name);
+
+            addContent(in_file_name, passwd_str);
+            printf("The label has been written to the file. (name: %s)\n", in_file_name);
+        }
+
+        free(passwd_str);
+        if (in_file_name != note)
+            free(in_file_name);
+        free(account);
+        free(passwd);
+        free(note);
+        continue;
+        
+        ERROR5:
+        if (in_file_name != note)
+            free(in_file_name);
+        ERROR4: free(note);
+        ERROR3: free(passwd);
+        ERROR2: free(account);
+        fclose(fp);
+        ERROR1: return false;
+    }
+
+    if (print_passwd)
+        printContent();
+    fclose(fp);
+    return true;
+}
+
+#undef INVALID_INFO
+#undef GRAMMAR_INFO
+
+static bool readWord(char **word, int len, char *word_name) {
+    char *ch;
+    printf("Please Enter %s :", word_name);
+    *word = calloc(len + 10, sizeof(char));
+    fgets(*word, len + 10, stdin);
+
+    if ((ch = strchr((*word), '\n')) == ((void *) 0)) {
+        fprintf(stderr, "%s too long for stdin.\n", word_name);
+        return false;
+    }
+
+    *ch = 0;
+    return true;
+}
 
 bool setPassWd(void) {
     char *account = NULL;
@@ -269,8 +465,11 @@ bool setPassWd(void) {
     char *in_file_name = NULL;
     char *passwd_str = NULL;
 
-    READ_WORD(account, 100, "Your account", ERROR1);
-    READ_WORD(passwd, 100, "Your password", ERROR2);
+    if (!readWord(&account, 100, "Your Account"))
+        goto ERROR1;
+
+    if (!readWord(&passwd, 100, "Your Password"))
+        goto ERROR2;
 
     if (*passwd == 0) {  // 未输入密码内容
         free(passwd);
@@ -278,10 +477,13 @@ bool setPassWd(void) {
         printf("random password: '%s'\n", passwd);
     }
 
-    READ_WORD(note, 100, "Your note", ERROR3);
+    if (!readWord(&note, 100, "Your note"))
+        goto ERROR3;
 
-    if (in_file)
-        READ_WORD(in_file_name, 100, "Account name", ERROR4);
+    if (in_file) {
+        if (!readWord(&in_file_name, 100, "Account name"))
+            goto ERROR4;
+    }
 
     passwd_str = makePasswordString(account, passwd, note);
     if (passwd_str == NULL)
@@ -329,7 +531,9 @@ bool getPassWd(void) {
         printContent();
 
     if (in_file && !print_passwd) {
-        READ_WORD(in_file_name, 50, "Your Label", ERROR1);
+        if (readWord(&in_file_name, 50, "Password Name"))
+            goto ERROR1;
+
         passwd_str = findContent(in_file_name);
         if (passwd_str == NULL) {
             fprintf(stderr, "name [%s] not found.", in_file_name);
@@ -337,8 +541,10 @@ bool getPassWd(void) {
             return false;
         }
         free(in_file_name);
-    } else
-        READ_WORD(passwd_str, 200, "Your Label", ERROR1);
+    } else {
+        if (readWord(&passwd_str, 200, "Your Label"))
+            goto ERROR1;
+    }
 
     if (!getInfoFromPasswordString(passwd_str, &account, &passwd, &note))
         goto ERROR2;
@@ -355,6 +561,57 @@ bool getPassWd(void) {
     ERROR1: return false;
 }
 
+static int charToInt(char ch) {
+    switch (ch) {
+        case '0': return 0;
+        case '1': return 1;
+        case '2': return 2;
+        case '3': return 3;
+        case '4': return 4;
+        case '5': return 5;
+        case '6': return 6;
+        case '7': return 7;
+        case '8': return 8;
+        case '9': return 9;
+        default: return -1;
+    }
+}
+
+static bool getNumber(int *num) {
+    int ch;
+    int re = false;
+    bool negative = false;  // 是否为负数
+    int the_num = 0;
+
+    while (isspace(ch = getc(stdin))) {  // 清除空格
+        if (ch == '\n') {
+            ungetc(ch, stdin);
+            return false;
+        }
+    }
+
+    if (ch == '-') {
+        negative = true;
+        ch = getc(stdin);
+    }
+
+    for (; isalnum(ch); ch = getc(stdin)) {
+        re = true;
+        int n = charToInt((char) ch);
+        if (n == -1)
+            return false;
+        the_num = the_num * 10 + n;
+    }
+
+    ungetc(ch, stdin);
+
+    if (!re)
+        return false;
+
+    *num = (negative? -the_num : the_num);
+    return true;
+}
+
 bool delPassWd(void) {
     int i;
     int max = -1;
@@ -364,13 +621,11 @@ bool delPassWd(void) {
         printContent();
 
     printf("Enter the serial number of the label you want to delete (starting from 0)\n"
-           "Enter -1. A maximum of %d parameters can be entered.\n", DEL_CONTENT_SZIE);
+           "A maximum of %d parameters can be entered.\n", DEL_CONTENT_SZIE);
 
     for (i = 0; i < DEL_CONTENT_SZIE; i++) {
         int index = 0;
-        if (scanf( "%d", &index) != 1)
-            break;
-        if (index == -1)
+        if (!getNumber(&index))
             break;
         if (index <= max) {
             printf("Please enter in descending order, skipped %d.", index);

+ 10 - 0
main.h

@@ -22,6 +22,16 @@
 
 #define DEL_CONTENT_SZIE (20)
 
+static void *s_calloc(size_t n, size_t s) {
+   void *new = calloc(n, s);
+   if (new == NULL)
+       exit(EXIT_FAILURE);
+   return new;
+}
+
+#define free(p) (((p) != NULL ? free(p) : NULL), ((p) = NULL))
+#define calloc(n, s) (s_calloc(n, s))
+
 struct MD5_CTX {
     unsigned int count[2];
     unsigned int state[4];

+ 1 - 1
passwd_file.c

@@ -300,7 +300,7 @@ void printContent(void) {
 #endif
     printf("--------------------\n");
     for (int i = 0; i < content_size; i++, con = con->next)
-        printf("%d. %s : name: %s, label: %s\n", i, con->date, con->name, con->passwd_str);
+        printf("%d. %s : program_name: %s, label: %s\n", i, con->date, con->name, con->passwd_str);
     printf("********************\n");
 }