1 Newsgroups: comp.lang.perl.modules
2 Subject: Best form for allowing module extension?
8 I am writing a module (Archive::Zip) that implements the basic read and
9 write functionality for Zip archive files. These files have provisions
10 for extensions for specific platforms: each member has an 'extra field'
11 that can contain OS-specific (or, indeed, any member-specific) data. The
12 overall format of this data is specified (<Header ID>, <count>, <data>),
13 but the actual contents depends on the Header ID.
15 Because I'm only working in a couple of operating environments, and
16 because I'm not trying to write a full "unzip" or "PKZIP" replacement, I
17 don't really want to try to interpret all of these formats.
19 From the PKWARE Appnote.txt file:
21 The current Header ID mappings defined by PKWARE are:
28 0x000f Patch Descriptor
30 Several third party mappings commonly used are:
32 0x4b46 FWKCS MD5 (see below)
35 0x4453 Windows NT security descriptor (binary ACL)
38 0x4c41 OS/2 access control list (text ACL)
39 0x4d49 Info-ZIP VMS (VAX or Alpha)
40 0x5455 extended timestamp
41 0x5855 Info-ZIP Unix (original, also OS/2, NT, etc)
44 0x7855 Info-ZIP Unix (new)
47 I want to make it easy for other people to provide this support without
50 Note that not all of these extensions have anything to do with file
51 permissions, although it may be helpful to provide one or more hooks for
54 * supply OS-specific filename
55 * open file for write (set permissions)
56 * after closing file (to set ownership, timestamps, etc.)
58 I can provide generic support for these extra fields, so that each
59 member can have 0 or more extra fields, each with a type tag and
62 I have seen File::Spec and File::Spec::Unix, etc., and don't think that
63 this scheme is appropriate, since you could have a zip file that was
64 produced on one operating system being extracted by another.
66 Also, it is possible to have multiple types of extra fields in a single
69 What I have thought about is this: a user who wants to interpret the
70 extended information in the zip members can include the appropriate
73 # ==================== in user's code ====================
74 use Archive::Zip; # basic functionality
75 use Archive::Zip::Unix; # to interpret Unix file permissions, etc.
76 use Archive::Zip::MD5; # to interpret MD5 extended info
78 my $zip = Archive::Zip->new();
79 $zip->read('ZIPFILE.ZIP');
80 foreach my $member ($zip->members())
82 foreach my $extraField ($member->extraFields())
84 print $extraField->info() . "\n";
89 # ==================== end user's code ====================
91 I can make an extensible class for writers of OS-specific modules to
94 # ==================== in my code ====================
95 package Archive::Zip::ExtraField;
98 # Each subclass must call this with their class name and tag ID.
101 my ($class, $tag) = @_;
102 $Handlers{ $tag } = $class;
105 # Overrideable methods
109 ref($self) . " " . $self->{tag} . " " . $self->{dataLength};
112 # Provide OS-specific name if any or undef
113 sub preferredFileName { undef }
115 # Returns numeric arg for open() call or undef
116 sub openPermissions { undef }
118 # Hook for doing things after file is extracted
119 # Called as: $extraField->afterClosingExtractedFile($fileName)
120 sub afterClosingExtractedFile { }
122 package Archive::Zip::Member;
124 # return array of extra fields
125 sub extraFields() { ... }
130 my ($preferredFileName) =
132 (map { $_->preferredFileName() } $self->extraFields());
133 my $fileName = $preferredFileName || $self->fileName();
134 # ... similar things for open permissions ...
135 my $fh = FileHandle->new($fileName, $openPermissions);
136 # ... extract data to fh ...
138 map { $_->afterClosingExtractedFile($fileName) }
139 $self->extraFields();
141 # ==================== end my code ====================
144 Does this seem like a good way to go? Any other suggestions?
148 currently: Stanwood, WA
149 email: ned@bike-nomad.com
150 homepage: http://www.bike-nomad.com