feat(导入导出): 支持同时导出和导入系统与用户PATH变量

- 重构导出功能,将系统变量和用户变量合并到单个JSON文件中
- 重构导入功能,支持解析包含系统变量和用户变量的JSON文件
- 在导入时提供选项让用户选择导入目标(系统变量、用户变量或全部)
- 更新UI交互逻辑,适配新的导入导出数据结构
- 改进JSON文件格式,包含版本信息和导出时间戳
This commit is contained in:
2026-03-26 12:16:48 +08:00
parent 55ff64b92d
commit 8767271e96
3 changed files with 237 additions and 122 deletions
+155 -100
View File
@@ -58,39 +58,56 @@ static char *escape_json_string(const char *str)
return result;
}
// 导出 PATH 到 JSON 文件
int export_paths_to_file(const StringList *list, const char *filepath, int is_system)
// 导出路径数据到 JSON 文件
int export_paths_to_file(const ExportData *data, const char *filepath)
{
if (!list || !filepath)
if (!data || !filepath)
return -1;
FILE *fp = fopen(filepath, "w, ccs=UTF-8");
FILE *fp = fopen(filepath, "w");
if (!fp)
return -1;
fprintf(fp, "\xEF\xBB\xBF");
char datetime[64];
get_current_datetime(datetime, sizeof(datetime));
fprintf(fp, "{\n");
fprintf(fp, " \"version\": \"%s\",\n", EXPORT_VERSION);
fprintf(fp, " \"type\": \"%s\",\n", is_system ? "SYSTEM" : "USER");
fprintf(fp, " \"type\": \"ALL\",\n");
fprintf(fp, " \"exported\": \"%s\",\n", datetime);
fprintf(fp, " \"paths\": [\n");
for (int i = 0; i < list->count; i++)
fprintf(fp, " \"system\": [\n");
for (int i = 0; i < data->system.count; i++)
{
if (list->items[i])
if (data->system.items[i])
{
char *escaped = escape_json_string(list->items[i]);
char *escaped = escape_json_string(data->system.items[i]);
if (escaped)
{
fprintf(fp, " \"%s\"%s\n", escaped, (i < list->count - 1) ? "," : "");
fprintf(fp, " \"%s\"%s\n", escaped, (i < data->system.count - 1) ? "," : "");
free(escaped);
}
}
}
fprintf(fp, " ],\n");
fprintf(fp, " \"user\": [\n");
for (int i = 0; i < data->user.count; i++)
{
if (data->user.items[i])
{
char *escaped = escape_json_string(data->user.items[i]);
if (escaped)
{
fprintf(fp, " \"%s\"%s\n", escaped, (i < data->user.count - 1) ? "," : "");
free(escaped);
}
}
}
fprintf(fp, " ]\n");
fprintf(fp, "}\n");
fclose(fp);
@@ -112,7 +129,7 @@ static void trim_whitespace(char *str)
memmove(str, start, strlen(start) + 1);
}
// 检查是否为注释行或空行
// 检查字符串是否为注释行或空行
static int is_comment_or_empty(const char *line)
{
while (*line == ' ' || *line == '\t')
@@ -124,118 +141,156 @@ static int is_comment_or_empty(const char *line)
return 0;
}
// 检查是否为 JSON 文件
// 检查文件是否为 JSON 格式
static int is_json_file(const char *filepath)
{
const char *ext = strrchr(filepath, '.');
return ext && strcasecmp(ext, ".json") == 0;
}
// 从文件导入 PATH
int import_paths_from_file(const char *filepath, StringList *list)
// 从文件导入 PATH (返回是否包含全部格式)
int import_paths_from_file(const char *filepath, ExportData *data)
{
if (!filepath || !list)
if (!filepath || !data)
return -1;
if (is_json_file(filepath))
init_string_list(&data->system);
init_string_list(&data->user);
if (!is_json_file(filepath))
{
FILE *fp = fopen(filepath, "r, ccs=UTF-8");
FILE *fp = fopen(filepath, "rb");
if (!fp)
return -1;
clear_string_list(list);
char buffer[8192];
int in_paths = 0;
int depth = 0;
int in_string = 0;
char path_buffer[4096];
int path_len = 0;
while (fgets(buffer, sizeof(buffer), fp))
{
char *p = buffer;
while (*p)
{
if (*p == '"' && (p == buffer || *(p - 1) != '\\'))
{
in_string = !in_string;
}
else if (in_string && *p == '\\')
{
p++;
if (*p)
{
if (*p == 'n')
*p = '\n';
else if (*p == 'r')
*p = '\r';
else if (*p == 't')
*p = '\t';
}
}
else if (!in_string)
{
if (*p == '{' || *p == '[')
depth++;
else if (*p == '}' || *p == ']')
depth--;
else if (*p == ':')
in_paths = (depth == 1);
else if (in_paths && depth == 2 && *p == '"')
{
path_len = 0;
p++;
while (*p && path_len < (int)sizeof(path_buffer) - 1)
{
if (*p == '"' && *(p - 1) != '\\')
break;
if (*p == '\\' && *(p + 1))
{
p++;
if (*p == 'n')
*p = '\n';
else if (*p == 'r')
*p = '\r';
else if (*p == 't')
*p = '\t';
}
path_buffer[path_len++] = *p++;
}
if (path_len > 0)
{
path_buffer[path_len] = '\0';
add_string_list(list, path_buffer);
}
}
}
p++;
}
}
fclose(fp);
return 0;
}
else
{
FILE *fp = fopen(filepath, "r, ccs=UTF-8");
if (!fp)
return -1;
clear_string_list(list);
StringList list;
init_string_list(&list);
char line[4096];
while (fgets(line, sizeof(line), fp))
{
trim_whitespace(line);
if (is_comment_or_empty(line))
continue;
add_string_list(list, line);
add_string_list(&list, line);
}
fclose(fp);
data->system = list;
return 0;
}
FILE *fp = fopen(filepath, "rb");
if (!fp)
return -1;
char buffer[8192];
int in_system = 0;
int in_user = 0;
int depth = 0;
int in_string = 0;
char path_buffer[4096];
int path_len = 0;
while (fgets(buffer, sizeof(buffer), fp))
{
char *p = buffer;
while (*p)
{
if (*p == '"' && (p == buffer || *(p - 1) != '\\'))
{
in_string = !in_string;
}
else if (in_string && *p == '\\')
{
p++;
if (*p)
{
if (*p == 'n')
*p = '\n';
else if (*p == 'r')
*p = '\r';
else if (*p == 't')
*p = '\t';
}
}
else if (!in_string)
{
if (*p == '{' || *p == '[')
depth++;
else if (*p == '}' || *p == ']')
depth--;
else if (depth == 1 && *p == '"')
{
if (strncmp(p, "\"system\"", 8) == 0)
{
in_system = 1;
in_user = 0;
}
else if (strncmp(p, "\"user\"", 6) == 0)
{
in_user = 1;
in_system = 0;
}
}
else if (in_system && depth == 2 && *p == '"')
{
path_len = 0;
p++;
while (*p && path_len < (int)sizeof(path_buffer) - 1)
{
if (*p == '"' && *(p - 1) != '\\')
break;
if (*p == '\\' && *(p + 1))
{
p++;
if (*p == 'n')
*p = '\n';
else if (*p == 'r')
*p = '\r';
else if (*p == 't')
*p = '\t';
}
path_buffer[path_len++] = *p++;
}
if (path_len > 0)
{
path_buffer[path_len] = '\0';
add_string_list(&data->system, path_buffer);
}
}
else if (in_user && depth == 2 && *p == '"')
{
path_len = 0;
p++;
while (*p && path_len < (int)sizeof(path_buffer) - 1)
{
if (*p == '"' && *(p - 1) != '\\')
break;
if (*p == '\\' && *(p + 1))
{
p++;
if (*p == 'n')
*p = '\n';
else if (*p == 'r')
*p = '\r';
else if (*p == 't')
*p = '\t';
}
path_buffer[path_len++] = *p++;
}
if (path_len > 0)
{
path_buffer[path_len] = '\0';
add_string_list(&data->user, path_buffer);
}
}
}
p++;
}
}
fclose(fp);
return 0;
}