#!/usr/bin/perl # # Extract ZIX files # # Written by Alan Mizrahi, alan at mizrahi dot com dot ve (http://www.mizrahi.com.ve/) # # Thanks to Kenneth Sorling, nevershaveyourduck at gmail dot com (http://www.kennethsorling.se/) # for the file format # # WARNING: do NOT run any programs contained inside any .ZIX files, they are presumably # loaded with crap that can harm your computer. Media content (movies, sound) should be ok. # Read http://en.wikipedia.org/wiki/Winzix for more information # # first (and hopefully last) version: 20080124 [AM] # use strict; use warnings; use File::Basename; use Compress::Zlib; die "Syntax: unzix.pl " if $#ARGV < 0; my $in = $ARGV[0]; open IN, $in or die "Error opening $in: $!"; binmode IN; my $buffer; my $BUFSIZE = 8 * 1048576; my $r = read IN, $buffer, 6; die "Error reading $in: $!" if $r!=6; die "Not zix 2.0 format" if unpack('a6', $buffer) ne 'WINZIX'; $r = read IN, $buffer, 2; die "Error reading $in: $!" if $r!=2; die "New version of format, please contact the author" if unpack('n', $buffer) != 3; my $p = 8; while (!eof(IN)) { $r = read IN, $buffer, 43; die "Error reading $in: $!" if $r != 43; my ($compSize, $size, $fnLen, $sum) = unpack('x6Nx4Nx6nxC16', $buffer); $r = read IN, $buffer, $fnLen; die "Error reading $in: $!" if $r != $fnLen; my $fname = unpack("a$fnLen", $buffer); ($fname) = $fname =~/^\/*(.*)/; # convert to relative path print "Extracting $fname ($size bytes)\n"; my $dir = ''; for (split('/', dirname($fname))) { $dir.="$_/"; if (! -d $dir) { mkdir $dir or die "Error creating dir $dir: $!"; } } open OUT, ">$fname" or die "Error creating $fname: $!"; binmode OUT; my $zlib = inflateInit() or die "Error creating inflation stream"; my $rs = 0; # already read size while ($rs < $compSize) { my $bs = $BUFSIZE<($compSize-$rs)?$BUFSIZE:($compSize-$rs); # how much to read $r = read IN, $buffer, $bs; die "Error reading $in: $!" if $bs != $r; my ($outbuf, $status) = $zlib->inflate(\$buffer); die "Error uncompressing $in: zlib status: $status" if ($status != Z_OK && $status != Z_STREAM_END); syswrite OUT, $outbuf; $rs += $r; printf "%d/%d (%3d%%)\n", $rs, $compSize, ($rs * 100 /$compSize); } close OUT; } close IN; exit 0;