ZipArchive.st
changeset 2861 e5b9ccd39972
parent 2860 04b2ef9b1ef8
child 2893 08c695e14c86
equal deleted inserted replaced
2860:04b2ef9b1ef8 2861:e5b9ccd39972
  3154 !
  3154 !
  3155 
  3155 
  3156 entries
  3156 entries
  3157     "return a collection of fileName entries"
  3157     "return a collection of fileName entries"
  3158 
  3158 
  3159     |names|
  3159     ^ zipMembersByName keys
  3160 
  3160 !
  3161     names := OrderedCollection new.
  3161 
  3162 
  3162 file
  3163     self zipMembersDo:[:zipd |
  3163     ^ file
  3164         names add:(zipd fileName)
       
  3165     ].
       
  3166     ^ names
       
  3167 !
  3164 !
  3168 
  3165 
  3169 fileSize
  3166 fileSize
  3170     file notNil ifTrue:[
  3167     file notNil ifTrue:[
  3171         ^ file size
  3168         ^ file size
  3174 !
  3171 !
  3175 
  3172 
  3176 members
  3173 members
  3177     "return a collection of members"
  3174     "return a collection of members"
  3178 
  3175 
  3179     |members|
  3176     ^ zipMembersByName values.
  3180 
       
  3181     members := OrderedCollection new.
       
  3182 
       
  3183     self zipMembersDo:[:zipd |
       
  3184         members add:zipd
       
  3185     ].
       
  3186     ^ members
       
  3187 !
  3177 !
  3188 
  3178 
  3189 membersMatching:aFileMatchPattern
  3179 membersMatching:aFileMatchPattern
  3190     "return a collection of members which match aFileMatchPattern"
  3180     "return a collection of members which match aFileMatchPattern"
  3191 
  3181 
  3192     ^ self members select:[:m | aFileMatchPattern match:m fileName]
  3182     ^ self zipMembersByName select:[:m | aFileMatchPattern match:m fileName]
  3193 !
  3183 !
  3194 
  3184 
  3195 name
  3185 name
  3196     "return the (file-)name of this zipArchive"
  3186     "return the (file-)name of this zipArchive"
  3197 
  3187 
  3198     ^ archiveName
  3188     ^ archiveName
       
  3189 !
       
  3190 
       
  3191 numberOfEntries
       
  3192     "return the number of entries in the archive"
       
  3193 
       
  3194     ^ zipMembersByName size
  3199 !
  3195 !
  3200 
  3196 
  3201 pathName
  3197 pathName
  3202     "FileStream compatibility: answer the name of the underlying file - a String"
  3198     "FileStream compatibility: answer the name of the underlying file - a String"
  3203 
  3199 
  3209     endOfArchive   := anEndPosition.
  3205     endOfArchive   := anEndPosition.
  3210 !
  3206 !
  3211 
  3207 
  3212 size
  3208 size
  3213     ^self fileSize
  3209     ^self fileSize
       
  3210 !
       
  3211 
       
  3212 zipMembersByName
       
  3213     ^ zipMembersByName
  3214 ! !
  3214 ! !
  3215 
  3215 
  3216 !ZipArchive methodsFor:'error raising'!
  3216 !ZipArchive methodsFor:'error raising'!
  3217 
  3217 
  3218 error:anErrorString
  3218 error:anErrorString
  3257     ].
  3257     ].
  3258 
  3258 
  3259     archiveName := filename name.
  3259     archiveName := filename name.
  3260     mode := readOrWriteMode.
  3260     mode := readOrWriteMode.
  3261 
  3261 
       
  3262     self openFile.
  3262     mode ~~ #write ifTrue:[
  3263     mode ~~ #write ifTrue:[
  3263         |mustCloseFile|
  3264         |mustCloseFile|
  3264 
  3265 
  3265         mustCloseFile := true.
       
  3266 
       
  3267         self openFile.
       
  3268         [
  3266         [
       
  3267             mustCloseFile := true.
  3269             self readDirectory.
  3268             self readDirectory.
  3270             mustCloseFile := false.
  3269             mustCloseFile := false.
  3271 
  3270 
  3272             mode == #append ifTrue:[
  3271             mode == #append ifTrue:[
  3273                 members := self entries collect:[:eachEntryName | self findMember:eachEntryName] thenSelect:[:eachEntry | eachEntry notNil].
  3272                 members := self zipMembersByName values.
  3274                 members isEmptyOrNil ifTrue:[^ self].
  3273                 members isEmptyOrNil ifTrue:[^ self].
  3275 
  3274 
  3276                 maxStartPosition := (members collect:[:eachMember | eachMember fileStart]) max.
  3275                 maxStartPosition := members maxApplying:[:eachMember | self dataStartOf:eachMember].
  3277                 lastMember := members detect:[:eachMember | eachMember fileStart = maxStartPosition].
  3276                 lastMember := members detect:[:eachMember | eachMember dataStart = maxStartPosition].
  3278 
  3277 
  3279                 file position0Based:(startOfArchive + lastMember fileStart + lastMember compressedSize).
  3278                 file position0Based:(startOfArchive + lastMember dataStart + lastMember compressedSize).
  3280                 mode := #write.
  3279                 mode := #write.
  3281             ].
  3280             ].
  3282         ] ensure:[
  3281         ] ensure:[
  3283             mustCloseFile ifTrue:[self closeFile].
  3282             mustCloseFile ifTrue:[self closeFile].
  3284         ].
  3283         ].
  3285     ] ifFalse:[        
  3284     ] ifFalse:[
  3286         self openFile.
  3285         zipMembersByName := Dictionary new.
  3287     ].
  3286     ].
  3288 
  3287 
  3289     "Modified: / 31-08-2010 / 12:39:25 / sr"
  3288     "Modified: / 31-08-2010 / 12:39:25 / sr"
  3290 !
  3289 !
  3291 
  3290 
  3292 readFrom:aPositionableStream
  3291 readFrom:aPositionableStream
  3293     <resource: #obsolete>
  3292     <resource: #obsolete>
  3294     "initialize the archive to read from aPositionableStream.
  3293     "initialize the archive to read from aPositionableStream.
  3295      Obsolete - backward compatibility."
  3294      Obsolete - backward compatibility."
  3296 
  3295 
       
  3296     self obsoleteMethodWarning.
  3297     ^ self readingFrom:aPositionableStream
  3297     ^ self readingFrom:aPositionableStream
  3298 !
  3298 !
  3299 
  3299 
  3300 readingFrom:aPositionableStream
  3300 readingFrom:aPositionableStream
  3301     "initialize the archive to read from aPositionableStream"
  3301     "initialize the archive to read from aPositionableStream"
  3343     aPositionableStream isFileStream ifTrue:[
  3343     aPositionableStream isFileStream ifTrue:[
  3344         archiveName := aPositionableStream pathName.
  3344         archiveName := aPositionableStream pathName.
  3345     ] ifFalse:[
  3345     ] ifFalse:[
  3346         archiveName := 'internal stream'.
  3346         archiveName := 'internal stream'.
  3347     ].
  3347     ].
       
  3348     zipMembersByName := Dictionary new.
  3348 ! !
  3349 ! !
  3349 
  3350 
  3350 !ZipArchive methodsFor:'private'!
  3351 !ZipArchive methodsFor:'private'!
  3351 
  3352 
  3352 checkZipArchive:archiveFileName
  3353 checkZipArchive:archiveFileName
  3374             self addCentralZipDirectory
  3375             self addCentralZipDirectory
  3375         ].
  3376         ].
  3376         file close.
  3377         file close.
  3377         file := nil.
  3378         file := nil.
  3378     ]
  3379     ]
       
  3380 !
       
  3381 
       
  3382 dataStartOf:zipEntry
       
  3383     "fetch the absolute start address of the data of a given zipEntry.
       
  3384      Note: extra field and extra field length may be different from that in
       
  3385            the central directory entry. Sow e have to fetch the local header."
       
  3386 
       
  3387     |dataStart fileHeaderStart fileNameLength extraFieldLength|
       
  3388 
       
  3389     dataStart := zipEntry dataStart.
       
  3390     dataStart notNil ifTrue:[
       
  3391         ^ dataStart.
       
  3392     ].
       
  3393 
       
  3394     fileHeaderStart := zipEntry relativeLocalHeaderOffset + startOfArchive.
       
  3395     (fileHeaderStart + 30) > endOfArchive ifTrue: [
       
  3396         ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry end is out of the archive bounds'.
       
  3397     ].
       
  3398 
       
  3399     "Now read the fileHeader:
       
  3400         0  local file header signature     4 bytes  (0x04034b50)
       
  3401         4  version needed to extract       2 bytes
       
  3402         6  general purpose bit flag        2 bytes
       
  3403         8  compression method              2 bytes
       
  3404         10 last mod file time              2 bytes
       
  3405         12 last mod file date              2 bytes
       
  3406         14 crc-32                          4 bytes
       
  3407         18 compressed size                 4 bytes
       
  3408         22 uncompressed size               4 bytes
       
  3409         26 file name length (x)            2 bytes
       
  3410         28 extra field length (y)          2 bytes
       
  3411               fixd size total len:    30
       
  3412         30 file name (variable size)
       
  3413         30+x    extra field (variable size)
       
  3414         30+x+y  data
       
  3415      Note: extra field and extra field length may be different from that in
       
  3416            the central directory entry!!
       
  3417     "
       
  3418 
       
  3419     file position0Based:fileHeaderStart+26.
       
  3420     fileNameLength := file nextUnsignedShortMSB:false.
       
  3421     extraFieldLength := file nextUnsignedShortMSB:false.
       
  3422 
       
  3423     dataStart := fileHeaderStart + 30 + fileNameLength + extraFieldLength.
       
  3424 
       
  3425     (dataStart + (zipEntry compressedSize)) > endOfArchive ifTrue: [
       
  3426         ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry end is out of the archive bounds'.
       
  3427     ].
       
  3428     zipEntry dataStart:dataStart.
       
  3429 
       
  3430     ^ dataStart
  3379 !
  3431 !
  3380 
  3432 
  3381 openFile
  3433 openFile
  3382     |fn|
  3434     |fn|
  3383 
  3435 
  3613     ].
  3665     ].
  3614 
  3666 
  3615     "Modified: / 19-11-2010 / 16:23:36 / cg"
  3667     "Modified: / 19-11-2010 / 16:23:36 / cg"
  3616 !
  3668 !
  3617 
  3669 
  3618 addMember
       
  3619     "add a zipMember"
       
  3620 
       
  3621     |zmemb |
       
  3622 
       
  3623     self addMember:(zmemb := ZipMember new).
       
  3624     ^ zmemb.
       
  3625 
       
  3626     "Created: / 29.3.1998 / 18:22:25 / cg"
       
  3627     "Modified: / 9.9.1998 / 20:33:32 / cg"
       
  3628 !
       
  3629 
       
  3630 addMember:zmemb
  3670 addMember:zmemb
  3631     "add a zipMember"
  3671     "add a zipMember"
  3632 
  3672 
  3633     (firstEntry == nil) ifTrue:[
  3673     (firstEntry == nil) ifTrue:[
  3634         firstEntry := zmemb
  3674         firstEntry := zmemb
  3635     ] ifFalse:[
  3675     ] ifFalse:[
  3636         lastEntry next:zmemb.
  3676         lastEntry next:zmemb.
  3637     ].
  3677     ].
  3638     lastEntry := zmemb.
  3678     lastEntry := zmemb.
       
  3679     (zipMembersByName includesKey:zmemb fileName) ifTrue:[
       
  3680         "ignore duplicate entries for backward compatibility.
       
  3681          Argh: expecco once added wrong duplicates to the end of ets files.
       
  3682                The first entry is valid."
       
  3683         Transcript showCR:'Duplicate entry in ZIP (ignored): ', zmemb fileName.
       
  3684     ] ifFalse:[
       
  3685         zipMembersByName at:zmemb fileName put:zmemb.
       
  3686     ].
  3639     ^ zmemb.
  3687     ^ zmemb.
  3640 
  3688 
  3641     "Modified: / 30.3.1998 / 17:13:20 / cg"
  3689     "Modified: / 30.3.1998 / 17:13:20 / cg"
  3642     "Created: / 9.9.1998 / 20:33:06 / cg"
  3690     "Created: / 9.9.1998 / 20:33:06 / cg"
  3643 !
  3691 !
  3667 !
  3715 !
  3668 
  3716 
  3669 findMember:name
  3717 findMember:name
  3670     "find a zipMember by name"
  3718     "find a zipMember by name"
  3671 
  3719 
  3672 "/    zipMembersByName isNil ifTrue:[
  3720     ^ zipMembersByName at:name ifAbsent:[].
  3673 "/        zipMembersByName := Dictionary new.
       
  3674 "/        self zipMembersDo:[:zipd |
       
  3675 "/            zipMembersByName at:(zipd fileName) put:zipd.
       
  3676 "/        ].
       
  3677 "/    ].
       
  3678 "/    ^ zipMembersByName at:name ifAbsent:nil.
       
  3679 
       
  3680     self zipMembersDo:[:zipd |
       
  3681         (zipd fileName = name) ifTrue:[^ zipd].
       
  3682     ].
       
  3683     ^ nil
       
  3684 
       
  3685     "Modified: / 18-11-2010 / 20:23:35 / cg"
       
  3686 !
  3721 !
  3687 
  3722 
  3688 findMemberAllowForMissingTrailingSlash: name
  3723 findMemberAllowForMissingTrailingSlash: name
  3689     "find a zipMember by name. Allow for missing trailing slash for directories.
  3724     "find a zipMember by name. Allow for missing trailing slash for directories.
  3690      This method is currently used by JavaVM"
  3725      This method is currently used by JavaVM"
  3753         ^ self.
  3788         ^ self.
  3754     ] do:[
  3789     ] do:[
  3755         centralDirectory readFrom:file.
  3790         centralDirectory readFrom:file.
  3756 
  3791 
  3757         "/ set file position to start of central directory
  3792         "/ set file position to start of central directory
  3758         (pos0 - (centralDirectory centralDirectorySize)) < startOfArchive ifTrue: [
  3793         (pos0 - centralDirectory centralDirectoryStartOffset - centralDirectory centralDirectorySize) < startOfArchive ifTrue: [
  3759             ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - central directory start is out of the archive bounds'.
  3794             ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - central directory start is out of the archive bounds'.
  3760         ].
  3795         ].
  3761 
  3796 
       
  3797         startOfArchive := pos0 - centralDirectory centralDirectoryStartOffset - centralDirectory centralDirectorySize.
  3762         file position0Based:(pos0 - (centralDirectory centralDirectorySize)).
  3798         file position0Based:(pos0 - (centralDirectory centralDirectorySize)).
       
  3799 
       
  3800         zipMembersByName := Dictionary new:centralDirectory centralDirectoryTotalNoOfEntries.
  3763 
  3801 
  3764         "/ read central directory entries
  3802         "/ read central directory entries
  3765         1 to:(centralDirectory centralDirectoryTotalNoOfEntries) do:[:i |
  3803         1 to:(centralDirectory centralDirectoryTotalNoOfEntries) do:[:i |
  3766             |zipd filename_length centralFileHeaderSignature relative_offset_local_header 
  3804             |zipd filename_length centralFileHeaderSignature relative_offset_local_header 
  3767              posOfNextMember extra|
  3805              posOfNextMember extra|
  3774                 ZipFileFormatErrorSignal raiseRequestErrorString:' - file format error - bad centralHeaderSignature in: ' ,
  3812                 ZipFileFormatErrorSignal raiseRequestErrorString:' - file format error - bad centralHeaderSignature in: ' ,
  3775                                                 (file isFileStream ifTrue:[file pathName] ifFalse:['inStream']).
  3813                                                 (file isFileStream ifTrue:[file pathName] ifFalse:['inStream']).
  3776                 ^ self.
  3814                 ^ self.
  3777             ].
  3815             ].
  3778 
  3816 
  3779             zipd := ZipMember new.
  3817             zipd := ZipMember new readCentralDirectoryEntryFrom:file.
  3780             zipd readCentralDirectoryEntryFrom:file.
       
  3781             self addMember:zipd.
  3818             self addMember:zipd.
  3782         ].
  3819         ].
  3783 
  3820 
  3784         (file position + 6) > endOfArchive ifTrue: [
  3821         (file position + 6) > endOfArchive ifTrue: [
  3785             "/ archive has no digital signature
  3822             "/ archive has no digital signature
  3868 ! !
  3905 ! !
  3869 
  3906 
  3870 !ZipArchive methodsFor:'queries'!
  3907 !ZipArchive methodsFor:'queries'!
  3871 
  3908 
  3872 isValidPath: anArchivePathName
  3909 isValidPath: anArchivePathName
  3873     ^ self members
  3910     self zipMembersByName
  3874         contains:[:aMember |
  3911         keysDo:[:eachMemberName |
  3875             |fn|
  3912             ((eachMemberName startsWith:anArchivePathName,'/') 
  3876 
  3913              or:[eachMemberName = anArchivePathName]) ifTrue:[^ true]
  3877             fn := aMember fileName.
       
  3878             ((fn startsWith:anArchivePathName,'/') or:[(fn = anArchivePathName)])
       
  3879         ].
  3914         ].
  3880 
  3915 
  3881     "/ cg: wrong - what about (isValidPath:'foo'), if there is a file named 'foobar' ?!!
  3916     ^ false.
  3882 "/    self members do: [:aMember|
       
  3883 "/        (aMember fileName startsWith:anArchivePathName) ifTrue:[
       
  3884 "/            ^ true
       
  3885 "/        ].
       
  3886 "/    ].
       
  3887 "/    ^ false
       
  3888 ! !
  3917 ! !
  3889 
  3918 
  3890 !ZipArchive methodsFor:'reading'!
  3919 !ZipArchive methodsFor:'reading'!
  3891 
  3920 
  3892 extract:fileName
  3921 extract:fileName
  4036         ]
  4065         ]
  4037     ].
  4066     ].
  4038 !
  4067 !
  4039 
  4068 
  4040 withPositionAndMemberFor:fileName do:aBlock
  4069 withPositionAndMemberFor:fileName do:aBlock
  4041     |zmemb  |
  4070     |zmemb dataStart|
  4042 
  4071 
  4043     (file isNil or:[mode ~~ #read]) ifTrue:[
  4072     (file isNil or:[mode ~~ #read]) ifTrue:[
  4044         ^ self error: 'ZipArchive not open for reading ...'.
  4073         ^ self error: 'ZipArchive not open for reading ...'.
  4045     ].    
  4074     ].    
  4046 
  4075 
  4047     zmemb := self findMember:fileName.
  4076     zmemb := self findMember:fileName.
  4048     zmemb isNil ifTrue:[^ nil].
  4077     zmemb isNil ifTrue:[^ nil].
  4049     (zmemb fileStart + startOfArchive) > endOfArchive ifTrue: [
  4078 
  4050         ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry start is out of the archive bounds'.
  4079     dataStart := self dataStartOf:zmemb.
  4051     ].
  4080     aBlock value:zmemb value:dataStart.
  4052 
       
  4053     (zmemb fileStart + startOfArchive + (zmemb compressedSize)) > endOfArchive ifTrue: [
       
  4054         ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry end is out of the archive bounds'.
       
  4055     ].
       
  4056 
       
  4057     aBlock value:zmemb value:(zmemb fileStart + startOfArchive)
       
  4058 
  4081 
  4059     "Created: / 21-11-2010 / 11:51:41 / cg"
  4082     "Created: / 21-11-2010 / 11:51:41 / cg"
  4060 ! !
  4083 ! !
  4061 
  4084 
  4062 !ZipArchive methodsFor:'reading - stream'!
  4085 !ZipArchive methodsFor:'reading - stream'!
  4063 
  4086 
  4064 readStreamFor:nameOfFileInArchive
  4087 readStreamFor:nameOfFileInArchive
  4065     "open a stream on archive contents identified by nameOfFileInArchive"
  4088     "open a stream on archive contents identified by nameOfFileInArchive"
  4066 
  4089 
  4067     |zipEntry|
  4090     |zipEntry dataStart|
  4068 
  4091 
  4069     (file isNil or:[mode ~~ #read]) ifTrue:[
  4092     (file isNil or:[mode ~~ #read]) ifTrue:[
  4070         ^ OpenError raiseRequestWith:nameOfFileInArchive errorString:'ZipArchive not open for reading ...'.
  4093         ^ OpenError raiseRequestWith:nameOfFileInArchive errorString:'ZipArchive not open for reading ...'.
  4071     ].    
  4094     ].    
  4072 
  4095 
  4073     zipEntry := self findMember:nameOfFileInArchive.
  4096     zipEntry := self findMember:nameOfFileInArchive.
  4074     zipEntry isNil ifTrue:[
  4097     zipEntry isNil ifTrue:[
  4075         ^ OpenError raiseRequestWith:nameOfFileInArchive errorString:'ZipArchive member does not exist: '.
  4098         ^ OpenError raiseRequestWith:nameOfFileInArchive errorString:'ZipArchive member does not exist: '.
  4076     ].
  4099     ].
  4077 
  4100 
  4078     (zipEntry fileStart + startOfArchive) > endOfArchive ifTrue: [
  4101     dataStart := self dataStartOf:zipEntry.
  4079         ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry start is out of the archive bounds'.
  4102     file position0Based:dataStart.
  4080     ].
       
  4081 
       
  4082     (zipEntry fileStart + startOfArchive + (zipEntry compressedSize)) > endOfArchive ifTrue: [
       
  4083         ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry end is out of the archive bounds'.
       
  4084     ].
       
  4085 
       
  4086     file position0Based:(zipEntry fileStart + startOfArchive).
       
  4087 
  4103 
  4088     ^ (ZipReadStream zipFileStream:file zipEntry:zipEntry)
  4104     ^ (ZipReadStream zipFileStream:file zipEntry:zipEntry)
  4089         zipArchive:self.
  4105         zipArchive:self.
  4090 ! !
  4106 ! !
  4091 
  4107 
  4129 addDirectory: aDirectoryName
  4145 addDirectory: aDirectoryName
  4130     "do not create directories (isDirectory = true) - they are not compatible between operating systems"
  4146     "do not create directories (isDirectory = true) - they are not compatible between operating systems"
  4131 
  4147 
  4132     <resource: #obsolete>
  4148     <resource: #obsolete>
  4133 
  4149 
       
  4150     self obsoleteMethodWarning.
  4134     ^ self addFile:aDirectoryName withContents:nil compressMethod:COMPRESSION_STORED asDirectory:true.
  4151     ^ self addFile:aDirectoryName withContents:nil compressMethod:COMPRESSION_STORED asDirectory:true.
  4135 
  4152 
  4136     "Modified: / 19-11-2010 / 15:38:59 / cg"
  4153     "Modified: / 19-11-2010 / 15:38:59 / cg"
  4137 !
  4154 !
  4138 
  4155 
  4164         "/ if proceeded, write as uncompressed
  4181         "/ if proceeded, write as uncompressed
  4165         theCompressMethod := COMPRESSION_STORED
  4182         theCompressMethod := COMPRESSION_STORED
  4166     ].
  4183     ].
  4167 
  4184 
  4168     zipEntry := ZipMember new default.
  4185     zipEntry := ZipMember new default.
  4169     self addMember:zipEntry.
       
  4170 
       
  4171     theZipFileName := self validZipFileNameFrom:aFileName. 
  4186     theZipFileName := self validZipFileNameFrom:aFileName. 
  4172 
  4187 
  4173     zipEntry fileName: theZipFileName.
  4188     zipEntry fileName: theZipFileName.
  4174     zipEntry fileNameLength: theZipFileName size.
  4189     zipEntry fileNameLength: theZipFileName size.
  4175     zipEntry uncompressedSize: 0.
  4190     zipEntry uncompressedSize: 0.
  4230     "/ crc32 is allways reqired (not as written in docu to be zero in case of uncompressed mode)
  4245     "/ crc32 is allways reqired (not as written in docu to be zero in case of uncompressed mode)
  4231     zipEntry crc32:crc32.
  4246     zipEntry crc32:crc32.
  4232     zipEntry uncompressedSize: unCompressedDataSize.
  4247     zipEntry uncompressedSize: unCompressedDataSize.
  4233 
  4248 
  4234     zipEntry rewriteCrcAndSizeTo:file.
  4249     zipEntry rewriteCrcAndSizeTo:file.
       
  4250     self addMember:zipEntry.
       
  4251 
  4235     file setToEnd.
  4252     file setToEnd.
  4236 
  4253 
  4237     "Modified: / 19-11-2010 / 15:39:32 / cg"
  4254     "Modified: / 19-11-2010 / 15:39:32 / cg"
  4238 !
  4255 !
  4239 
  4256 
  4287                 "/ if proceeded, write as uncompressed
  4304                 "/ if proceeded, write as uncompressed
  4288                 
  4305                 
  4289                 theCompressMethod := COMPRESSION_STORED
  4306                 theCompressMethod := COMPRESSION_STORED
  4290             ].
  4307             ].
  4291     zipEntry := ZipMember new default.
  4308     zipEntry := ZipMember new default.
  4292     self addMember:zipEntry.
       
  4293     theZipFileName := self validZipFileNameFrom:aFileName.
  4309     theZipFileName := self validZipFileNameFrom:aFileName.
  4294     zipEntry fileName:theZipFileName.
  4310     zipEntry fileName:theZipFileName.
  4295     zipEntry fileNameLength:theZipFileName size.
  4311     zipEntry fileNameLength:theZipFileName size.
  4296 
  4312 
  4297     (self appendTrailingSlash and:[isDirectory]) ifTrue:[
  4313     (self appendTrailingSlash and:[isDirectory]) ifTrue:[
  4347     file setToEnd.
  4363     file setToEnd.
  4348     zipEntry writeTo:file.
  4364     zipEntry writeTo:file.
  4349     theCompressedData notNil ifTrue:[
  4365     theCompressedData notNil ifTrue:[
  4350         file nextPutBytes:zipEntry compressedSize from:theCompressedData.
  4366         file nextPutBytes:zipEntry compressedSize from:theCompressedData.
  4351     ].
  4367     ].
       
  4368     self addMember:zipEntry.
  4352 
  4369 
  4353     "Created: / 18-11-2010 / 19:31:10 / cg"
  4370     "Created: / 18-11-2010 / 19:31:10 / cg"
  4354     "Modified: / 19-11-2010 / 17:47:01 / cg"
  4371     "Modified: / 19-11-2010 / 17:47:01 / cg"
  4355     "Modified: / 19-11-2012 / 12:04:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
  4372     "Modified: / 19-11-2012 / 12:04:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
  4356 ! !
  4373 ! !
  4368 writeStreamFor:nameOfFileInArchive compressMethod:theCompressMethodArg
  4385 writeStreamFor:nameOfFileInArchive compressMethod:theCompressMethodArg
  4369     "create new entry in central directory"
  4386     "create new entry in central directory"
  4370 
  4387 
  4371     |zipEntry curTime curDate theZipFileName theCompressMethod|
  4388     |zipEntry curTime curDate theZipFileName theCompressMethod|
  4372 
  4389 
  4373     (file isNil or: [mode ~~ #write]) ifTrue: [
  4390     (file isNil or:[mode ~~ #write]) ifTrue: [
  4374         ^ self error: 'ZipArchive not open for writing ...'.
  4391         ^ self error: 'ZipArchive not open for writing ...'.
  4375     ].
  4392     ].
  4376 
  4393 
  4377     theCompressMethod := theCompressMethodArg.
  4394     theCompressMethod := theCompressMethodArg.
  4378 
  4395 
  4382         "/ if proceeded, write as uncompressed
  4399         "/ if proceeded, write as uncompressed
  4383         theCompressMethod := COMPRESSION_STORED
  4400         theCompressMethod := COMPRESSION_STORED
  4384     ].
  4401     ].
  4385 
  4402 
  4386     zipEntry := ZipMember new default.
  4403     zipEntry := ZipMember new default.
  4387     self addMember:zipEntry.
       
  4388 
       
  4389     theZipFileName := self validZipFileNameFrom:nameOfFileInArchive. 
  4404     theZipFileName := self validZipFileNameFrom:nameOfFileInArchive. 
  4390 
  4405 
  4391     zipEntry fileName: theZipFileName.
  4406     zipEntry fileName: theZipFileName.
  4392     zipEntry fileNameLength: theZipFileName size.
  4407     zipEntry fileNameLength: theZipFileName size.
  4393     zipEntry uncompressedSize: 0.
  4408     zipEntry uncompressedSize: 0.
  4404 
  4419 
  4405     "/ ensure that the file position is at the end
  4420     "/ ensure that the file position is at the end
  4406     file setToEnd.
  4421     file setToEnd.
  4407 
  4422 
  4408     zipEntry writeTo:file.
  4423     zipEntry writeTo:file.
       
  4424     self addMember:zipEntry.
  4409 
  4425 
  4410     ^ (ZipWriteStream zipFileStream:file zipEntry:zipEntry)
  4426     ^ (ZipWriteStream zipFileStream:file zipEntry:zipEntry)
  4411         zipArchive:self.
  4427         zipArchive:self.
  4412 
  4428 
  4413     "Modified: / 19-11-2010 / 15:38:54 / cg"
  4429     "Modified: / 19-11-2010 / 15:38:54 / cg"
  4642     "Created: / 09-04-1998 / 13:05:03 / cg"
  4658     "Created: / 09-04-1998 / 13:05:03 / cg"
  4643     "Modified: / 21-01-2011 / 00:05:00 / cg"
  4659     "Modified: / 21-01-2011 / 00:05:00 / cg"
  4644 !
  4660 !
  4645 
  4661 
  4646 dataStart
  4662 dataStart
  4647     "tell the file offset, where tha data of this zip entry starts"
  4663     "tell the file offset, where the data of this zip entry starts"
  4648     dataStart isNil ifTrue: [
  4664 
  4649         dataStart := relativeLocalHeaderOffset 
       
  4650                     + "C_SIZEOFLOCALHEADER" 30 
       
  4651                     + fileNameLength 
       
  4652                     + extraFieldLength.
       
  4653     ].
       
  4654     ^ dataStart
  4665     ^ dataStart
  4655     "Created: / 29.3.1998 / 18:28:40 / cg"
  4666     "Created: / 29.3.1998 / 18:28:40 / cg"
  4656 !
  4667 !
  4657 
  4668 
  4658 dataStart:something
  4669 dataStart:something
  4844     "Created: / 25-11-2011 / 17:59:47 / cg"
  4855     "Created: / 25-11-2011 / 17:59:47 / cg"
  4845 ! !
  4856 ! !
  4846 
  4857 
  4847 !ZipArchive::ZipMember methodsFor:'queries'!
  4858 !ZipArchive::ZipMember methodsFor:'queries'!
  4848 
  4859 
  4849 fileStart
       
  4850     ^ self dataStart
       
  4851     "/ ^ relative_offset_local_header + ZipArchive LREC_SIZE + 4 + name size
       
  4852 
       
  4853     "Created: / 29.3.1998 / 19:10:57 / cg"
       
  4854 !
       
  4855 
       
  4856 isDirectory
  4860 isDirectory
  4857     ^ 
  4861     ^ 
  4858     ((externalFileAttributes ? 0) bitTest:EXTERNALFILEATTRIBUTES_ISDIRECTORY)
  4862     ((externalFileAttributes ? 0) bitTest:EXTERNALFILEATTRIBUTES_ISDIRECTORY)
  4859         or:[uncompressedSize == 0 and:[fileName last = $/]].
  4863         or:[uncompressedSize == 0 and:[fileName last = $/]].
  4860 
  4864 
  4872     generalPurposBitFlag := aStream nextUnsignedShortMSB:false. 
  4876     generalPurposBitFlag := aStream nextUnsignedShortMSB:false. 
  4873     compressionMethod := aStream nextUnsignedShortMSB:false.
  4877     compressionMethod := aStream nextUnsignedShortMSB:false.
  4874     lastModFileTime := aStream nextUnsignedShortMSB:false.   
  4878     lastModFileTime := aStream nextUnsignedShortMSB:false.   
  4875     lastModFileDate := aStream nextUnsignedShortMSB:false.
  4879     lastModFileDate := aStream nextUnsignedShortMSB:false.
  4876     crc32 := aStream nextUnsignedLongMSB: false.
  4880     crc32 := aStream nextUnsignedLongMSB: false.
  4877     compressedSize := aStream nextLongMSB:false.     
  4881     compressedSize := aStream nextUnsignedLongMSB:false.     
  4878     uncompressedSize := aStream nextLongMSB:false.      
  4882     uncompressedSize := aStream nextUnsignedLongMSB:false.      
  4879     fileNameLength := aStream nextUnsignedShortMSB:false.   
  4883     fileNameLength := aStream nextUnsignedShortMSB:false.   
  4880     extraFieldLength := aStream nextUnsignedShortMSB:false. 
  4884     extraFieldLength := aStream nextUnsignedShortMSB:false. 
  4881     fileCommentLength := aStream nextUnsignedShortMSB:false. 
  4885     fileCommentLength := aStream nextUnsignedShortMSB:false. 
  4882     diskNumberStart := aStream nextUnsignedShortMSB:false.  
  4886     diskNumberStart := aStream nextUnsignedShortMSB:false.  
  4883     internalFileAttributes := aStream nextUnsignedShortMSB:false.   
  4887     internalFileAttributes := aStream nextUnsignedShortMSB:false.   
  4884     externalFileAttributes := aStream nextLongMSB:false.
  4888     externalFileAttributes := aStream nextUnsignedLongMSB:false.
  4885     relativeLocalHeaderOffset := aStream nextLongMSB:false.
  4889     relativeLocalHeaderOffset := aStream nextUnsignedLongMSB:false.
  4886 
  4890 
  4887 "/    (aStream position + fileNameLength) > endOfArchive ifTrue: [
  4891 "/    (aStream position + fileNameLength) > endOfArchive ifTrue: [
  4888 "/        ^ ZipArchive zipFileFormatErrorSignal raiseRequestErrorString:' - central directory entry out of archive bounds'.
  4892 "/        ^ ZipArchive zipFileFormatErrorSignal raiseRequestErrorString:' - central directory entry out of archive bounds'.
  4889 "/    ].
  4893 "/    ].
  4890     fileName:= String new:fileNameLength.
  4894     fileName:= String new:fileNameLength.
  4892 
  4896 
  4893     extraFieldLength ~~ 0 ifTrue: [
  4897     extraFieldLength ~~ 0 ifTrue: [
  4894 "/        (aStream position + extraFieldLength) > endOfArchive ifTrue: [
  4898 "/        (aStream position + extraFieldLength) > endOfArchive ifTrue: [
  4895 "/            ^ ZipArchive zipFileFormatErrorSignal raiseRequestErrorString:' - central directory entry out of archive bounds'.
  4899 "/            ^ ZipArchive zipFileFormatErrorSignal raiseRequestErrorString:' - central directory entry out of archive bounds'.
  4896 "/        ].
  4900 "/        ].
  4897         extraField := String new:extraFieldLength.
  4901         extraField := ByteArray new:extraFieldLength.
  4898         aStream nextBytes:extraFieldLength into:extraField.
  4902         aStream nextBytes:extraFieldLength into:extraField.
  4899     ].
  4903     ].
  4900 
  4904 
  4901     fileCommentLength ~~ 0 ifTrue: [
  4905     fileCommentLength ~~ 0 ifTrue: [
  4902 "/        (aStream position + fileCommentLength) > endOfArchive ifTrue: [
  4906 "/        (aStream position + fileCommentLength) > endOfArchive ifTrue: [
  5150 ! !
  5154 ! !
  5151 
  5155 
  5152 !ZipArchive class methodsFor:'documentation'!
  5156 !ZipArchive class methodsFor:'documentation'!
  5153 
  5157 
  5154 version
  5158 version
  5155     ^ '$Header: /cvs/stx/stx/libbasic2/ZipArchive.st,v 1.100 2012-12-05 14:38:32 stefan Exp $'
  5159     ^ '$Header: /cvs/stx/stx/libbasic2/ZipArchive.st,v 1.101 2012-12-08 20:05:28 stefan Exp $'
  5156 !
  5160 !
  5157 
  5161 
  5158 version_CVS
  5162 version_CVS
  5159     ^ '$Header: /cvs/stx/stx/libbasic2/ZipArchive.st,v 1.100 2012-12-05 14:38:32 stefan Exp $'
  5163     ^ '$Header: /cvs/stx/stx/libbasic2/ZipArchive.st,v 1.101 2012-12-08 20:05:28 stefan Exp $'
  5160 ! !
  5164 ! !
  5161 
  5165 
  5162 ZipArchive initialize!
  5166 ZipArchive initialize!