diff --git a/lib/core/archive_ops.dart b/lib/core/archive_ops.dart index cedfd1f..6dbe22a 100644 --- a/lib/core/archive_ops.dart +++ b/lib/core/archive_ops.dart @@ -451,6 +451,9 @@ List parse7zList(String out) { Future<(int, String, String)> _run7z(String exe, List args, {String? password, void Function(String line)? onLine, bool Function()? cancelled, String? workingDirectory, bool confirm = false}) async { final pr = await Process.start(exe, ['-sccUTF-8', '-scsUTF-8', ...args], workingDirectory: workingDirectory); + // -sccUTF-8 이면 7-Zip 은 표준 입력도 UTF-8 로 읽는다 - Dart 의 기본 (시스템 코드 페이지, 한국어 Windows 는 CP949) 으로 보내면 + // 한글 비밀번호가 틀렸다고 나왔다 (관리자 지시로 10/18 시험: UTF-8 + -sccUTF-8 이면 7z · RAR 이 한글 비밀번호로 풀림) + pr.stdin.encoding = utf8; // 묻지 않을 때도 빈 줄을 보내 기다리지 않게 (암호가 걸렸는데 비밀번호가 없으면 틀림으로 끝난다) pr.stdin.writeln(password ?? ''); // 만들 때는 "다시 넣기" 도 묻는다 (zip_aes) diff --git a/test/archive_ops_test.dart b/test/archive_ops_test.dart index ca5f5a0..8d3107e 100644 --- a/test/archive_ops_test.dart +++ b/test/archive_ops_test.dart @@ -238,6 +238,20 @@ void main() { }, skip: has ? false : '7-Zip 이 없음 (tool/fetch_7zip.ps1)'); } + test('zip_aes: 한글 비밀번호 7z 풀기 - 표준 입력을 UTF-8 로 (머리까지 암호 · 목록 · 풀기 · 틀린 비밀번호)', () async { + File(p.join(tmp.path, 'a.txt')).writeAsStringSync('안'); + final arc = p.join(tmp.path, 'k.7z'); + // 시험 압축만 명령 줄 -p 로 만든다 (앱은 비밀번호를 명령 줄에 넣지 않는다) + final mk = await Process.run(exe, ['a', '-t7z', '-mhe=on', '-p비번 123', arc, p.join(tmp.path, 'a.txt')]); + expect(mk.exitCode, 0, reason: '${mk.stdout}'); + await expectLater(list7z(exe, arc, password: '틀림'), throwsA(isA())); + final list = await list7z(exe, arc, password: '비번 123'); + expect(list.map((e) => e.name), ['a.txt']); + final out = Directory(p.join(tmp.path, '풀림'))..createSync(); + await extract7zPlan(exe, arc, out.path, planExtract(list), password: '비번 123'); + expect(File(p.join(out.path, 'a.txt')).readAsStringSync(), '안'); + }, skip: has ? false : '7-Zip 이 없음 (tool/fetch_7zip.ps1)'); + test('zip_aes: 취소 · 실패면 만들다 만 ZIP 을 남기지 않고, 빈 비밀번호는 받지 않음', () async { final f = File(p.join(tmp.path, 'a.txt'))..writeAsStringSync('A'); final zip = p.join(tmp.path, 'c.zip');