View in color | License | Download script | History |
30-Apr 15:54 UTC
[0.119] 15.028k
[0.119] 15.028k
zip.rREBOL [
Title: "ZIP explorer"
Date: 3-Dec-2001/13:11:09+1:00
Version: 0.1.0
File: %zip.r
Author: "Oldes"
Usage: "zip/examine %some-archive.zip ;will list the info"
Purpose: "Shows content of some ZIP archive"
Comment: {
^-This script does not explore all zip atributes, just search the "central directory block"
^-If you need something more you will have to look at ZIP spec. and enhance this script:
^-^-http://www.pkware.com/support/appnote.html
^-}
Email: %oliva--david--seznam--cz
library: [
level: 'advanced
platform: none
type: 'tool
domain: [file-handling broken]
tested-under: none
support: none
license: none
see-also: none
]
]
zip: context [
;event handlers - modify it if you need some other functionality
on-parse-file_head: does[show-info/file_head file_head]
on-parse-cde: does[show-info/central_dir_end cde]
;----------------------------------------------------------------
file_HEAD: cde: none
;help functions:
get-int: func[i][to-integer head reverse copy i]
getpart: func[bytes /local tmp][
tmp: copy/part bin bytes
bin: skip bin bytes
tmp
]
;-----------------
structure: make object! [
file_head: [
2 ;version made by
2 ;version needed to extract
2 ;general purpose bit flag
2 ;compression method
4 ;last mod file date/time
4 ;crc-32
4 ;compressed size
4 ;uncompressed size
2 ;file name length
2 ;extra field length
2 ;file comment length
2 ;disk number start
2 ;internal file attributes
4 ;external file attributes
4 ;relative offset of local header
;file name (variable size)
;extra field (variable size)
;file comment (variable size)
]
central_dir_end: [
4 ;end of central dir signature 4 bytes (0x06054b50)
2 ;number of this disk
2 ;number of the disk with the start of the central directory
2 ;total number of entries in the central directory on this disk
2 ;total number of entries in the central directory
4 ;size of the central directory
4 ;offset of start of central directory with respect to the starting disk number
2 ;.ZIP file comment length
;.ZIP file comment (variable size)
]
version_made_by: [
#{0000} "MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)"
#{0100} "Amiga"
#{0200} "OpenVMS"
#{0300} "Unix"
#{0400} "VM/CMS"
#{0500} "Atari ST"
#{0600} "OS/2 H.P.F.S."
#{0700} "Macintosh"
#{0800} "Z-System"
#{0900} "CP/M"
#{1000} "Windows NTFS"
#{1100} "MVS"
#{1200} "VSE"
#{1300} "Acorn Risc"
#{1400} "VFAT"
#{1500} "Alternate MVS"
#{1600} "BeOS"
#{1700} "Tandem"
]
]
show-info: make object! [
central_dir_end: func[cde /local n][
if 0 < n: get-int cde/2 [ print ["Number of this disk:" n]]
if not empty? n: last cde [ print ["ZIP comment:" mold n] ]
print head insert/dup copy "" "-" 71
]
file_head: func[fh][
if 0 < get-int fH/8 [ ;don't show dirs
print [
pad/left (to-string fh/16) 25
pad (get-int fH/7 ) 8 "/" pad/left (get-int fH/8) 8
pad/left msdate-to-date fH/5 20 ;modified date
select structure/version_made_by fH/1
tab
]
]
]
]
examine: func[file][
print ["ZIP file:" file]
bin: read/binary file
bin: find bin #{504b0506} ;end of central dir signature
cde: slice-bin bin structure/central_dir_end
insert tail cde to-string copy/part skip bin 22 get-int last cde
on-parse-cde
bin: skip head bin get-int cde/7 ;central directory structure
while [#{504b0102} = getpart 4][
file_HEAD: slice-bin getpart 42 structure/file_head
set [L1 L2 L3] reduce [get-int file_HEAD/9 get-int file_HEAD/10 get-int file_HEAD/11]
insert tail file_HEAD slice-bin getpart (L1 + L2 + L3) reduce [L1 L2 L3]
on-parse-file_head
]
]
];end of context
;other used functions:
pad: func [arg count /left /with ch /local txt L][
txt: make string! 10
L: (length? form arg) - count
either L > 0 [
txt: join copy/part form arg (count - 3) "..."
][
loop abs L [append txt either with [ch][" "]]
either left [
insert head txt arg
][
append txt arg
]
]
txt
]
msdate-to-date: func[
"Converts standard MS DOS binary time to Rebol's"
ms [binary! string!] /local to-int y m d h mi s
][
ms: enbase/base head reverse ms 2
to-int: func[v][
insert/dup v "0" 8 - length? v
to-integer debase/base head v 2
]
parse ms [
copy y 7 skip (y: 1980 + to-int y)
copy m 4 skip (m: to-int m)
copy d 5 skip (d: to-int d)
copy h 5 skip (h: to-int h)
copy mi 6 skip (mi: to-int mi)
copy s 5 skip (s: 2 * to-int s)
]
to-date rejoin [d "-" m "-" y "/" h ":" mi ":" s]
]
slice-bin: func [bin bytes /integers /local tmp b][
tmp: make block! length? bytes
forall bytes [
b: copy/part bin bytes/1
append tmp either integers [get-int b][b]
bin: skip bin bytes/1
]
tmp
] Notes
|