include	clib.inc

ifdef __ZIP__

include	iost.inc
include	string.inc
include	wsub.inc
include	fblk.inc
include	unzip.inc
include	malloc.inc

	public	arc_flength
	extrn	_bufin:byte

_DATA	SEGMENT

arc_flength dd ?
arc_pathz   dw ?

_DATA	ENDS

_TEXT	SEGMENT

ifdef DEBUG
	public	zip_allocfblk
	public	zip_findnext
	public	zip_testcentral
	public	zip_readcentral
	public	getendcentral
endif

getendcentral proc pascal wsub:dword, zend:dword
	invoke wsopenarch, wsub
	mov STDI.ios_file,ax
	inc ax
	.if ax
	    invoke oseekl, 0, SEEK_END
	    .if !ZERO?
		mov ax,word ptr STDI.ios_offset
		stom arc_flength
		.if dx || ax >= SIZE S_ZEND
		    call oungetc
		    .if !ZERO? && STDI.ios_i >= SIZE S_ZEND-1
			sub STDI.ios_i,SIZE S_ZEND-2
			.while 1
			    call oungetc
			    .if !ZERO?
				.if al != 'P'
				    .continue
				.endif
				mov ax,SIZE S_ZEND
				call oread
				.if !ZERO?
				    lodm es:[bx]
				    .if ax != ZIPHEADERID || dx != ZIPENDSENTRID
					.continue
				    .endif
				    invoke memcpy, zend, es::bx, SIZE S_ZEND
				    mov ax,1
				    jmp @F
				.endif
				.break
			    .endif
			    .break
			.endw
		    .endif
		.endif
	    .endif
	    invoke close, STDI.ios_file
	    xor ax,ax
	.endif
      @@:
	or ax,ax
	ret
getendcentral endp

zip_allocfblk proc
	push si
	push di
	mov si,offset entryname
	mov di,ax
	invoke strlen, ds::si
	add ax,SIZE S_FBLK
	push ax
	add ax,12
	invoke malloc, ax
	pop cx
	.if !ZERO?
	    mov bx,ax
	    mov ax,zip_central.cz_ext_attrib
	    and ax,_A_FATTRIB
	    or  ax,zip_attrib
	    mov es,dx
	    mov es:[bx],ax
	    .if di == 2
		mov di,cx
		.if zip_central.cz_version_made == 0
		    .if byte ptr zip_central.cz_ext_attrib & _A_SUBDIR
			jmp @F
		    .endif
		.endif
		mov ax,zip_attrib
		or  ax,_A_SUBDIR
		mov es:[bx],ax
	    .else
		mov di,cx
		movmx es:[bx.fb_size],zip_central.cz_fsize
	    .endif
	  @@:
	    push dx
	    push bx
	    mov ax,zip_central.cz_date
	    mov es:[bx.fb_date],ax
	    mov ax,zip_central.cz_time
	    mov es:[bx.fb_time],ax
	    add bx,fb_name
	    invoke strcpy, dx::bx, ds::si
	    sub ax,fb_name
	    add di,ax
	  ifdef __386__
	    mov eax,zip_central.cz_off_local
	    stosd
	    mov eax,zip_central.cz_csize
	    stosd
	    mov eax,zip_central.cz_crc
	    stosd
	  else
	    mov ax,word ptr zip_central.cz_off_local
	    stosw
	    mov ax,word ptr zip_central.cz_off_local+2
	    stosw
	    mov ax,word ptr zip_central.cz_csize
	    stosw
	    mov ax,word ptr zip_central.cz_csize+2
	    stosw
	    mov ax,word ptr zip_central.cz_crc
	    stosw
	    mov ax,word ptr zip_central.cz_crc+2
	    stosw
	  endif
	    pop ax
	    pop dx
	.endif
	pop di
	pop si
	ret
zip_allocfblk endp

zip_readcentral proc
	push si
	push di
	mov ax,SIZE S_CZIP
	call oread
	jz @F
	    sub ax,ax
	    cmp es:[bx.cz_pkzip],ZIPHEADERID
	    jne @F
	    cmp es:[bx.cz_zipid],ZIPCENTRALID
	    jne @F
	    add STDI.ios_i,SIZE S_CZIP
	    dec ax
	    mov dx,arc_pathz
	    cmp es:[bx.cz_fnsize],dx
	    jbe @F
	    mov ax,es
	    mov ds,ax
	    mov ax,ss
	    mov es,ax
	    mov di,offset zip_central
	    mov si,bx
	    mov ax,cx
	    mov cx,SIZE S_CZIP / 2
	    cld
	    rep movsw
	    mov cx,[bx.cz_fnsize]
	    add bx,SIZE S_CZIP
	    sub ax,SIZE S_CZIP
	    cmp ax,cx
	    jae @readcentral_name
		mov ax,ss
		mov ds,ax
		mov ax,cx
		call oread
		jz @F
		mov cx,zip_central.cz_fnsize
		mov ax,es
		mov ds,ax
		mov ax,ss
		mov es,ax
	@readcentral_name:
	    mov si,bx
	    mov di,offset entryname
	    shr cx,1
	    rep movsw
	    jc @readc_movsb
	@readc_name:
	    mov ax,ss
	    mov ds,ax
	    mov byte ptr [di],0
	    mov ax,zip_central.cz_fnsize
	    add STDI.ios_i,ax
	    mov cx,ax
	    mov ax,_A_ARCHZIP or _A_ARCH
	    .if byte ptr zip_central.cz_bitflag & 1
		or ax,_A_ENCRYPTED
	    .endif
	    .if byte ptr zip_central.cz_bitflag & 8
		or ax,_A_EXTLOCHD
	    .endif
	    mov zip_attrib,ax
	    mov ax,'/'
	    dec di
	    .if [di] == al
		mov [di],ah
		or zip_attrib,_A_SUBDIR
		dec zip_central.cz_fnsize
	    .endif
	    mov di,zip_central.cz_extsize
	    add di,zip_central.cz_cmtsize
	    .if di
		mov ax,di
		call oread
		jz @F
		add STDI.ios_i,di
	    .endif
	    mov ax,1
      @@:
	test ax,ax
	pop di
	pop si
	ret
	@readc_movsb:
	    movsb
	    jmp @readc_name
