c2d16441b9
git-svn-id: svn://kolibrios.org@632 a494cfbc-eb01-0410-851d-a64ba20cac60
1313 lines
39 KiB
PHP
1313 lines
39 KiB
PHP
; Loader of ZIP archives for KFar_Arc.
|
|
; Written by diamond in 2007.
|
|
|
|
virtual at 0
|
|
file_in_zip:
|
|
.fullname dd ? ; pointer to cp866 string
|
|
.name dd ?
|
|
.namelen dd ?
|
|
.bIsDirectory db ?
|
|
.bPseudoFolder db ?
|
|
rb 2
|
|
.parent dd ? ; pointer to parent directory record
|
|
.subfolders dd ? ; head of L2-list of subfolders [for folders]
|
|
.subfolders.end dd ?
|
|
.subfiles dd ? ; head of L2-list of files [for folders]
|
|
.subfiles.end dd ?
|
|
.NumSubItems dd ?
|
|
.next dd ? ; next item of list of subfolders or files
|
|
.prev dd ? ; previous item of list of subfolders or files
|
|
.stamp dd ?
|
|
.version_made_by dw ?
|
|
.version_needed dw ?
|
|
.flags dw ?
|
|
.method dw ?
|
|
.time dw ?
|
|
.date dw ?
|
|
.crc dd ?
|
|
.compressed_size dq ?
|
|
.uncompressed_size dq ?
|
|
.local_hdr dq ?
|
|
.disk dd ?
|
|
.attr dd ?
|
|
.size = $
|
|
end virtual
|
|
|
|
virtual at 0
|
|
handle_zip:
|
|
.type dd ?
|
|
.root.subfolders dd ?
|
|
.root.subfolders.end dd ?
|
|
.root.subfiles dd ?
|
|
.root.subfiles.end dd ?
|
|
.root.NumSubItems dd ?
|
|
.curdir dd ?
|
|
.NumFiles dd ?
|
|
.names_buf dd ?
|
|
.host dd ?
|
|
.host_datetime rd 6
|
|
.num_disks dd ?
|
|
.cur_disk dd ?
|
|
.cur_handle dd ?
|
|
.host_hPlugin dd ?
|
|
.host_idPlugin dd ?
|
|
.password_len dd ? ; -1 if no password defined; in characters
|
|
.password rb password_maxlen
|
|
.basesize = $
|
|
end virtual
|
|
|
|
uglobal
|
|
align 4
|
|
zip.num_disks dd ?
|
|
zip.cur_disk dd ?
|
|
zip.cur_handle dd ?
|
|
zip.NumAllocated dd ?
|
|
zip.NamesSize dd ?
|
|
zip.disk_name rb 1024
|
|
|
|
zip64eocd: ; zip64 end of central directory record
|
|
.sig dd ? ; signature
|
|
.size dq ? ; size of this record
|
|
.version_made_by dw ? ; version made by
|
|
.version_needed dw ? ; version needed to extract
|
|
.disk dd ? ; number of this disk
|
|
.cdir_disk dd ? ; number of the disk with the start
|
|
; of the central directory
|
|
.cdir_entries_disk dq ? ; total number of entries in the central
|
|
; directory on this disk
|
|
.cdir_entries dq ? ; total number of entries in the central directory
|
|
.cdir_size dq ? ; size of the central directory
|
|
.cdir_start dq ? ; offset of start of central directory
|
|
.sz = $ - zip64eocd
|
|
|
|
zip.file_header:
|
|
.sig dd ?
|
|
.version_made_by dw ? ; (absent in local file header)
|
|
.version_needed dw ?
|
|
.flags dw ? ; general purpose bit flag
|
|
.method dw ? ; compression method
|
|
.time dw ? ; last modified file time
|
|
.date dw ? ; last modified file date
|
|
.crc dd ?
|
|
.compressed_size dd ?
|
|
.uncompressed_size dd ?
|
|
.fname_len dw ? ; file name length
|
|
.extra_len dw ? ; extra field length
|
|
.sz_local = $ - (zip.file_header+2) ; size of local file header
|
|
.fcmt_len dw ? ; file comment length
|
|
.disk dw ? ; disk number start
|
|
.internal_attr dw ?
|
|
.external_attr dd ?
|
|
.local_hdr dd ? ; relative offset of local header
|
|
.sz_cdir = $ - zip.file_header ; size of file header in central directory
|
|
|
|
zip.extra:
|
|
.id dw ?
|
|
.size dw ?
|
|
zip.extra.zip64:
|
|
.uncompressed_size dq ?
|
|
.compressed_size dq ?
|
|
.local_hdr dq ?
|
|
.disk dd ?
|
|
.sz = $ - zip.extra.zip64
|
|
endg
|
|
|
|
open_zip:
|
|
and [zip.cur_handle], 0
|
|
; look for end of central directory record
|
|
push ebp
|
|
call [filesize]
|
|
sub eax, 1024
|
|
sbb edx, 0
|
|
jnb @f
|
|
xor eax, eax
|
|
xor edx, edx
|
|
@@:
|
|
push edx
|
|
push eax
|
|
push 0
|
|
push ebp
|
|
call [seek]
|
|
push 1024
|
|
push buffer
|
|
push ebp
|
|
call [read]
|
|
cmp eax, 22
|
|
jge @f
|
|
xor eax, eax
|
|
.ret:
|
|
ret
|
|
@@:
|
|
mov [inStream], ebp
|
|
lea edi, [buffer+eax-22]
|
|
@@:
|
|
cmp dword [edi], 0x06054B50
|
|
jz .eocd_found
|
|
dec edi
|
|
cmp edi, buffer
|
|
jae @b
|
|
xor eax, eax
|
|
ret
|
|
.eocd_found:
|
|
cmp edi, buffer+20
|
|
jb .no_eocd64
|
|
cmp dword [edi-20], 0x07064B50
|
|
jnz .no_eocd64
|
|
mov ebx, ebp
|
|
mov ecx, [edi-16]
|
|
mov edx, [edi-4]
|
|
mov [zip.num_disks], edx
|
|
dec edx
|
|
mov [zip.cur_disk], edx
|
|
cmp edx, ecx
|
|
jz @f
|
|
push 1
|
|
push dword [esp+8+28]
|
|
push dword [esp+12+24]
|
|
push dword [esp+16+20]
|
|
call zip.open_splitted
|
|
test eax, eax
|
|
jz .ret
|
|
mov ebx, eax
|
|
@@:
|
|
push dword [edi-8]
|
|
push dword [edi-12]
|
|
push 0
|
|
push ebx
|
|
call [seek]
|
|
push zip64eocd.sz
|
|
push zip64eocd
|
|
push ebx
|
|
call [read]
|
|
cmp eax, zip64eocd.sz
|
|
jnz .close_err
|
|
cmp [zip64eocd.sig], 0x06064B50
|
|
jnz .close_err
|
|
mov ecx, [zip64eocd.cdir_disk]
|
|
cmp ecx, [zip.cur_disk]
|
|
jz @f
|
|
push 1
|
|
push dword [esp+8+28]
|
|
push dword [esp+12+24]
|
|
push dword [esp+16+20]
|
|
call zip.open_splitted
|
|
test eax, eax
|
|
jz .ret
|
|
mov ebx, eax
|
|
@@:
|
|
push dword [zip64eocd.cdir_start+4]
|
|
push dword [zip64eocd.cdir_start]
|
|
push 0
|
|
push ebx
|
|
call [seek]
|
|
mov ecx, dword [zip64eocd.cdir_entries]
|
|
jmp .parse_cdir
|
|
.close_err:
|
|
call close_cur_handle
|
|
or eax, -1
|
|
ret
|
|
.no_eocd64:
|
|
mov ebx, ebp
|
|
movzx ecx, word [edi+6]
|
|
movzx edx, word [edi+4]
|
|
inc edx
|
|
mov [zip.num_disks], edx
|
|
dec edx
|
|
mov [zip.cur_disk], edx
|
|
cmp edx, ecx
|
|
jz @f
|
|
push 1
|
|
push dword [esp+8+28]
|
|
push dword [esp+12+24]
|
|
push dword [esp+16+20]
|
|
call zip.open_splitted
|
|
test eax, eax
|
|
jz .ret
|
|
mov ebx, eax
|
|
@@:
|
|
push 0
|
|
push dword [edi+16]
|
|
push 0
|
|
push ebx
|
|
call [seek]
|
|
movzx ecx, word [edi+10]
|
|
.parse_cdir:
|
|
mov [zip.NumAllocated], ecx
|
|
imul ecx, file_in_zip.size
|
|
jc .close_err
|
|
add ecx, handle_zip.basesize
|
|
jc .close_err
|
|
mov [hOut.allocated], ecx
|
|
call [pgalloc]
|
|
test eax, eax
|
|
jz .close_err
|
|
mov [hOut], eax
|
|
push eax
|
|
mov edi, eax
|
|
shr ecx, 2
|
|
xor eax, eax
|
|
rep stosd
|
|
mov edi, [esp+8+28]
|
|
dec ecx
|
|
repnz scasb
|
|
not ecx
|
|
mov [zip.NamesSize], ecx
|
|
call [pgalloc]
|
|
mov ebp, eax
|
|
pop edi
|
|
test eax, eax
|
|
jz .free_err
|
|
push edi
|
|
mov edi, ebp
|
|
mov esi, [esp+8+28]
|
|
rep movsb
|
|
pop edi
|
|
mov byte [edi+handle_zip.type], type_zip
|
|
add edi, handle_zip.basesize + file_in_zip.version_made_by
|
|
.cdir_loop:
|
|
mov esi, zip.file_header
|
|
push zip.file_header.sz_cdir
|
|
push esi
|
|
push ebx
|
|
call [read]
|
|
cmp eax, zip.file_header.sz_cdir
|
|
jz .cdir_item_ok
|
|
mov ecx, [zip.cur_disk]
|
|
inc ecx
|
|
cmp ecx, [zip.num_disks]
|
|
jz .cdir_done
|
|
push 1
|
|
push dword [esp+8+28]
|
|
push dword [esp+12+24]
|
|
push dword [esp+16+20]
|
|
call zip.open_splitted
|
|
test eax, eax
|
|
jz .free_err
|
|
mov ebx, eax
|
|
jmp .cdir_loop
|
|
.cdir_item_ok:
|
|
lodsd
|
|
cmp eax, 0x02014B50
|
|
jnz .cdir_done
|
|
mov eax, [hOut]
|
|
inc [eax+handle_zip.NumFiles]
|
|
mov eax, [eax+handle_zip.NumFiles]
|
|
cmp eax, [zip.NumAllocated]
|
|
jbe .norealloc
|
|
inc [zip.NumAllocated]
|
|
mov ecx, [hOut.allocated]
|
|
add ecx, file_in_zip.size
|
|
push ecx
|
|
and ecx, 0xFFF
|
|
cmp ecx, file_in_zip.size
|
|
pop ecx
|
|
mov [hOut.allocated], ecx
|
|
ja .norealloc
|
|
mov edx, [hOut]
|
|
call [pgrealloc]
|
|
test eax, eax
|
|
jnz @f
|
|
.free_err:
|
|
mov ecx, [hOut]
|
|
call [pgfree]
|
|
mov ecx, ebp
|
|
call [pgfree]
|
|
jmp .close_err
|
|
@@:
|
|
mov [hOut], eax
|
|
sub edi, edx
|
|
add edi, eax
|
|
.norealloc:
|
|
push 5
|
|
pop ecx
|
|
rep movsd
|
|
xor eax, eax
|
|
stosd
|
|
movsd
|
|
stosd
|
|
lodsw
|
|
mov ecx, [zip.NamesSize]
|
|
lea edx, [ecx+0xFFF]
|
|
and edx, not 0xFFF
|
|
lea ecx, [ecx+eax+1]
|
|
mov [zip.NamesSize], ecx
|
|
push ecx
|
|
add ecx, 0xFFF
|
|
and ecx, not 0xFFF
|
|
cmp ecx, edx
|
|
pop ecx
|
|
jz .noreallocname
|
|
mov edx, ebp
|
|
call [pgrealloc]
|
|
test eax, eax
|
|
jz .free_err
|
|
mov ebp, eax
|
|
.noreallocname:
|
|
movzx eax, word [esi-2]
|
|
inc eax
|
|
mov edx, [zip.NamesSize]
|
|
sub edx, eax
|
|
mov dword [edi-(file_in_zip.uncompressed_size+8)+file_in_zip.fullname], edx
|
|
add edx, ebp
|
|
dec eax
|
|
mov byte [edx+eax], 0
|
|
push eax
|
|
push edx
|
|
push ebx
|
|
call [read]
|
|
movzx eax, word [esi-2]
|
|
cmp byte [edx+eax-1], '/'
|
|
jnz @f
|
|
mov byte [edx+eax-1], 0
|
|
mov byte [edi-(file_in_zip.uncompressed_size+8)+file_in_zip.bIsDirectory], 1
|
|
@@:
|
|
mov eax, [esi+12]
|
|
mov [edi], eax
|
|
movzx eax, word [esi+4]
|
|
mov [edi+8], eax
|
|
lodsw
|
|
push esi
|
|
movzx ecx, ax
|
|
mov edx, ecx
|
|
.parse_extra:
|
|
sub ecx, 4
|
|
jb .extra_done
|
|
mov esi, zip.extra
|
|
push 4
|
|
push esi
|
|
push ebx
|
|
call [read]
|
|
cmp eax, 4
|
|
jnz .extra_done
|
|
sub edx, eax
|
|
cmp word [esi], 1
|
|
jnz .extra_skip
|
|
mov esi, zip.extra.zip64
|
|
push esi edi
|
|
sub edi, 8
|
|
xchg esi, edi
|
|
movsd
|
|
movsd
|
|
sub esi, 16
|
|
movsd
|
|
movsd
|
|
add esi, 8
|
|
movsd
|
|
movsd
|
|
movsd
|
|
pop edi esi
|
|
movzx eax, [zip.extra.size]
|
|
cmp eax, zip.extra.zip64.sz
|
|
jb @f
|
|
mov al, zip.extra.zip64.sz
|
|
@@:
|
|
sub ecx, eax
|
|
jb .extra_done
|
|
push eax
|
|
push esi
|
|
push ebx
|
|
call [read]
|
|
sub edx, eax
|
|
sub [zip.extra.size], ax
|
|
sub edi, 8
|
|
movsd
|
|
movsd
|
|
sub edi, 16
|
|
movsd
|
|
movsd
|
|
add edi, 8
|
|
movsd
|
|
movsd
|
|
movsd
|
|
sub edi, 12
|
|
.extra_skip:
|
|
movzx eax, word [zip.extra.size]
|
|
sub ecx, eax
|
|
jb .extra_done
|
|
sub edx, eax
|
|
push 0
|
|
push eax
|
|
push 1
|
|
push ebx
|
|
call [seek]
|
|
jmp .parse_extra
|
|
.extra_done:
|
|
pop esi
|
|
xor eax, eax
|
|
lodsw
|
|
add edx, eax
|
|
jz @f
|
|
push 0
|
|
push edx
|
|
push 1
|
|
push ebx
|
|
call [seek]
|
|
@@:
|
|
mov eax, [esi+4]
|
|
mov dword [edi+file_in_zip.attr-(file_in_zip.uncompressed_size+8)], eax
|
|
; test al, 10h
|
|
; setnz byte [edi+file_in_zip.bIsDirectory-(file_in_zip.uncompressed_size+8)]
|
|
add edi, file_in_zip.size-file_in_zip.uncompressed_size-8+file_in_zip.version_made_by
|
|
jmp .cdir_loop
|
|
.cdir_done:
|
|
mov edi, [hOut]
|
|
mov esi, zip.num_disks
|
|
push edi
|
|
add edi, handle_zip.num_disks
|
|
movsd
|
|
movsd
|
|
movsd
|
|
pop edi
|
|
mov [edi+handle_zip.names_buf], ebp
|
|
mov ecx, [edi+handle_zip.NumFiles]
|
|
jecxz .nofiles
|
|
add edi, handle_zip.basesize + file_in_zip.fullname
|
|
@@:
|
|
add [edi], ebp
|
|
add edi, file_in_zip.size
|
|
loop @b
|
|
.nofiles:
|
|
mov edx, [hOut]
|
|
mov ebx, [edx+handle_zip.NumFiles]
|
|
lea edi, [edx+handle_zip.root.subfolders]
|
|
add edx, handle_zip.basesize
|
|
push file_in_zip.size
|
|
call init_file_links
|
|
mov eax, [hOut]
|
|
and [eax+handle_zip.curdir], 0 ; set root directory
|
|
mov esi, [inStream]
|
|
mov [eax+handle_zip.host], esi
|
|
or [eax+handle_zip.password_len], -1
|
|
mov esi, [esp+4+20]
|
|
mov [eax+handle_zip.host_idPlugin], esi
|
|
mov esi, [esp+4+24]
|
|
mov [eax+handle_zip.host_hPlugin], esi
|
|
lea edi, [eax+handle_zip.host_datetime]
|
|
mov esi, [esp+12]
|
|
add esi, 8
|
|
mov ecx, 6
|
|
rep movsd
|
|
ret
|
|
|
|
close_cur_handle:
|
|
mov edx, zip.cur_handle
|
|
or dword [edx-4], -1
|
|
cmp dword [edx], 0
|
|
jz @f
|
|
push dword [edx]
|
|
call [close]
|
|
and dword [edx], 0
|
|
@@:
|
|
ret
|
|
|
|
zip.open_splitted:
|
|
call close_cur_handle
|
|
mov [zip.cur_disk], ecx
|
|
inc ecx
|
|
mov edx, ecx
|
|
cmp ecx, [zip.num_disks]
|
|
jnz @f
|
|
mov ecx, [inStream]
|
|
push 0
|
|
push 0
|
|
push 0
|
|
push ecx
|
|
call [seek]
|
|
mov eax, ecx
|
|
ret 16
|
|
@@:
|
|
push esi edi
|
|
mov esi, [esp+8+12]
|
|
mov edi, zip.disk_name
|
|
mov [esp+8+12], edi
|
|
mov ecx, 1024
|
|
@@:
|
|
lodsb
|
|
stosb
|
|
test al, al
|
|
loopnz @b
|
|
jnz .ret0
|
|
cmp ecx, 4
|
|
jb .ret0
|
|
dec edi
|
|
mov al, '.'
|
|
stosb
|
|
cmp edx, 100
|
|
jae .big
|
|
mov al, 'z'
|
|
stosb
|
|
mov eax, edx
|
|
aam
|
|
add ax, '00'
|
|
xchg al, ah
|
|
stosw
|
|
mov byte [edi], 0
|
|
.nameok:
|
|
pop edi esi
|
|
push dword [esp+16]
|
|
push dword [esp+16]
|
|
push dword [esp+16]
|
|
push dword [esp+16]
|
|
call [open2]
|
|
mov [zip.cur_handle], eax
|
|
ret 16
|
|
.ret0:
|
|
mov byte [edi-1], 0
|
|
pop edi esi
|
|
xor eax, eax
|
|
ret 16
|
|
.big:
|
|
cmp ecx, 12
|
|
jb .ret0
|
|
push 10
|
|
pop ecx
|
|
push -'0'
|
|
mov eax, edx
|
|
@@:
|
|
xor edx, edx
|
|
div ecx
|
|
push edx
|
|
test eax, eax
|
|
jnz @b
|
|
@@:
|
|
pop eax
|
|
add al, '0'
|
|
jz .nameok
|
|
stosb
|
|
jmp @b
|
|
|
|
close_zip:
|
|
mov esi, [esp+4]
|
|
push [esi+handle_zip.host]
|
|
call [close]
|
|
mov ecx, [esi+handle_zip.names_buf]
|
|
call [pgfree]
|
|
mov ecx, [esi+handle_zip.cur_handle]
|
|
jecxz @f
|
|
push ecx
|
|
call [close]
|
|
@@:
|
|
mov ecx, esi
|
|
call [pgfree]
|
|
ret 4
|
|
|
|
; ebp=hPlugin, eax->item, edi->info
|
|
getattr_zip:
|
|
cmp [eax+file_in_zip.bPseudoFolder], 0
|
|
jnz .pseudo
|
|
mov esi, eax
|
|
mov eax, [eax+file_in_zip.attr]
|
|
stosd
|
|
xor eax, eax
|
|
stosd
|
|
stosd
|
|
stosd
|
|
stosd
|
|
stosd
|
|
movzx eax, word [esi+file_in_zip.time]
|
|
mov ecx, eax
|
|
and al, 0x1F
|
|
shr ecx, 5
|
|
add eax, eax
|
|
stosb
|
|
mov eax, ecx
|
|
and al, 0x3F
|
|
shr ecx, 6
|
|
stosb
|
|
mov eax, ecx
|
|
stosw
|
|
movzx eax, word [esi+file_in_zip.date]
|
|
mov ecx, eax
|
|
and al, 0x1F
|
|
shr ecx, 5
|
|
stosb
|
|
mov eax, ecx
|
|
and al, 0xF
|
|
shr ecx, 4
|
|
stosb
|
|
lea eax, [ecx+1980]
|
|
stosw
|
|
mov eax, dword [esi+file_in_zip.uncompressed_size]
|
|
stosd
|
|
mov eax, dword [esi+file_in_zip.uncompressed_size+4]
|
|
stosd
|
|
ret
|
|
.pseudo:
|
|
push 0x10 ; attributes: folder
|
|
pop eax
|
|
stosd
|
|
xor eax, eax
|
|
stosd
|
|
lea esi, [ebp+handle_zip.host_datetime]
|
|
push 6
|
|
pop ecx
|
|
rep movsd
|
|
stosd
|
|
stosd
|
|
ret
|
|
|
|
virtual at 0
|
|
file_handle_zip:
|
|
.type dd ?
|
|
.item dd ?
|
|
.base dd ?
|
|
.start_disk dd ?
|
|
.start dq ?
|
|
.pos dq ?
|
|
.posc dq ?
|
|
.decoder dd ?
|
|
.cur_disk dd ?
|
|
.cur_disk_start dq ?
|
|
.bError db ?
|
|
.bPassProtected db ?
|
|
.bPassInited db ?
|
|
rb 1
|
|
.keys rd 3
|
|
.saved_keys rd 3
|
|
.size = $
|
|
end virtual
|
|
|
|
iglobal
|
|
handle_table_zip dd handle_table_zip, handle_table_zip
|
|
endg
|
|
|
|
; ebp=hPlugin, eax->item, edi=mode
|
|
open_file_zip:
|
|
mov [_esp], esp
|
|
mov [_ebp], ebp
|
|
mov [error_proc], .error
|
|
mov [clear_proc], .clear
|
|
mov ecx, [ebp+handle_zip.password_len]
|
|
inc ecx
|
|
setnz [bPasswordDefined]
|
|
jz @f
|
|
dec ecx
|
|
mov [password_size], ecx
|
|
lea esi, [ebp+handle_zip.password]
|
|
mov edi, password_ansi
|
|
rep movsb
|
|
@@:
|
|
xor edi, edi
|
|
mov [hOut], edi
|
|
mov [hOut.allocated], edi
|
|
mov ebx, eax
|
|
movzx eax, [ebx+file_in_zip.method]
|
|
test eax, eax
|
|
jz .common
|
|
.notcopy:
|
|
cmp eax, 8
|
|
jz .deflate
|
|
cmp eax, 9
|
|
jz .deflate
|
|
push -'0'
|
|
push 10
|
|
pop ecx
|
|
@@:
|
|
xor edx, edx
|
|
div ecx
|
|
push edx
|
|
test eax, eax
|
|
jnz @b
|
|
mov edi, aUnknownMethod.z
|
|
mov al, ' '
|
|
stosb
|
|
@@:
|
|
pop eax
|
|
add al, '0'
|
|
stosb
|
|
jnz @b
|
|
push ContinueBtn
|
|
push 1
|
|
push aUnknownMethod_ptr
|
|
push 1
|
|
call [SayErr]
|
|
xor eax, eax
|
|
.ret1:
|
|
ret
|
|
.deflate:
|
|
mov ecx, 0x12000
|
|
call [pgalloc]
|
|
test eax, eax
|
|
jz .ret1
|
|
mov [hOut], eax
|
|
mov ecx, dword [ebx+file_in_zip.compressed_size]
|
|
mov dword [eax+streamInfo.fullSize], ecx
|
|
mov ecx, dword [ebx+file_in_zip.compressed_size+4]
|
|
mov dword [eax+streamInfo.fullSize+4], ecx
|
|
mov [eax+streamInfo.fillBuf], zipin.fillBuf
|
|
mov [eax+streamInfo.bufSize], 0x2000 - (streamInfo.size+4) - deflate_decoder.size
|
|
and [eax+streamInfo.bufDataLen], 0
|
|
lea edx, [eax+streamInfo.size+4]
|
|
mov [eax+streamInfo.bufPtr], edx
|
|
add edx, [eax+streamInfo.bufSize]
|
|
mov ecx, dword [ebx+file_in_zip.uncompressed_size]
|
|
mov dword [edx+streamInfo.fullSize], ecx
|
|
mov ecx, dword [ebx+file_in_zip.uncompressed_size+4]
|
|
mov dword [edx+streamInfo.fullSize+4], ecx
|
|
mov [edx+streamInfo.bufSize], 0x10000
|
|
and [edx+streamInfo.bufDataLen], 0
|
|
mov [edx+streamInfo.size], eax
|
|
lea eax, [edx+deflate_decoder.size]
|
|
mov [edx+streamInfo.bufPtr], eax
|
|
push ebp
|
|
mov ebp, edx
|
|
call deflate_init_decoder
|
|
mov edi, ebp
|
|
pop ebp
|
|
cmp [ebx+file_in_zip.method], 9
|
|
setz [edi+deflate_decoder.bDeflate64]
|
|
.common:
|
|
mov esi, handle_table_zip
|
|
push file_handle_zip.size
|
|
pop ecx
|
|
call alloc_handle
|
|
test eax, eax
|
|
jz return.clear
|
|
mov edx, [hOut]
|
|
mov [edx+streamInfo.size], eax
|
|
mov [eax+file_handle_zip.type], type_zip
|
|
xor edx, edx
|
|
mov dword [eax+file_handle_zip.pos], edx
|
|
mov dword [eax+file_handle_zip.pos+4], edx
|
|
mov dword [eax+file_handle_zip.posc], edx
|
|
mov dword [eax+file_handle_zip.posc+4], edx
|
|
mov [eax+file_handle_zip.item], ebx
|
|
mov [eax+file_handle_zip.base], ebp
|
|
mov [eax+file_handle_zip.decoder], edi
|
|
mov [eax+file_handle_zip.bError], dl
|
|
mov [eax+file_handle_zip.bPassInited], dl
|
|
test [ebx+file_in_zip.flags], 1
|
|
setnz [eax+file_handle_zip.bPassProtected]
|
|
mov ecx, [ebx+file_in_zip.disk]
|
|
mov [eax+file_handle_zip.start_disk], ecx
|
|
mov [eax+file_handle_zip.cur_disk], ecx
|
|
mov ecx, dword [ebx+file_in_zip.local_hdr]
|
|
mov dword [eax+file_handle_zip.start], ecx
|
|
mov ecx, dword [ebx+file_in_zip.local_hdr+4]
|
|
mov dword [eax+file_handle_zip.start+4], ecx
|
|
mov dword [eax+file_handle_zip.cur_disk_start], edx
|
|
mov dword [eax+file_handle_zip.cur_disk_start+4], edx
|
|
mov [hOut.allocated], eax
|
|
mov [hOut], edx
|
|
push ebx
|
|
mov ebx, eax
|
|
push zip.file_header.sz_local
|
|
pop ecx
|
|
mov edi, zip.file_header+2
|
|
call zip.read
|
|
cmp dword [edi-zip.file_header.sz_local], 0x04034B50
|
|
jnz return.err
|
|
movzx ecx, word [edi-4]
|
|
movzx eax, word [edi-2]
|
|
lea esi, [ecx+eax+zip.file_header.sz_local]
|
|
xor edi, edi
|
|
call zip.setpos
|
|
call zip.update_start
|
|
cmp [ebx+file_handle_zip.bPassProtected], 0
|
|
jz .nopass
|
|
.redo_pass:
|
|
call query_password
|
|
jz return.clear
|
|
call zip.init_keys
|
|
push 12
|
|
pop ecx
|
|
mov edi, buffer
|
|
call zip.read
|
|
mov eax, [ebx+file_handle_zip.item]
|
|
mov al, byte [eax+file_in_zip.crc+3]
|
|
cmp [edi-1], al
|
|
jz .passok
|
|
push CancelPassBtn
|
|
push 2
|
|
push aArchiveDataErrorPass_ptr
|
|
push 1
|
|
call [SayErr]
|
|
cmp al, 1
|
|
jnz return.clear
|
|
xor eax, eax
|
|
mov dword [ebx+file_handle_zip.posc], eax
|
|
mov dword [ebx+file_handle_zip.posc+4], eax
|
|
mov dword [ebx+file_handle_zip.cur_disk_start], eax
|
|
mov dword [ebx+file_handle_zip.cur_disk_start+4], eax
|
|
mov eax, [ebx+file_handle_zip.start_disk]
|
|
mov [ebx+file_handle_zip.cur_disk], eax
|
|
mov [bPasswordDefined], 0
|
|
jmp .redo_pass
|
|
.passok:
|
|
mov ecx, [password_size]
|
|
mov [ebp+handle_zip.password_len], ecx
|
|
mov esi, password_ansi
|
|
lea edi, [ebp+handle_zip.password]
|
|
rep movsb
|
|
lea esi, [ebx+file_handle_zip.keys]
|
|
lea edi, [ebx+file_handle_zip.saved_keys]
|
|
movsd
|
|
movsd
|
|
movsd
|
|
mov esi, 12
|
|
xor edi, edi
|
|
call zip.update_start
|
|
.nopass:
|
|
pop ebx
|
|
mov eax, [hOut.allocated]
|
|
cmp dword [ebx+file_in_zip.uncompressed_size+4], 0
|
|
jnz .ret
|
|
mov ecx, dword [ebx+file_in_zip.uncompressed_size]
|
|
if defined LIMIT_FOR_MEM_STREAM
|
|
cmp ecx, LIMIT_FOR_MEM_STREAM
|
|
ja .ret
|
|
end if
|
|
push eax ecx
|
|
add ecx, 0x3FF
|
|
shr ecx, 10 ; get size in Kb
|
|
call [getfreemem]
|
|
shr eax, 2
|
|
cmp ecx, eax
|
|
pop ecx eax
|
|
ja .ret
|
|
; create memory stream and unpack to memory
|
|
mov ebx, eax
|
|
add ecx, mem_stream.buf
|
|
call [pgalloc]
|
|
sub ecx, mem_stream.buf
|
|
test eax, eax
|
|
jz return.clear
|
|
mov edi, eax
|
|
mov [hOut], eax
|
|
xor eax, eax ; type_mem_stream
|
|
stosd ; mem_stream.type
|
|
mov eax, ecx
|
|
stosd ; mem_stream.size
|
|
xor eax, eax
|
|
stosd ; mem_stream.pos
|
|
push ecx edi
|
|
push ecx
|
|
push edi
|
|
push ebx
|
|
call read_zip
|
|
pop esi ecx
|
|
mov [_esp], esp
|
|
mov [_ebp], ebp
|
|
mov [error_proc], .error
|
|
mov [clear_proc], .clear
|
|
cmp eax, -1
|
|
jz .clear
|
|
; cmp eax, ecx
|
|
; jnz .error
|
|
; call crc
|
|
; mov edx, [ebx+file_handle_zip.item]
|
|
; cmp eax, [edx+file_in_zip.crc]
|
|
; jnz .error
|
|
call .1
|
|
mov eax, [hOut]
|
|
.ret:
|
|
ret
|
|
|
|
.error:
|
|
push ContinueBtn
|
|
push 1
|
|
push aArchiveDataError_ptr
|
|
push 1
|
|
call [SayErr]
|
|
.clear:
|
|
mov ecx, [hOut]
|
|
call [pgfree]
|
|
.1:
|
|
mov ebx, [hOut.allocated]
|
|
test ebx, ebx
|
|
jz @f
|
|
push ebx
|
|
call close_file_zip
|
|
@@:
|
|
xor eax, eax
|
|
ret
|
|
|
|
close_file_zip:
|
|
mov ecx, [ebx+file_handle_zip.decoder]
|
|
jecxz @f
|
|
mov ecx, [ecx+streamInfo.size]
|
|
call [pgfree]
|
|
@@:
|
|
mov esi, ebx
|
|
call free_handle
|
|
ret 4
|
|
|
|
zip.init_keys:
|
|
mov [ebx+file_handle_zip.keys+0], 305419896
|
|
mov [ebx+file_handle_zip.keys+4], 591751049
|
|
mov [ebx+file_handle_zip.keys+8], 878082192
|
|
mov ecx, [password_size]
|
|
jecxz .empty
|
|
mov esi, password_ansi
|
|
xor eax, eax
|
|
@@:
|
|
lodsb
|
|
call zip.update_keys
|
|
loop @b
|
|
.empty:
|
|
mov [ebx+file_handle_zip.bPassInited], 1
|
|
ret
|
|
|
|
zip.update_keys:
|
|
mov dl, byte [ebx+file_handle_zip.keys]
|
|
xor dl, al
|
|
movzx edx, dl
|
|
mov eax, [ebx+file_handle_zip.keys]
|
|
shr eax, 8
|
|
xor eax, [crc_table+edx*4]
|
|
mov [ebx+file_handle_zip.keys], eax
|
|
movzx eax, al
|
|
add eax, [ebx+file_handle_zip.keys+4]
|
|
imul eax, 134775813
|
|
inc eax
|
|
mov [ebx+file_handle_zip.keys+4], eax
|
|
shr eax, 24
|
|
mov edx, [ebx+file_handle_zip.keys+8]
|
|
xor al, dl
|
|
shr edx, 8
|
|
xor edx, [crc_table+eax*4]
|
|
mov [ebx+file_handle_zip.keys+8], edx
|
|
ret
|
|
|
|
zip.decrypt_byte:
|
|
; out: ah = result
|
|
mov eax, [ebx+file_handle_zip.keys+8]
|
|
or eax, 2
|
|
mov edx, eax
|
|
xor edx, 1
|
|
mul edx
|
|
ret
|
|
|
|
zip.get_cur_handle:
|
|
mov edx, [ebp+handle_zip.host]
|
|
mov eax, [ebp+handle_zip.num_disks]
|
|
dec eax
|
|
cmp eax, [ebx+file_handle_zip.cur_disk]
|
|
jz .handleok
|
|
inc eax
|
|
mov [zip.num_disks], eax
|
|
mov edx, [ebp+handle_zip.cur_handle]
|
|
mov eax, [ebp+handle_zip.cur_disk]
|
|
cmp eax, [ebx+file_handle_zip.cur_disk]
|
|
jz .handleok
|
|
mov [zip.cur_handle], edx
|
|
push ecx
|
|
mov ecx, [ebx+file_handle_zip.cur_disk]
|
|
push 1
|
|
push [ebp+handle_zip.names_buf]
|
|
push [ebp+handle_zip.host_hPlugin]
|
|
push [ebp+handle_zip.host_idPlugin]
|
|
call zip.open_splitted
|
|
pop ecx
|
|
mov edx, eax
|
|
test eax, eax
|
|
jnz @f
|
|
push zip.disk_name
|
|
push aCannotOpenFile
|
|
mov eax, esp
|
|
push ContinueBtn
|
|
push 1
|
|
push eax
|
|
push 2
|
|
call [SayErr]
|
|
jmp return.clear
|
|
@@:
|
|
mov [ebp+handle_zip.cur_handle], eax
|
|
mov eax, [ebx+file_handle_zip.cur_disk]
|
|
mov [ebp+handle_zip.cur_disk], eax
|
|
.handleok:
|
|
ret
|
|
|
|
zip.read:
|
|
; in: ebx=hFile, edi->buf, ecx=size
|
|
push ebp edi
|
|
mov ebp, [ebx+file_handle_zip.base]
|
|
.s:
|
|
call zip.get_cur_handle
|
|
mov eax, dword [ebx+file_handle_zip.posc]
|
|
mov esi, dword [ebx+file_handle_zip.posc+4]
|
|
sub eax, dword [ebx+file_handle_zip.cur_disk_start]
|
|
sbb esi, dword [ebx+file_handle_zip.cur_disk_start+4]
|
|
push eax
|
|
mov eax, dword [ebx+file_handle_zip.cur_disk]
|
|
cmp eax, dword [ebx+file_handle_zip.start_disk]
|
|
pop eax
|
|
jnz @f
|
|
add eax, dword [ebx+file_handle_zip.start]
|
|
adc esi, dword [ebx+file_handle_zip.start+4]
|
|
@@:
|
|
push esi
|
|
push eax
|
|
push 0
|
|
push edx
|
|
call [seek]
|
|
push ecx
|
|
push edi
|
|
push edx
|
|
call [read]
|
|
cmp eax, -1
|
|
jz .error
|
|
add edi, eax
|
|
add dword [ebx+file_handle_zip.posc], eax
|
|
adc dword [ebx+file_handle_zip.posc+4], 0
|
|
sub ecx, eax
|
|
jz .ok
|
|
inc dword [ebx+file_handle_zip.cur_disk]
|
|
mov eax, dword [ebx+file_handle_zip.posc]
|
|
mov dword [ebx+file_handle_zip.cur_disk_start], eax
|
|
mov eax, dword [ebx+file_handle_zip.posc+4]
|
|
mov dword [ebx+file_handle_zip.cur_disk_start+4], eax
|
|
jmp .s
|
|
.ok:
|
|
cmp [ebx+file_handle_zip.bPassInited], 0
|
|
jnz .decrypt
|
|
pop eax ebp
|
|
ret
|
|
.decrypt:
|
|
mov ecx, edi
|
|
pop edi
|
|
sub ecx, edi
|
|
jz .nodata
|
|
@@:
|
|
call zip.decrypt_byte
|
|
xor [edi], ah
|
|
mov al, [edi]
|
|
inc edi
|
|
call zip.update_keys
|
|
loop @b
|
|
.nodata:
|
|
pop ebp
|
|
ret
|
|
.error:
|
|
push ContinueBtn
|
|
push 1
|
|
push aReadError_ptr
|
|
push 1
|
|
call [SayErr]
|
|
jmp return.clear
|
|
|
|
zip.setpos:
|
|
; in: ebx=hFile, edi:esi=newpos
|
|
cmp [ebx+file_handle_zip.bPassInited], 0
|
|
jnz .pass
|
|
push ebp
|
|
mov ebp, [ebx+file_handle_zip.base]
|
|
push edi esi
|
|
sub esi, dword [ebx+file_handle_zip.cur_disk_start]
|
|
sbb edi, dword [ebx+file_handle_zip.cur_disk_start+4]
|
|
jae .fwd
|
|
mov eax, [ebx+file_handle_zip.start_disk]
|
|
mov [ebx+file_handle_zip.cur_disk], eax
|
|
and dword [ebx+file_handle_zip.cur_disk_start], 0
|
|
and dword [ebx+file_handle_zip.cur_disk_start+4], 0
|
|
pop esi edi
|
|
push edi esi
|
|
.fwd:
|
|
call zip.get_cur_handle
|
|
push edx
|
|
call [filesize]
|
|
push eax
|
|
mov eax, [ebx+file_handle_zip.cur_disk]
|
|
cmp eax, [ebx+file_handle_zip.start_disk]
|
|
pop eax
|
|
jnz @f
|
|
sub eax, dword [ebx+file_handle_zip.start]
|
|
sbb edx, dword [ebx+file_handle_zip.start+4]
|
|
@@:
|
|
sub esi, eax
|
|
sbb edi, edx
|
|
jb @f
|
|
inc [ebx+file_handle_zip.cur_disk]
|
|
add dword [ebx+file_handle_zip.cur_disk_start], eax
|
|
adc dword [ebx+file_handle_zip.cur_disk_start+4], edx
|
|
jmp .fwd
|
|
@@:
|
|
pop esi edi
|
|
mov dword [ebx+file_handle_zip.posc], esi
|
|
mov dword [ebx+file_handle_zip.posc+4], edi
|
|
pop ebp
|
|
ret
|
|
.pass:
|
|
push edi esi
|
|
sub esi, dword [ebx+file_handle_zip.posc]
|
|
sbb edi, dword [ebx+file_handle_zip.posc+4]
|
|
jae .pfwd
|
|
lea esi, [ebx+file_handle_zip.saved_keys]
|
|
lea edi, [ebx+file_handle_zip.keys]
|
|
movsd
|
|
movsd
|
|
movsd
|
|
and dword [ebx+file_handle_zip.posc], 0
|
|
and dword [ebx+file_handle_zip.posc+4], 0
|
|
mov eax, [ebx+file_handle_zip.start_disk]
|
|
mov [ebx+file_handle_zip.cur_disk], eax
|
|
and dword [ebx+file_handle_zip.cur_disk_start], 0
|
|
and dword [ebx+file_handle_zip.cur_disk_start+4], 0
|
|
pop esi edi
|
|
push edi esi
|
|
.pfwd:
|
|
push edi esi
|
|
mov ecx, 1024
|
|
sub esi, ecx
|
|
sbb edi, 0
|
|
jae @f
|
|
add ecx, esi
|
|
@@:
|
|
push ecx
|
|
mov edi, buffer
|
|
call zip.read
|
|
pop ecx
|
|
pop esi edi
|
|
sub esi, ecx
|
|
sbb edi, 0
|
|
mov eax, esi
|
|
or eax, edi
|
|
jnz .pfwd
|
|
pop esi edi
|
|
ret
|
|
|
|
zip.update_start:
|
|
; edi=0, esi=pos
|
|
sub esi, dword [ebx+file_handle_zip.cur_disk_start]
|
|
mov dword [ebx+file_handle_zip.cur_disk_start], edi
|
|
add dword [ebx+file_handle_zip.start], esi
|
|
adc dword [ebx+file_handle_zip.start+4], edi
|
|
mov dword [ebx+file_handle_zip.posc], edi
|
|
mov dword [ebx+file_handle_zip.posc+4], edi
|
|
mov eax, [ebx+file_handle_zip.cur_disk]
|
|
cmp eax, [ebx+file_handle_zip.start_disk]
|
|
jz @f
|
|
mov [ebx+file_handle_zip.start_disk], eax
|
|
mov dword [ebx+file_handle_zip.start], esi
|
|
mov dword [ebx+file_handle_zip.start+4], edi
|
|
@@:
|
|
ret
|
|
|
|
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
|
|
read_zip:
|
|
mov [_esp], esp
|
|
mov [_ebp], ebp
|
|
mov [error_proc], .error
|
|
mov [clear_proc], .clear
|
|
cmp [ebx+file_handle_zip.bError], 0
|
|
jnz .reterr
|
|
mov edi, [esp+8]
|
|
mov ecx, [esp+12]
|
|
mov esi, [ebx+file_handle_zip.item]
|
|
mov edx, dword [esi+file_in_zip.uncompressed_size]
|
|
mov esi, dword [esi+file_in_zip.uncompressed_size+4]
|
|
sub edx, dword [ebx+file_handle_zip.pos]
|
|
sbb esi, dword [ebx+file_handle_zip.pos+4]
|
|
jnz @f
|
|
cmp edx, ecx
|
|
jae @f
|
|
mov ecx, edx
|
|
@@:
|
|
jecxz .done
|
|
mov eax, [ebx+file_handle_zip.decoder]
|
|
test eax, eax
|
|
jnz .notcopy
|
|
call zip.read
|
|
jmp .done
|
|
.notcopy:
|
|
mov dword [eax+streamInfo.fullSize], ecx
|
|
and dword [eax+streamInfo.fullSize+4], 0
|
|
call read_7z_to_buf
|
|
.done:
|
|
sub edi, [esp+8]
|
|
mov eax, edi
|
|
add dword [ebx+file_handle_zip.pos], eax
|
|
adc dword [ebx+file_handle_zip.pos+4], 0
|
|
.ret:
|
|
ret 12
|
|
|
|
.error:
|
|
push ContinueBtn
|
|
push 1
|
|
push aArchiveDataError_ptr
|
|
push 1
|
|
call [SayErr]
|
|
.clear:
|
|
mov ebx, [esp+4]
|
|
mov [ebx+file_handle_zip.bError], 1
|
|
.reterr:
|
|
or eax, -1
|
|
ret 12
|
|
|
|
zipin.fillBuf:
|
|
mov ebx, [eax+streamInfo.size]
|
|
call zip.read
|
|
popad
|
|
ret
|
|
|
|
; void __stdcall setpos(HANDLE hFile, __int64 pos);
|
|
setpos_zip:
|
|
mov [_esp], esp
|
|
mov [_ebp], ebp
|
|
mov [error_proc], read_zip.error
|
|
mov [clear_proc], read_zip.clear
|
|
cmp [ebx+file_handle_zip.decoder], 0
|
|
jnz .notcopy
|
|
mov esi, [esp+8]
|
|
mov edi, [esp+12]
|
|
call zip.setpos
|
|
mov dword [ebx+file_handle_zip.pos], esi
|
|
mov dword [ebx+file_handle_zip.pos+4], edi
|
|
ret 12
|
|
.notcopy:
|
|
cmp [ebx+file_handle_zip.bError], 0
|
|
jnz .backward
|
|
mov ecx, [esp+8]
|
|
mov edx, [esp+12]
|
|
sub ecx, dword [ebx+file_handle_zip.pos]
|
|
sbb edx, dword [ebx+file_handle_zip.pos+4]
|
|
jb .backward
|
|
mov eax, [ebx+file_handle_zip.decoder]
|
|
mov dword [eax+streamInfo.fullSize], ecx
|
|
mov dword [eax+streamInfo.fullSize+4], edx
|
|
call skip_7z
|
|
add dword [ebx+file_handle_zip.pos], ecx
|
|
adc dword [ebx+file_handle_zip.pos+4], edx
|
|
ret 12
|
|
.backward:
|
|
xor eax, eax
|
|
mov [ebx+file_handle_zip.bError], al
|
|
mov dword [ebx+file_handle_zip.pos], eax
|
|
mov dword [ebx+file_handle_zip.pos+4], eax
|
|
mov dword [ebx+file_handle_zip.posc], eax
|
|
mov dword [ebx+file_handle_zip.posc+4], eax
|
|
mov dword [ebx+file_handle_zip.cur_disk_start], eax
|
|
mov dword [ebx+file_handle_zip.cur_disk_start+4], eax
|
|
lea esi, [ebx+file_handle_zip.saved_keys]
|
|
lea edi, [ebx+file_handle_zip.keys]
|
|
movsd
|
|
movsd
|
|
movsd
|
|
mov eax, [ebx+file_handle_zip.start_disk]
|
|
mov [ebx+file_handle_zip.cur_disk], eax
|
|
mov eax, [ebx+file_handle_zip.decoder]
|
|
mov eax, [eax+deflate_decoder.inStream]
|
|
mov esi, [ebx+file_handle_zip.item]
|
|
mov ecx, dword [esi+file_in_zip.compressed_size]
|
|
mov dword [eax+streamInfo.fullSize], ecx
|
|
mov ecx, dword [esi+file_in_zip.compressed_size+4]
|
|
mov dword [eax+streamInfo.fullSize+4], ecx
|
|
and [eax+streamInfo.bufDataLen], 0
|
|
lea ebp, [eax+streamInfo.size+4]
|
|
add ebp, [eax+streamInfo.bufSize]
|
|
and [ebp+streamInfo.bufDataLen], 0
|
|
call deflate_init_decoder
|
|
cmp [esi+file_in_zip.method], 9
|
|
setz [ebp+deflate_decoder.bDeflate64]
|
|
mov eax, [esp+8]
|
|
mov dword [ebp+streamInfo.fullSize], eax
|
|
mov eax, [esp+12]
|
|
mov dword [ebp+streamInfo.fullSize+4], eax
|
|
mov eax, ebp
|
|
call skip_7z
|
|
mov eax, [esp+8]
|
|
mov dword [ebx+file_handle_zip.pos], eax
|
|
mov eax, [esp+12]
|
|
mov dword [ebx+file_handle_zip.pos+4], eax
|
|
ret 12
|