Add files via upload
This commit is contained in:
969
source/sfv_md5/verify.c
Normal file
969
source/sfv_md5/verify.c
Normal file
@@ -0,0 +1,969 @@
|
||||
// verify.c
|
||||
// Copyright : 2022-02-25 Yutaka Sawada
|
||||
// License : The MIT license
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600 // Windows Vista or later
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crc.h"
|
||||
#include "verify.h"
|
||||
#include "ini.h"
|
||||
#include "phmd5.h"
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
// CRC-32 を比較する
|
||||
// 0 = ファイルが存在して完全である
|
||||
// 1 = ファイルが存在しない
|
||||
// 2 = ファイルが破損してる
|
||||
static int file_crc32_check(
|
||||
int num,
|
||||
char *ascii_name,
|
||||
wchar_t *uni_name,
|
||||
wchar_t *file_path,
|
||||
unsigned int crc2)
|
||||
{
|
||||
unsigned char buf[IO_SIZE];
|
||||
int len, off, bad_flag;
|
||||
unsigned int crc, time_last, meta_data[7];
|
||||
__int64 file_size = 0, file_left;
|
||||
HANDLE hFile;
|
||||
|
||||
prog_last = -1;
|
||||
time_last = GetTickCount() / UPDATE_TIME; // 時刻の変化時に経過を表示する
|
||||
wcscpy(file_path, base_dir);
|
||||
// 先頭の「..\」を許可してるので、基準ディレクトリから上に遡る。
|
||||
len = base_len - 1;
|
||||
off = 0;
|
||||
while ((uni_name[off] == '.') && (uni_name[off + 1] == '.') && (uni_name[off + 2] == '\\')){
|
||||
off += 3;
|
||||
file_path[len] = 0;
|
||||
while (file_path[len] != '\\'){
|
||||
file_path[len] = 0;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
wcscat(file_path, uni_name + off);
|
||||
|
||||
// 読み込むファイルを開く
|
||||
hFile = CreateFile(file_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE){
|
||||
bad_flag = 1; // 消失は記録しない
|
||||
} else {
|
||||
bad_flag = check_ini_state(num, meta_data, hFile);
|
||||
memcpy(&file_size, meta_data, 8);
|
||||
if (bad_flag == -2){ // 記録が無い場合 (属性取得エラーは不明にする)
|
||||
file_left = file_size;
|
||||
crc = 0xFFFFFFFF; // 初期化
|
||||
while (file_left > 0){
|
||||
len = IO_SIZE;
|
||||
if (file_left < IO_SIZE)
|
||||
len = (int)file_left;
|
||||
if (!ReadFile(hFile, buf, len, &bad_flag, NULL) || (len != bad_flag))
|
||||
break; // 読み取りエラーは必ず破損になる
|
||||
file_left -= len;
|
||||
// CRC-32 を更新する
|
||||
crc = crc_update(crc, buf, len);
|
||||
|
||||
// 経過表示
|
||||
if (GetTickCount() / UPDATE_TIME != time_last){
|
||||
if (print_progress_file((int)(((file_size - file_left) * 1000) / file_size), uni_name)){
|
||||
CloseHandle(hFile);
|
||||
return 2;
|
||||
}
|
||||
time_last = GetTickCount() / UPDATE_TIME;
|
||||
}
|
||||
}
|
||||
crc ^= 0xFFFFFFFF; // 最終処理
|
||||
if ((crc != crc2) || (file_left > 0)){
|
||||
bad_flag = 2; // ハッシュ値が異なる、または途中まで
|
||||
} else {
|
||||
bad_flag = 0; // 完全
|
||||
}
|
||||
write_ini_state(num, meta_data, bad_flag); // 検査結果を記録する、完全か破損
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
switch (bad_flag){
|
||||
case 0:
|
||||
printf("%13I64d Complete : \"%s\"\n", file_size, ascii_name);
|
||||
break;
|
||||
case 1:
|
||||
printf(" 0 Missing : \"%s\"\n", ascii_name);
|
||||
bad_flag = 4 | 8;
|
||||
break;
|
||||
case 2:
|
||||
printf("%13I64d Damaged : \"%s\"\n", file_size, ascii_name);
|
||||
bad_flag = 4;
|
||||
break;
|
||||
default: // IOエラー等
|
||||
printf(" ? Unknown : \"%s\"\n", ascii_name);
|
||||
bad_flag = 4;
|
||||
break;
|
||||
}
|
||||
fflush(stdout);
|
||||
return bad_flag;
|
||||
}
|
||||
|
||||
// SFV ファイル
|
||||
int verify_sfv(
|
||||
char *ascii_buf,
|
||||
wchar_t *file_path)
|
||||
{
|
||||
wchar_t *line_off, uni_buf[MAX_LEN];
|
||||
unsigned int err = 0, rv, line_len, name_len, crc, line_num, num, comment;
|
||||
|
||||
// ファイル数を調べる
|
||||
comment = 0;
|
||||
num = 0;
|
||||
line_num = 1;
|
||||
line_off = text_buf;
|
||||
while (*line_off != 0){ // 一行ずつ処理する
|
||||
line_len = 0;
|
||||
while (line_off[line_len] != 0){ // 改行までを一行とする
|
||||
if (line_off[line_len] == '\n')
|
||||
break;
|
||||
if (line_off[line_len] == '\r')
|
||||
break;
|
||||
line_len++;
|
||||
}
|
||||
// 行の内容が適正か調べる
|
||||
if (line_off[0] == ';'){ // コメント
|
||||
if (((comment & 1) == 0) && (line_len > 8) && (line_len < MAX_LEN)){
|
||||
// クリエイターの表示がまだなら
|
||||
if (wcsncmp(line_off, L"; Generated by ", 15) == 0){ // WIN-SFV32, SFV32nix
|
||||
wcsncpy(uni_buf, line_off + 15, line_len - 15);
|
||||
uni_buf[line_len - 15] = 0;
|
||||
comment |= 1;
|
||||
} else if (wcsncmp(line_off, L"; Using ", 8) == 0){
|
||||
wcsncpy(uni_buf, line_off + 8, line_len - 8);
|
||||
uni_buf[line_len - 8] = 0;
|
||||
comment |= 1; // 同一行を二度表示しない
|
||||
}
|
||||
if (comment & 1){
|
||||
uni_buf[COMMENT_LEN - 1] = 0; // 表示する文字数を制限する
|
||||
utf16_to_cp(uni_buf, ascii_buf, COMMENT_LEN * 3, cp_output);
|
||||
printf("Creator : %s\n", ascii_buf);
|
||||
comment |= 4;
|
||||
}
|
||||
}
|
||||
if (((comment & 6) == 0) && (line_len < MAX_LEN)){
|
||||
// 最初のコメントの表示がまだなら
|
||||
crc = 1;
|
||||
while (crc < line_len){
|
||||
if (line_off[crc] != ' ')
|
||||
break;
|
||||
crc++;
|
||||
}
|
||||
if (crc < line_len){
|
||||
wcsncpy(uni_buf, line_off + crc, line_len - crc);
|
||||
uni_buf[line_len - crc] = 0;
|
||||
uni_buf[COMMENT_LEN - 1] = 0; // 表示する文字数を制限する
|
||||
utf16_to_cp(uni_buf, ascii_buf, COMMENT_LEN * 3, cp_output);
|
||||
printf("Comment : %s\n", ascii_buf);
|
||||
}
|
||||
comment |= 2; // 「;」だけの行も認識する
|
||||
}
|
||||
comment &= ~4; // bit 4 を消す
|
||||
} else if ((line_len > 9) && (line_off[line_len - 9] == ' ') // CRC の前がスペース
|
||||
&& (base16_len(line_off + (line_len - 8)) == 8)){ // 16進数で8文字
|
||||
// ファイル名
|
||||
name_len = line_len - 9;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
while (line_off[name_len - 1] == ' ')
|
||||
name_len--;
|
||||
// ファイル名の前後が「"」で囲まれてる場合は取り除く
|
||||
if ((line_off[0] == '"') && (line_off[name_len - 1] == '"')){
|
||||
name_len -= 2;
|
||||
wcsncpy(uni_buf, line_off + 1, name_len);
|
||||
} else {
|
||||
wcsncpy(uni_buf, line_off, name_len);
|
||||
}
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv > 1){
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
if (rv == 16){
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 浄化できないファイル名
|
||||
} else if ((rv & 6) == 0){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" is invalid\n", line_num, ascii_buf);
|
||||
} else {
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" was sanitized\n", line_num, ascii_buf);
|
||||
}
|
||||
}
|
||||
if (rv != 16)
|
||||
file_num++;
|
||||
} else {
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 長すぎるファイル名
|
||||
}
|
||||
} else if (line_len > 0){
|
||||
//printf("line %d is invalid\n", line_num);
|
||||
num++; // 内容が認識できない行
|
||||
}
|
||||
// 次の行へ
|
||||
line_off += line_len;
|
||||
if (*line_off == '\n')
|
||||
line_off++;
|
||||
if (*line_off == '\r'){
|
||||
line_off++;
|
||||
if (*line_off == '\n') // 「\r\n」を一つの改行として扱う
|
||||
line_off++;
|
||||
}
|
||||
line_num++;
|
||||
}
|
||||
if (comment & 8)
|
||||
printf("\n");
|
||||
// チェックサム・ファイルの状態
|
||||
if (num == 0){
|
||||
printf("Status : Good\n");
|
||||
} else {
|
||||
printf("Status : Damaged\n");
|
||||
err |= 16; // 後で 256に変更する
|
||||
}
|
||||
if (file_num == 0){
|
||||
printf("valid file is not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\nInput File list : %d\n", file_num);
|
||||
printf(" CRC-32 : Filename\n");
|
||||
fflush(stdout);
|
||||
line_off = text_buf;
|
||||
while (*line_off != 0){ // 一行ずつ処理する
|
||||
line_len = 0;
|
||||
while (line_off[line_len] != 0){ // 改行までを一行とする
|
||||
if (line_off[line_len] == '\n')
|
||||
break;
|
||||
if (line_off[line_len] == '\r')
|
||||
break;
|
||||
line_len++;
|
||||
}
|
||||
// 行の内容が適正か調べる
|
||||
if ((line_off[0] != ';') && // コメントではない
|
||||
(line_len > 9) && (line_off[line_len - 9] == ' ') // CRC の前がスペース
|
||||
&& (base16_len(line_off + (line_len - 8)) == 8)){ // 16進数で8文字
|
||||
// ファイル名
|
||||
name_len = line_len - 9;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
while (line_off[name_len - 1] == ' ')
|
||||
name_len--;
|
||||
// ファイル名の前後が「"」で囲まれてる場合は取り除く
|
||||
if ((line_off[0] == '"') && (line_off[name_len - 1] == '"')){
|
||||
name_len -= 2;
|
||||
wcsncpy(uni_buf, line_off + 1, name_len);
|
||||
} else {
|
||||
wcsncpy(uni_buf, line_off, name_len);
|
||||
}
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// CRC
|
||||
crc = get_val32h(line_off + (line_len - 8));
|
||||
printf("%08X : \"%s\"\n", crc, ascii_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 次の行へ
|
||||
line_off += line_len;
|
||||
if (*line_off == '\n')
|
||||
line_off++;
|
||||
if (*line_off == '\r'){
|
||||
line_off++;
|
||||
if (*line_off == '\n') // 「\r\n」を一つの改行として扱う
|
||||
line_off++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("\nVerifying Input File :\n");
|
||||
printf(" Size Status : Filename\n");
|
||||
fflush(stdout);
|
||||
if (recent_data != 0){ // 前回の検査結果を使うなら
|
||||
PHMD5 ctx;
|
||||
// チェックサム・ファイル識別用にハッシュ値を計算する
|
||||
Phmd5Begin(&ctx);
|
||||
Phmd5Process(&ctx, (unsigned char *)text_buf, text_len * 2);
|
||||
Phmd5End(&ctx);
|
||||
// 前回の検査結果が存在するか
|
||||
check_ini_file(ctx.hash, text_len);
|
||||
}
|
||||
num = 0;
|
||||
line_off = text_buf;
|
||||
while (*line_off != 0){ // 一行ずつ処理する
|
||||
line_len = 0;
|
||||
while (line_off[line_len] != 0){ // 改行までを一行とする
|
||||
if (line_off[line_len] == '\n')
|
||||
break;
|
||||
if (line_off[line_len] == '\r')
|
||||
break;
|
||||
line_len++;
|
||||
}
|
||||
// 行の内容が適正か調べる
|
||||
if ((line_off[0] != ';') && // コメントではない
|
||||
(line_len > 9) && (line_off[line_len - 9] == ' ') // CRC の前がスペース
|
||||
&& (base16_len(line_off + (line_len - 8)) == 8)){ // 16進数で8文字
|
||||
// ファイル名
|
||||
name_len = line_len - 9;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
while (line_off[name_len - 1] == ' ')
|
||||
name_len--;
|
||||
// ファイル名の前後が「"」で囲まれてる場合は取り除く
|
||||
if ((line_off[0] == '"') && (line_off[name_len - 1] == '"')){
|
||||
name_len -= 2;
|
||||
wcsncpy(uni_buf, line_off + 1, name_len);
|
||||
} else {
|
||||
wcsncpy(uni_buf, line_off, name_len);
|
||||
}
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// CRC
|
||||
crc = get_val32h(line_off + (line_len - 8));
|
||||
rv = file_crc32_check(num, ascii_buf, uni_buf, file_path, crc);
|
||||
if (rv & 3){
|
||||
err = rv;
|
||||
break;
|
||||
}
|
||||
if (rv & 0xC){ // Missing or Damaged
|
||||
err |= rv;
|
||||
err += 0x100;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 次の行へ
|
||||
line_off += line_len;
|
||||
if (*line_off == '\n')
|
||||
line_off++;
|
||||
if (*line_off == '\r'){
|
||||
line_off++;
|
||||
if (*line_off == '\n') // 「\r\n」を一つの改行として扱う
|
||||
line_off++;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
// MD5 を比較する
|
||||
// 0 = ファイルが存在して完全である
|
||||
// 1 = ファイルが存在しない
|
||||
// 2 = ファイルが破損してる
|
||||
static int file_md5_check(
|
||||
int num,
|
||||
char *ascii_name,
|
||||
wchar_t *uni_name,
|
||||
wchar_t *file_path,
|
||||
unsigned char *hash)
|
||||
{
|
||||
unsigned char buf[IO_SIZE];
|
||||
int len, off, bad_flag;
|
||||
unsigned int time_last, meta_data[8];
|
||||
__int64 file_size = 0, file_left;
|
||||
HANDLE hFile;
|
||||
PHMD5 ctx;
|
||||
|
||||
prog_last = -1;
|
||||
time_last = GetTickCount() / UPDATE_TIME; // 時刻の変化時に経過を表示する
|
||||
wcscpy(file_path, base_dir);
|
||||
// 先頭の「..\」を許可してるので、基準ディレクトリから上に遡る。
|
||||
len = base_len - 1;
|
||||
off = 0;
|
||||
while ((uni_name[off] == '.') && (uni_name[off + 1] == '.') && (uni_name[off + 2] == '\\')){
|
||||
off += 3;
|
||||
file_path[len] = 0;
|
||||
while (file_path[len] != '\\'){
|
||||
file_path[len] = 0;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
wcscat(file_path, uni_name + off);
|
||||
//printf("path = \"%S\"\n", file_path);
|
||||
|
||||
// 読み込むファイルを開く
|
||||
hFile = CreateFile(file_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE){
|
||||
bad_flag = 1; // 消失は記録しない
|
||||
} else {
|
||||
bad_flag = check_ini_state(num, meta_data, hFile);
|
||||
memcpy(&file_size, meta_data, 8);
|
||||
if (bad_flag == -2){ // 記録が無い場合 (属性取得エラーは不明にする)
|
||||
file_left = file_size;
|
||||
Phmd5Begin(&ctx); // 初期化
|
||||
while (file_left > 0){
|
||||
len = IO_SIZE;
|
||||
if (file_left < IO_SIZE)
|
||||
len = (int)file_left;
|
||||
if (!ReadFile(hFile, buf, len, &bad_flag, NULL) || (len != bad_flag))
|
||||
break; // 読み取りエラーは必ず破損になる
|
||||
file_left -= len;
|
||||
// MD5 を更新する
|
||||
Phmd5Process(&ctx, buf, len);
|
||||
|
||||
// 経過表示
|
||||
if (GetTickCount() / UPDATE_TIME != time_last){
|
||||
if (print_progress_file((int)(((file_size - file_left) * 1000) / file_size), uni_name)){
|
||||
CloseHandle(hFile);
|
||||
return 2;
|
||||
}
|
||||
time_last = GetTickCount() / UPDATE_TIME;
|
||||
}
|
||||
}
|
||||
Phmd5End(&ctx); // 最終処理
|
||||
// printf("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X %d\n",
|
||||
// ctx.hash[0], ctx.hash[1], ctx.hash[2], ctx.hash[3], ctx.hash[4], ctx.hash[5], ctx.hash[6], ctx.hash[7],
|
||||
// ctx.hash[8], ctx.hash[9], ctx.hash[10], ctx.hash[11], ctx.hash[12], ctx.hash[13], ctx.hash[14], ctx.hash[15]);
|
||||
if ((memcmp(hash, ctx.hash, 16) != 0) || (file_left > 0)){
|
||||
bad_flag = 2; // ハッシュ値が異なる、または途中まで
|
||||
} else {
|
||||
bad_flag = 0; // 完全
|
||||
}
|
||||
write_ini_state(num, meta_data, bad_flag); // 検査結果を記録する、完全か破損
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
switch (bad_flag){
|
||||
case 0:
|
||||
printf("%13I64d Complete : \"%s\"\n", file_size, ascii_name);
|
||||
break;
|
||||
case 1:
|
||||
printf(" 0 Missing : \"%s\"\n", ascii_name);
|
||||
bad_flag = 4 | 8;
|
||||
break;
|
||||
case 2:
|
||||
printf("%13I64d Damaged : \"%s\"\n", file_size, ascii_name);
|
||||
bad_flag = 4;
|
||||
break;
|
||||
default: // IOエラー等
|
||||
printf(" ? Unknown : \"%s\"\n", ascii_name);
|
||||
bad_flag = 4;
|
||||
break;
|
||||
}
|
||||
fflush(stdout);
|
||||
return bad_flag;
|
||||
}
|
||||
|
||||
// MD5 ファイル
|
||||
int verify_md5(
|
||||
char *ascii_buf,
|
||||
wchar_t *file_path)
|
||||
{
|
||||
unsigned char hash[16];
|
||||
wchar_t *line_off, uni_buf[MAX_LEN], num_buf[3];
|
||||
unsigned int err = 0, i, rv, line_len, name_len, line_num, num, comment;
|
||||
|
||||
// ファイル数を調べる
|
||||
comment = 0;
|
||||
num = 0;
|
||||
line_num = 1;
|
||||
line_off = text_buf;
|
||||
while (*line_off != 0){ // 一行ずつ処理する
|
||||
line_len = 0;
|
||||
while (line_off[line_len] != 0){ // 改行までを一行とする
|
||||
if (line_off[line_len] == '\n')
|
||||
break;
|
||||
if (line_off[line_len] == '\r')
|
||||
break;
|
||||
line_len++;
|
||||
}
|
||||
// 行の内容が適正か調べる
|
||||
if (line_off[0] == ';'){ // コメント
|
||||
if (((comment & 1) == 0) && (line_len > 8) && (line_len < MAX_LEN)){
|
||||
// クリエイターの表示がまだなら
|
||||
if (wcsncmp(line_off, L"; Generated by ", 15) == 0){ // md5sum, Easy MD5 Creator
|
||||
wcsncpy(uni_buf, line_off + 15, line_len - 15);
|
||||
uni_buf[line_len - 15] = 0;
|
||||
comment = 1;
|
||||
} else if (wcsncmp(line_off, L"; Using ", 8) == 0){
|
||||
wcsncpy(uni_buf, line_off + 8, line_len - 8);
|
||||
uni_buf[line_len - 8] = 0;
|
||||
comment = 1;
|
||||
}
|
||||
if (comment & 1){
|
||||
uni_buf[COMMENT_LEN - 1] = 0; // 表示する文字数を制限する
|
||||
utf16_to_cp(uni_buf, ascii_buf, COMMENT_LEN * 3, cp_output);
|
||||
printf("Creator : %s\n", ascii_buf);
|
||||
comment |= 4; // 同一行を二度表示しない
|
||||
}
|
||||
}
|
||||
if (((comment & 6) == 0) && (line_len < MAX_LEN)){
|
||||
// 最初のコメントの表示がまだなら
|
||||
i = 1;
|
||||
while (i < line_len){
|
||||
if (line_off[i] != ' ')
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (i < line_len){
|
||||
wcsncpy(uni_buf, line_off + i, line_len - i);
|
||||
uni_buf[line_len - i] = 0;
|
||||
uni_buf[COMMENT_LEN - 1] = 0; // 表示する文字数を制限する
|
||||
utf16_to_cp(uni_buf, ascii_buf, COMMENT_LEN * 3, cp_output);
|
||||
printf("Comment : %s\n", ascii_buf);
|
||||
}
|
||||
comment |= 2; // 「;」だけの行も認識する
|
||||
}
|
||||
comment &= ~4; // bit 4 を消す
|
||||
} else if (line_off[0] == '#'){ // コメント
|
||||
if (((comment & 1) == 0) && (line_len > 8) && (line_len < MAX_LEN)){
|
||||
// クリエイターの表示がまだなら
|
||||
if (wcsncmp(line_off, L"# Generated by ", 15) == 0){ // OpenHashTab
|
||||
wcsncpy(uni_buf, line_off + 15, line_len - 15);
|
||||
uni_buf[line_len - 15] = 0;
|
||||
comment = 1;
|
||||
} else if (wcsncmp(line_off, L"# MD5 checksum generated by ", 28) == 0){ // IsoBuster
|
||||
wcsncpy(uni_buf, line_off + 28, line_len - 28);
|
||||
uni_buf[line_len - 28] = 0;
|
||||
comment = 1;
|
||||
} else if (wcsncmp(line_off, L"#MD5 checksums generated by ", 28) == 0){ // xACT
|
||||
wcsncpy(uni_buf, line_off + 28, line_len - 28);
|
||||
uni_buf[line_len - 28] = 0;
|
||||
comment = 1;
|
||||
} else if (wcsncmp(line_off, L"# MD5 checksums generated by ", 29) == 0){ // MD5summer
|
||||
wcsncpy(uni_buf, line_off + 29, line_len - 29);
|
||||
uni_buf[line_len - 29] = 0;
|
||||
comment = 1;
|
||||
}
|
||||
if (comment & 1){
|
||||
uni_buf[COMMENT_LEN - 1] = 0; // 表示する文字数を制限する
|
||||
utf16_to_cp(uni_buf, ascii_buf, COMMENT_LEN * 3, cp_output);
|
||||
printf("Creator : %s\n", ascii_buf);
|
||||
}
|
||||
}
|
||||
} else if (line_len > 33){ // コメントではない
|
||||
// MD5 の後がスペース (md5sum 形式)
|
||||
if ((line_off[32] == ' ') && (base16_len(line_off) == 32)){
|
||||
// ファイル名
|
||||
name_len = line_len - 33;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
// タイプ記号「*」までのスペースは複数個でもいい
|
||||
while (line_off[line_len - name_len] == ' ')
|
||||
name_len--;
|
||||
if (line_off[line_len - name_len] == '*')
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off + (line_len - name_len), name_len);
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv > 1){
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
if (rv == 16){
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 浄化できないファイル名
|
||||
} else if ((rv & 6) == 0){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" is invalid\n", line_num, ascii_buf);
|
||||
} else {
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" was sanitized\n", line_num, ascii_buf);
|
||||
}
|
||||
}
|
||||
if (rv != 16)
|
||||
file_num++;
|
||||
} else {
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 長すぎるファイル名
|
||||
}
|
||||
|
||||
// ファイル名の後にMD5
|
||||
} else if ((line_off[line_len - 33] == ' ') && (base16_len(line_off + (line_len - 32)) == 32)){
|
||||
// MD5 の前が括弧 (BSD/OpenSSL 形式)
|
||||
if (((wcsncmp(line_off, L"MD5(", 4) == 0) || (wcsncmp(line_off, L"MD5 (", 5) == 0))
|
||||
&& ((wcsncmp(line_off + (line_len - 35), L")= ", 3) == 0) ||
|
||||
(wcsncmp(line_off + (line_len - 36), L") = ", 4) == 0))){
|
||||
// ファイル名
|
||||
name_len = line_len - 35 - 4;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
if (line_off[line_len - 35] != ')')
|
||||
name_len--;
|
||||
if (line_off[3] == ' '){
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off + 5, name_len);
|
||||
} else {
|
||||
wcsncpy(uni_buf, line_off + 4, name_len);
|
||||
}
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv > 1){
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
if (rv == 16){
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 浄化できないファイル名
|
||||
} else if ((rv & 6) == 0){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" is invalid\n", line_num, ascii_buf);
|
||||
} else {
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" was sanitized\n", line_num, ascii_buf);
|
||||
}
|
||||
}
|
||||
if (rv != 16)
|
||||
file_num++;
|
||||
} else {
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 長すぎるファイル名
|
||||
}
|
||||
} else { // MD5 の前がスペース (Easy MD5 Creator 形式)
|
||||
// ファイル名
|
||||
name_len = line_len - 33;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
while (line_off[name_len - 1] == ' ')
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off, name_len);
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv > 1){
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
if (rv == 16){
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 浄化できないファイル名
|
||||
} else if ((rv & 6) == 0){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" is invalid\n", line_num, ascii_buf);
|
||||
} else {
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
printf("line%d: \"%s\" was sanitized\n", line_num, ascii_buf);
|
||||
}
|
||||
}
|
||||
if (rv != 16)
|
||||
file_num++;
|
||||
} else {
|
||||
if ((comment & 8) == 0){
|
||||
comment |= 8;
|
||||
printf("\nWarning about filenames :\n");
|
||||
}
|
||||
printf("line%d: filename is invalid\n", line_num);
|
||||
num++; // 長すぎるファイル名
|
||||
}
|
||||
}
|
||||
} else {
|
||||
num++; // 内容が認識できない行
|
||||
}
|
||||
} else if (line_len > 0){
|
||||
num++; // 内容が認識できない行
|
||||
}
|
||||
// 次の行へ
|
||||
line_off += line_len;
|
||||
if (*line_off == '\n')
|
||||
line_off++;
|
||||
if (*line_off == '\r'){
|
||||
line_off++;
|
||||
if (*line_off == '\n') // 「\r\n」を一つの改行として扱う
|
||||
line_off++;
|
||||
}
|
||||
line_num++;
|
||||
}
|
||||
if (comment & 8)
|
||||
printf("\n");
|
||||
// チェックサム・ファイルの状態
|
||||
if (num == 0){
|
||||
printf("Status : Good\n");
|
||||
} else {
|
||||
printf("Status : Damaged\n");
|
||||
err |= 16; // 後で 256に変更する
|
||||
}
|
||||
if (file_num == 0){
|
||||
printf("valid file is not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\nInput File list : %d\n", file_num);
|
||||
printf("\t MD5 Hash\t\t : Filename\n");
|
||||
fflush(stdout);
|
||||
line_off = text_buf;
|
||||
while (*line_off != 0){ // 一行ずつ処理する
|
||||
line_len = 0;
|
||||
while (line_off[line_len] != 0){ // 改行までを一行とする
|
||||
if (line_off[line_len] == '\n')
|
||||
break;
|
||||
if (line_off[line_len] == '\r')
|
||||
break;
|
||||
line_len++;
|
||||
}
|
||||
// 行の内容が適正か調べる
|
||||
if ((line_off[0] != ';') && (line_len > 33)){ // コメントではない
|
||||
// MD5 の後がスペース (md5sum 形式)
|
||||
if ((line_off[32] == ' ') && (base16_len(line_off) == 32)){
|
||||
// ファイル名
|
||||
name_len = line_len - 33;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
// タイプ記号「*」までのスペースは複数個でもいい
|
||||
while (line_off[line_len - name_len] == ' ')
|
||||
name_len--;
|
||||
if (line_off[line_len - name_len] == '*')
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off + (line_len - name_len), name_len);
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// MD5
|
||||
num_buf[2] = 0;
|
||||
for (i = 0; i < 16; i++){
|
||||
wcsncpy(num_buf, line_off + (i * 2), 2);
|
||||
hash[i] = (unsigned char)get_val32h(num_buf);
|
||||
}
|
||||
printf("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X : \"%s\"\n",
|
||||
hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7],
|
||||
hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15], ascii_buf);
|
||||
}
|
||||
}
|
||||
|
||||
// ファイル名の後にMD5
|
||||
} else if ((line_off[line_len - 33] == ' ') && (base16_len(line_off + (line_len - 32)) == 32)){
|
||||
// MD5 の前が括弧 (BSD/OpenSSL 形式)
|
||||
if (((wcsncmp(line_off, L"MD5(", 4) == 0) || (wcsncmp(line_off, L"MD5 (", 5) == 0))
|
||||
&& ((wcsncmp(line_off + (line_len - 35), L")= ", 3) == 0) ||
|
||||
(wcsncmp(line_off + (line_len - 36), L") = ", 4) == 0))){
|
||||
// ファイル名
|
||||
name_len = line_len - 35 - 4;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
if (line_off[line_len - 35] != ')')
|
||||
name_len--;
|
||||
if (line_off[3] == ' '){
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off + 5, name_len);
|
||||
} else {
|
||||
wcsncpy(uni_buf, line_off + 4, name_len);
|
||||
}
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// MD5
|
||||
num_buf[2] = 0;
|
||||
for (i = 0; i < 16; i++){
|
||||
wcsncpy(num_buf, line_off + (line_len - 32 + (i * 2)), 2);
|
||||
hash[i] = (unsigned char)get_val32h(num_buf);
|
||||
}
|
||||
printf("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X : \"%s\"\n",
|
||||
hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7],
|
||||
hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15], ascii_buf);
|
||||
}
|
||||
}
|
||||
} else { // MD5 の前がスペース (Easy MD5 Creator 形式)
|
||||
// ファイル名
|
||||
name_len = line_len - 33;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
while (line_off[name_len - 1] == ' ')
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off, name_len);
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// MD5
|
||||
num_buf[2] = 0;
|
||||
for (i = 0; i < 16; i++){
|
||||
wcsncpy(num_buf, line_off + (line_len - 32 + (i * 2)), 2);
|
||||
hash[i] = (unsigned char)get_val32h(num_buf);
|
||||
}
|
||||
printf("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X : \"%s\"\n",
|
||||
hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7],
|
||||
hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15], ascii_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 次の行へ
|
||||
line_off += line_len;
|
||||
if (*line_off == '\n')
|
||||
line_off++;
|
||||
if (*line_off == '\r'){
|
||||
line_off++;
|
||||
if (*line_off == '\n') // 「\r\n」を一つの改行として扱う
|
||||
line_off++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nVerifying Input File :\n");
|
||||
printf(" Size Status : Filename\n");
|
||||
fflush(stdout);
|
||||
if (recent_data != 0){ // 前回の検査結果を使うなら
|
||||
PHMD5 ctx;
|
||||
// チェックサム・ファイル識別用にハッシュ値を計算する
|
||||
Phmd5Begin(&ctx);
|
||||
Phmd5Process(&ctx, (unsigned char *)text_buf, text_len * 2);
|
||||
Phmd5End(&ctx);
|
||||
// 前回の検査結果が存在するか
|
||||
check_ini_file(ctx.hash, text_len);
|
||||
}
|
||||
num = 0;
|
||||
line_off = text_buf;
|
||||
while (*line_off != 0){ // 一行ずつ処理する
|
||||
line_len = 0;
|
||||
while (line_off[line_len] != 0){ // 改行までを一行とする
|
||||
if (line_off[line_len] == '\n')
|
||||
break;
|
||||
if (line_off[line_len] == '\r')
|
||||
break;
|
||||
line_len++;
|
||||
}
|
||||
// 行の内容が適正か調べる
|
||||
if ((line_off[0] != ';') && (line_len > 33)){ // コメントではない
|
||||
// MD5 の後がスペース (md5sum 形式)
|
||||
if ((line_off[32] == ' ') && (base16_len(line_off) == 32)){
|
||||
// ファイル名
|
||||
name_len = line_len - 33;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
// タイプ記号「*」までのスペースは複数個でもいい
|
||||
while (line_off[line_len - name_len] == ' ')
|
||||
name_len--;
|
||||
if (line_off[line_len - name_len] == '*')
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off + (line_len - name_len), name_len);
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// MD5
|
||||
num_buf[2] = 0;
|
||||
for (i = 0; i < 16; i++){
|
||||
wcsncpy(num_buf, line_off + (i * 2), 2);
|
||||
hash[i] = (unsigned char)get_val32h(num_buf);
|
||||
}
|
||||
rv = file_md5_check(num, ascii_buf, uni_buf, file_path, hash);
|
||||
if (rv & 3){
|
||||
err = rv;
|
||||
break;
|
||||
}
|
||||
if (rv & 0xC){ // Missing or Damaged
|
||||
err |= rv;
|
||||
err += 0x100;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
// ファイル名の後にMD5
|
||||
} else if ((line_off[line_len - 33] == ' ') && (base16_len(line_off + (line_len - 32)) == 32)){
|
||||
// MD5 の前が括弧 (BSD/OpenSSL 形式)
|
||||
if (((wcsncmp(line_off, L"MD5(", 4) == 0) || (wcsncmp(line_off, L"MD5 (", 5) == 0))
|
||||
&& ((wcsncmp(line_off + (line_len - 35), L")= ", 3) == 0) ||
|
||||
(wcsncmp(line_off + (line_len - 36), L") = ", 4) == 0))){
|
||||
// ファイル名
|
||||
name_len = line_len - 35 - 4;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
if (line_off[line_len - 35] != ')')
|
||||
name_len--;
|
||||
if (line_off[3] == ' '){
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off + 5, name_len);
|
||||
} else {
|
||||
wcsncpy(uni_buf, line_off + 4, name_len);
|
||||
}
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// MD5
|
||||
num_buf[2] = 0;
|
||||
for (i = 0; i < 16; i++){
|
||||
wcsncpy(num_buf, line_off + (line_len - 32 + (i * 2)), 2);
|
||||
hash[i] = (unsigned char)get_val32h(num_buf);
|
||||
}
|
||||
rv = file_md5_check(num, ascii_buf, uni_buf, file_path, hash);
|
||||
if (rv & 3){
|
||||
err = rv;
|
||||
break;
|
||||
}
|
||||
if (rv & 0xC){ // Missing or Damaged
|
||||
err |= rv;
|
||||
err += 0x100;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
}
|
||||
} else { // MD5 の前がスペース (Easy MD5 Creator 形式)
|
||||
// ファイル名
|
||||
name_len = line_len - 33;
|
||||
if (base_len + name_len < MAX_LEN){
|
||||
while (line_off[name_len - 1] == ' ')
|
||||
name_len--;
|
||||
wcsncpy(uni_buf, line_off, name_len);
|
||||
uni_buf[name_len] = 0;
|
||||
rv = sanitize_filename(uni_buf); // ファイル名を浄化する
|
||||
if (rv != 16){
|
||||
utf16_to_cp(uni_buf, ascii_buf, MAX_LEN * 3, cp_output);
|
||||
// MD5
|
||||
num_buf[2] = 0;
|
||||
for (i = 0; i < 16; i++){
|
||||
wcsncpy(num_buf, line_off + (line_len - 32 + (i * 2)), 2);
|
||||
hash[i] = (unsigned char)get_val32h(num_buf);
|
||||
}
|
||||
rv = file_md5_check(num, ascii_buf, uni_buf, file_path, hash);
|
||||
if (rv & 3){
|
||||
err = rv;
|
||||
break;
|
||||
}
|
||||
if (rv & 0xC){ // Missing or Damaged
|
||||
err |= rv;
|
||||
err += 0x100;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 次の行へ
|
||||
line_off += line_len;
|
||||
if (*line_off == '\n')
|
||||
line_off++;
|
||||
if (*line_off == '\r'){
|
||||
line_off++;
|
||||
if (*line_off == '\n') // 「\r\n」を一つの改行として扱う
|
||||
line_off++;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user