-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
144 lines (130 loc) · 4.59 KB
/
main.py
File metadata and controls
144 lines (130 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# -*- coding: utf-8 -*-
import sys
import os
import zipfile
import py7zr
import tempfile
import stat
INEFFICIENT_FORMATS = {".jpg", ".jpeg", ".jpe", ".jfif", ".png", ".apng", ".mp4", ".mp3", ".avi", ".mp2", ".mp1", ".m4a"}
MAX_FILE_SIZE = 1024 * 1024 * 1024 # 1GB 제한 (압축 해제 시)
def safe_path(base, target):
"""경로 탈출 방지"""
abs_base = os.path.abspath(base)
abs_target = os.path.abspath(os.path.join(base, target))
if os.path.commonpath([abs_base, abs_target]) != abs_base
raise Exception(f"경로 탈출 시도 감지: {target}")
return abs_target
def is_safe_filename(name):
"""파일명 검증"""
return not ("/" in name or "\\" in name or name.startswith(".."))
def strip_exec_permission(path):
"""실행 권한 제거"""
try:
mode = os.stat(path).st_mode
os.chmod(path, mode & ~stat.S_IXUSR & ~stat.S_IXGRP & ~stat.S_IXOTH)
except Exception:
pass
def safe_extract_zip(zf, output):
for name in zf.namelist():
if not is_safe_filename(name):
print(f"{name}: 위험한 파일명이라 제외")
continue
target_path = safe_path(output, name)
info = zf.getinfo(name)
if info.file_size > MAX_FILE_SIZE:
print(f"{name}: 파일 크기 초과로 해제 취소")
continue
zf.extract(name, output)
strip_exec_permission(target_path)
def safe_extract_7z(archive, output):
for name in archive.getnames():
if not is_safe_filename(name):
print(f"{name}: 위험한 파일명이라 제외")
continue
target_path = safe_path(output, name)
archive.extract(targets=[name], path=output)
strip_exec_permission(target_path)
def cm_zip(files, output="output.zip"):
with zipfile.ZipFile(output, 'w', compression=zipfile.ZIP_DEFLATED) as zf:
for file in files:
ext = os.path.splitext(file)[1].lower()
if ext in INEFFICIENT_FORMATS:
print(f"{file}: 비효율적 포맷이라 제외")
continue
if not os.path.exists(file):
print(f"{file}: 없음")
continue
if os.path.getsize(file) > MAX_FILE_SIZE:
print(f"{file}: 크기 초과로 제외")
continue
zf.write(file, os.path.basename(file))
print("ZIP 압축 완료:", output)
def decm_zip(file, output="."):
try:
with zipfile.ZipFile(file, 'r') as zf:
safe_extract_zip(zf, output)
print("ZIP 해제 완료:", output)
except zipfile.BadZipFile:
print("손상된 ZIP 파일")
except PermissionError:
print("권한 오류")
except Exception as e:
print("ZIP 해제 오류:", e)
def cm_7z(files, output="output.7z"):
with py7zr.SevenZipFile(output, 'w') as archive:
for file in files:
ext = os.path.splitext(file)[1].lower()
if ext in INEFFICIENT_FORMATS:
print(f"{file}: 비효율적 포맷이라 제외")
continue
if not os.path.exists(file):
print(f"{file}: 없음")
continue
if os.path.getsize(file) > MAX_FILE_SIZE:
print(f"{file}: 크기 초과로 제외")
continue
archive.write(file, os.path.basename(file))
print("7Z 압축 완료:", output)
def decm_7z(file, output="."):
try:
with py7zr.SevenZipFile(file, 'r') as archive:
safe_extract_7z(archive, output)
print("7Z 해제 완료:", output)
except py7zr.Bad7zFile:
print("손상된 7Z 파일")
except PermissionError:
print("권한 오류")
except Exception as e:
print("7Z 해제 오류:", e)
def m():
if len(sys.argv) < 3:
print("사용법: cps z file1 file2 ... | cps 7z file1 file2 ... | decps z archive.zip | decps 7z archive.7z")
sys.exit(1)
cm = sys.argv[1]
m = sys.argv[2]
if cm == "cps":
files = sys.argv[3:]
if not files:
print("압축할 파일 없음")
return
if m == "z":
cm_zip(files)
elif m == "7z":
cm_7z(files)
else:
print("미지원 모드")
elif cm == "decps":
if len(sys.argv) < 4:
print("해제할 파일 없음")
return
archive = sys.argv[3]
if m == "z":
decm_zip(archive)
elif m == "7z":
decm_7z(archive)
else:
print("미지원 모드")
else:
print("미지원")
if __name__ == "__main__":
m()