zip_readcentral endp

zip_testcentral proc pascal uses si di wsub:dword
	mov si,offset entryname
	les di,[di.ws_arch]
	mov al,[di]
	.if al
	    mov al,0
	    mov cx,arc_pathz
	    inc cx
	    @@:
		dec cx
		jz @F
		mov al,[si]
		mov ah,[di]
		inc si
		inc di
		cmp ah,al
		je @B
		cmpaxi
		je @B
		cmp ax,'\/'
		je @B
	    @@:
	    sub al,ah
	    mov ax,0
	    jnz @F
	.endif
	mov si,word ptr wsub
	sub di,word ptr [si.ws_arch]
	mov si,offset entryname
	.if di
	    .if [di+entryname] == '/'
		mov ax,si
		inc ax
		add ax,di
		invoke strcpy, ds::si, ds::ax
	    .else
		jmp @F
	    .endif
	.endif
	.if entryname == ','
	    mov ax,si
	    inc ax
	    invoke strcpy, ds::si, ds::ax
	.endif
	invoke strchr, ds::si, '/'
	.if !ZERO?
	    mov bx,ax
	    mov byte ptr [bx],0
	    invoke wsearch, wsub, ds::si
	    .if ax == -1
		mov ax,2
	    .else
		xor ax,ax
	    .endif
	.else
	    invoke wsearch, wsub, ds::si
	    .if ax == -1
		mov ax,1
	    .else
		les bx,wsub
		les bx,es:[bx.ws_fcb]
		shl ax,2
		add bx,ax
		les bx,es:[bx]
		mov ax,zip_central.cz_date
		mov dx,zip_central.cz_time
		mov es:[bx.fb_time],dx
		mov es:[bx.fb_date],ax
		.if zip_central.cz_version_made == 0
		    mov ax,zip_central.cz_ext_attrib
		    or  ax,zip_attrib
		    and ax,_A_FATTRIB
		    mov es:[bx],ax
		.endif
		xor ax,ax
	    .endif
	.endif
      @@:
	ret
zip_testcentral endp

zip_findnext proc
	call zip_readcentral
	.while ax
	    inc ax
	    .if ax
		invoke zip_testcentral, si::di
	    .else
		mov ax,es:[bx.cz_extsize]
		add ax,es:[bx.cz_cmtsize]
		add ax,es:[bx.cz_fnsize]
		push ax
		call oread
		pop dx
		.break .if ZERO?
		add STDI.ios_i,dx
		xor ax,ax
	    .endif
	    .if ax
		call zip_allocfblk
		.break
	    .endif
	    call zip_readcentral
	.endw
	ret
zip_findnext endp

wzipread proc dist pascal public uses si di wsub:dword
local	alloc:byte
local	fblk:dword
local	rbuf[8192]:byte
	sub ax,ax
	mov STDI.ios_i,ax
	mov STDI.ios_c,ax
	mov STDI.ios_flag,ax
	mov alloc,al
	invoke malloc, 64000
	.if ax
	    mov cx,64000
	    mov alloc,1
	.else
	    lea ax,rbuf
	    mov dx,ss
	    mov cx,8192
	.endif
	mov STDI.ios_size,cx
	stom STDI.ios_bp
	les bx,wsub
	invoke strlen, es:[bx.ws_arch]
	mov arc_pathz,ax
	lodso wsub,si,di
	invoke wsfree, si::di
	invoke getendcentral, si::di, addr zip_endcent
	.if ZERO?
	    mov ax,-2
	.else
	    invoke fbupdir, _A_ARCHZIP
	    mov es,si
	    mov es:[di.ws_count],1
	    les bx,es:[di.ws_fcb]
	    stom es:[bx]
	    invoke oseek, zip_endcent.ze_off_cent, SEEK_SET
	    call zip_findnext
	    stom fblk
	    .while ax
		mov bx,ax
		mov al,es:[0004h]
		.if al & _A_SUBDIR
		  @@:
		    mov es,si
		    mov ax,es:[di.ws_count]
		    les bx,es:[di.ws_fcb]
		    shl ax,2
		    add bx,ax
		    movmx es:[bx],fblk
		    mov es,si
		    inc es:[di.ws_count]
		    mov ax,es:[di.ws_count]
		    .break .if ax >= es:[di.ws_maxfb]
		.else
		    add bx,fb_name
		    mov es,si
		    invoke cmpwarg, dx::bx, es:[di.ws_mask]
		    jnz @B
		    invoke free, fblk
		.endif
		call zip_findnext
		stom fblk
	    .endw
	    invoke close, STDI.ios_file
	    mov es,si
	    mov ax,es:[di]
	.endif
	.if alloc
	    mov si,ax
	    invoke free, STDI.ios_bp
	    mov ax,si
	.endif
	ret
wzipread endp

_TEXT	ENDS
endif
	END
