Newsgroups: comp.lang.perl.modules Subject: Best form for allowing module extension? Reply-To: Followup-To: Keywords: Summary: I am writing a module (Archive::Zip) that implements the basic read and write functionality for Zip archive files. These files have provisions for extensions for specific platforms: each member has an 'extra field' that can contain OS-specific (or, indeed, any member-specific) data. The overall format of this data is specified (
, , ), but the actual contents depends on the Header ID. Because I'm only working in a couple of operating environments, and because I'm not trying to write a full "unzip" or "PKZIP" replacement, I don't really want to try to interpret all of these formats. From the PKWARE Appnote.txt file: The current Header ID mappings defined by PKWARE are: 0x0007 AV Info 0x0009 OS/2 0x000a NTFS 0x000c VAX/VMS 0x000d Unix 0x000f Patch Descriptor Several third party mappings commonly used are: 0x4b46 FWKCS MD5 (see below) 0x07c8 Macintosh 0x4341 Acorn/SparkFS 0x4453 Windows NT security descriptor (binary ACL) 0x4704 VM/CMS 0x470f MVS 0x4c41 OS/2 access control list (text ACL) 0x4d49 Info-ZIP VMS (VAX or Alpha) 0x5455 extended timestamp 0x5855 Info-ZIP Unix (original, also OS/2, NT, etc) 0x6542 BeOS/BeBox 0x756e ASi Unix 0x7855 Info-ZIP Unix (new) 0xfd4a SMS/QDOS I want to make it easy for other people to provide this support without changing my code. Note that not all of these extensions have anything to do with file permissions, although it may be helpful to provide one or more hooks for extracting files: * supply OS-specific filename * open file for write (set permissions) * after closing file (to set ownership, timestamps, etc.) I can provide generic support for these extra fields, so that each member can have 0 or more extra fields, each with a type tag and uninterpreted data. I have seen File::Spec and File::Spec::Unix, etc., and don't think that this scheme is appropriate, since you could have a zip file that was produced on one operating system being extracted by another. Also, it is possible to have multiple types of extra fields in a single zip file. What I have thought about is this: a user who wants to interpret the extended information in the zip members can include the appropriate extension modules: # ==================== in user's code ==================== use Archive::Zip; # basic functionality use Archive::Zip::Unix; # to interpret Unix file permissions, etc. use Archive::Zip::MD5; # to interpret MD5 extended info my $zip = Archive::Zip->new(); $zip->read('ZIPFILE.ZIP'); foreach my $member ($zip->members()) { foreach my $extraField ($member->extraFields()) { print $extraField->info() . "\n"; } $member->extract(); } # ==================== end user's code ==================== I can make an extensible class for writers of OS-specific modules to inherit from: # ==================== in my code ==================== package Archive::Zip::ExtraField; my %Handlers; # Each subclass must call this with their class name and tag ID. sub registerType { my ($class, $tag) = @_; $Handlers{ $tag } = $class; } # Overrideable methods sub info { my $self = shift; ref($self) . " " . $self->{tag} . " " . $self->{dataLength}; } # Provide OS-specific name if any or undef sub preferredFileName { undef } # Returns numeric arg for open() call or undef sub openPermissions { undef } # Hook for doing things after file is extracted # Called as: $extraField->afterClosingExtractedFile($fileName) sub afterClosingExtractedFile { } package Archive::Zip::Member; # return array of extra fields sub extraFields() { ... } sub extract { my $self = shift; my ($preferredFileName) = grep { $_ } (map { $_->preferredFileName() } $self->extraFields()); my $fileName = $preferredFileName || $self->fileName(); # ... similar things for open permissions ... my $fh = FileHandle->new($fileName, $openPermissions); # ... extract data to fh ... $fh->close(); map { $_->afterClosingExtractedFile($fileName) } $self->extraFields(); } # ==================== end my code ==================== Does this seem like a good way to go? Any other suggestions? -- Ned Konz currently: Stanwood, WA email: ned@bike-nomad.com homepage: http://www.bike-nomad.com