From b0ac3c4581e40c9cd07bf8a1f950e4efe5c953c9 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Sun, 18 Oct 2026 00:13:09 +0900 Subject: [PATCH] =?UTF-8?q?WIP=2086=20=EB=B3=B4=EC=B6=A9:=207z=20=C2=B7=20?= =?UTF-8?q?RAR=20=EC=9D=98=20=ED=95=9C=EA=B8=80=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=ED=92=80=EA=B8=B0=20-=207-Zip=20=ED=91=9C?= =?UTF-8?q?=EC=A4=80=20=EC=9E=85=EB=A0=A5=EC=9D=84=20UTF-8=20=EB=A1=9C=20(?= =?UTF-8?q?=EA=B2=80=ED=86=A0=20=EB=8C=80=EA=B8=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 관리자 지시 (10/18): -sccUTF-8 로 표준 입력을 UTF-8 로 보내 보고, 되면 그것을 쓴다. - 10/18 실제 7z.exe 시험: 7z 형식 (머리까지 암호) 의 한글 비밀번호는 -sccUTF-8 + UTF-8 표준 입력이면 풀림 (exit 0). 앱의 _run7z 는 -sccUTF-8 을 붙이면서 표준 입력은 Dart 기본 (시스템 코드 페이지 = CP949) 으로 보내 실패하고 있었다 (CP949 + -sccUTF-8 = exit 2 확인). → pr.stdin.encoding = utf8. 7z · RAR 의 목록 · 풀기 · 비밀번호 모두 같은 길 (RAR 은 만들 수 없어 실제 RAR 로는 시험 못 함 - 같은 비밀번호 읽기) - ZIP 만들기는 그대로: 7-Zip 의 ZIP 은 영문 밖 비밀번호를 (표준 입력 · 명령 줄 모두) 받지 않아 archive AES + 512MB 제한 + 경고 (관리자 승인). ZIP 풀기는 archive (앞 커밋의 UTF-8 바이트 고침) - 명령 줄 -p 는 쓰지 않음 (프로세스 목록에 보임, 관리자 지시) 시험: archive_ops 14 통과 (새: 한글 비밀번호 7z - 틀린 비밀번호 · 목록 · 풀기. 시험 압축만 명령 줄 -p 로 만듦). Co-Authored-By: Claude Opus 5.5 --- lib/core/archive_ops.dart | 3 +++ test/archive_ops_test.dart | 14 ++++++++++++++ 2 files changed, 17 insertions(+) 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');