Command.extract_file()   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
c 2
b 0
f 0
dl 0
loc 23
rs 8.3946
1
import json
2
import os
3
import re
4
import struct
5
from time import strftime
6
7
from django.core.management.base import BaseCommand
8
9
from chat.py2_3 import get_unicode
10
from django.conf import settings
11
12
ext = {
13
	b'\x47\x49': 'gif',
14
	b'\xff\xd8': 'jpg',
15
	b'\x89\x50': 'png',
16
	b'\x42\x4d': 'bmp'
17
}
18
19
file_names_pattern = {
20
	"I" : "base",
21
	"II" : "girls",
22
	"III": "extra"
23
}
24
25
START_CHAR = 13313
26
27
smiley_pattern = re.compile(r'^:.*:$')
28
29
30
class Command(BaseCommand):
31
	requires_system_checks = False
32
	def __init__(self):
33
		super(Command, self).__init__()
34
	help = 'CFPack Stealer 1.01'
35
36
	def add_arguments(self, parser):
37
		parser.add_argument(
38
			'--source',
39
			dest='port',
40
			default= os.path.join(settings.BASE_DIR, 'DefaultSmilies.cfpack'),
41
			type=str,
42
		)
43
44
	def extract_file(self):
45
		with open(self.pack_path, 'rb') as f:
46
			addition_info, cats = {}, []
47
			smileys = {}
48
			start_char  = START_CHAR
49
50
			if not os.path.exists(settings.SMILEYS_ROOT):
51
				print("Created smileys dir" + settings.SMILEYS_ROOT)
52
				os.mkdir(settings.SMILEYS_ROOT)
53
			size = struct.unpack('<H', f.read(2))  # header size (useless)
54
			addition_info['width'], addition_info['height'], count = struct.unpack('<HHB', f.read(5))
55
			for c in range(count):
56
				size = ord(f.read(1)) * 2  # 2 bytes per utf8
57
				cats.append((f.read(size)).decode('utf-16le'))  # save category
58
				addition_info[cats[c]] = []
59
				tab_dir_path = os.sep.join((settings.SMILEYS_ROOT, file_names_pattern[cats[c]]))
60
				if not os.path.exists(tab_dir_path):
61
					os.mkdir(tab_dir_path)
62
			addition_info['count'] = struct.unpack('<H', f.read(2))[0]  # amount of bytes in a single pack
63
			for item in range(addition_info['count']):
64
				start_char += 1
65
				self.write_smile(cats, count, f, item, smileys, start_char)
66
		return smileys
67
68
	def write_smile(self, cats, count, f, item, smileys, start_char):
69
		f.seek(1, 1)  # skip header size
70
		cat_cur = ord(f.read(1))
71
		if cat_cur >= count:
72
			raise SyntaxError('File is not valid')
73
		size = ord(f.read(1)) * 2
74
		alias = (f.read(size)).decode('utf-16le')
75
		f.seek(1, 1)  # 0
76
		size = struct.unpack('<I', f.read(4))[0]
77
		data = f.read(size)
78
		file_ext = ext.get(data[:2], '')
79
		file_name = '{0:04x}.{1}'.format(item, file_ext)
80
		tab = file_names_pattern[cats[cat_cur]]
81
		gif_file_path = os.sep.join((settings.SMILEYS_ROOT, tab, file_name))
82
		smileys.setdefault(tab, [])
83
		if not smiley_pattern.match(alias):
84
			alias = ":%s:" % alias
85
		smileys[tab].append({
86
			'code': get_unicode(start_char),
87
			'alt': alias,
88
			'src': file_name,
89
		})
90
		with open(gif_file_path, 'wb') as gif:
91
			gif.write(data)
92
93
	def create_json_info(self, info):
94
95
		info_file_name = os.sep.join((settings.SMILEYS_ROOT, 'info.json'))
96
		with open(info_file_name, 'w') as f:
97
			f.write(json.dumps(info))
98
99
	def handle(self, *args, **options):
100
		self.pack_path = options['port']
101
		if not os.path.exists(self.pack_path):
102
			raise Exception("cfpack file <<%s>> doesn't exist" % self.pack_path)
103
		info = self.extract_file()
104
		self.create_json_info(info)
105
		print(strftime('[%H:%M:%S] Done.'))
106
107
108