summaryrefslogtreecommitdiffstats
path: root/iphone/bin/Mac/Finder/AliasRecord.pm
diff options
context:
space:
mode:
Diffstat (limited to 'iphone/bin/Mac/Finder/AliasRecord.pm')
-rwxr-xr-xiphone/bin/Mac/Finder/AliasRecord.pm169
1 files changed, 169 insertions, 0 deletions
diff --git a/iphone/bin/Mac/Finder/AliasRecord.pm b/iphone/bin/Mac/Finder/AliasRecord.pm
new file mode 100755
index 0000000..06f68f6
--- /dev/null
+++ b/iphone/bin/Mac/Finder/AliasRecord.pm
@@ -0,0 +1,169 @@
+package Mac::Finder::AliasRecord;
+
+# Generate(/Parse) a Mac "alias record" binary string/file.
+#
+# Currently just enough is implemented to satisfy immediate requirements
+# (ie, write backgroundImageAlias to .DS_Store for DMG)
+#
+# based on these documents:
+# http://www.geocities.com/xhelmboyx/quicktime/formats/alias-layout.txt
+# http://sebastien.kirche.free.fr/python_stuff/MacOS-aliases.txt
+#
+# FIXME interface is very poor...
+
+use warnings;
+use strict;
+use DateTime;
+use File::Spec;
+use File::Spec::Mac;
+use Encode qw(encode);
+require Exporter;
+
+our $VERSION = '0.1';
+our @ISA = qw(Exporter);
+
+my %FSEncodings = (
+ MacFS => ['RW', ''],
+ MFS => ['RW', ''],
+ HFS => ['BD', ''],
+ 'HFS+' => ['H+', ''],
+
+ AudioCD => ['', 'JH'],
+ ISO9660 => ['', 'AG'],
+ FAT => ['', 'IS'],
+ Joliet => ['', 'Jo'],
+ 'ISO9660+Joliet' => ['', 'Jo'],
+);
+
+my %DiskEncodings = (
+ HD => 0,
+ FixedHD => 0,
+ Network => 1,
+ NetworkDisk => 1,
+ Floppy => 4,
+ Floppy1440 => 4,
+ Other => 5,
+ OtherDisk => 5,
+);
+
+my %RecordEncodings = (
+ parentDir => 0x00,
+ absolutePath => 0x02,
+ unicodeFile => 0x0e,
+ unicodeVolume => 0x0f,
+ volumePath => 0x12,
+);
+
+sub new {
+ my $class = shift || __PACKAGE__;
+ my $self = {
+ aliasCreator => '',
+ aliasVersion => 2,
+ aliasType => 'file',
+ volume => '',
+ volumeCreated => 0,
+ volumeFS => 'HFS',
+ volumeDisk => undef,
+ volumeAttrs => 0,
+ directoryID => 0,
+ file => '',
+ fileID => 0,
+ fileCreated => 0,
+ fileType => '',
+ fileCreator => '',
+ nlvlFrom => -1,
+ nlvlTo => -1,
+ records => { },
+ @_
+ };
+ if(exists($self->{path})) {
+ my $path = $self->{path};
+ my ($vol, $dir, $file) = File::Spec::Mac->splitpath($path);
+ $vol =~ s/:$//;
+ my @dir = File::Spec::Mac->splitdir($dir);
+ while(@dir && !$dir[0]) {
+ shift(@dir);
+ }
+ while(@dir && !$dir[-1]) {
+ pop(@dir);
+ }
+ $self->{volume} ||= $vol;
+ $self->{records}{unicodeVolume} ||=
+ pack('na*', length($vol), encode('utf-16be', $vol));
+
+ $self->{file} ||= $file;
+ $self->{records}{parentDir} ||= $dir[-1]
+ if(@dir);
+ $self->{records}{absolutePath} ||= $path;
+ $self->{records}{volumePath} ||= File::Spec->catfile('', @dir, $file);
+ $self->{records}{unicodeFile} ||=
+ pack('na*', length($file), encode('utf-16be', $file));
+ }
+ return(bless($self, ref($class) || $class));
+}
+
+sub toFSTime {
+ my $val = shift;
+ if(ref($val) && $val->isa("DateTime")) {
+ $val = $val->epoch - DateTime->new(year => 1904)->epoch();
+ }
+ return($val);
+}
+
+sub write {
+ my ($self, $out) = @_;
+
+ my $aliasType = $self->{aliasType};
+ $aliasType = (($aliasType =~ /^d(ir(ectory)?)?$/i && 1) ||
+ ($aliasType !~ /^f(ile)?$/ && $aliasType) || 0);
+
+ my $volumeCreated = toFSTime($self->{volumeCreated});
+ my $volumeFS = $self->{volumeFS};
+ if(ref($volumeFS) ne 'ARRAY') {
+ $volumeFS = $FSEncodings{$volumeFS} || ['', ''];
+ }
+
+ my $volumeDisk = $self->{volumeDisk};
+ if(!defined($volumeDisk)) {
+ if($volumeFS->[0] eq 'H+') {
+ $volumeDisk = 'Floppy';
+ }
+ elsif($volumeFS->[0]) {
+ $volumeDisk = 'HD';
+ }
+ else {
+ $volumeDisk = 'Other';
+ }
+ }
+ $volumeDisk = (exists($DiskEncodings{$volumeDisk})
+ ? $DiskEncodings{$volumeDisk}
+ : $volumeDisk);
+
+ my $fileCreated = toFSTime($self->{fileCreated});
+
+ my $buf =
+ pack('nn (C/a @28)Na2n N(C/a @64)NNa4a4 n!n!Na2 x10 (n!n/ax!2)*',
+ $self->{aliasVersion}, $aliasType,
+ $self->{volume}, $volumeCreated, $volumeFS->[0], $volumeDisk,
+ $self->{directoryID}, $self->{file}, $self->{fileID}, $fileCreated,
+ $self->{fileType}, $self->{fileCreator}, $self->{nlvlFrom},
+ $self->{nlvlTo}, $self->{volumeAttrs}, $volumeFS->[1],
+ map(((exists($RecordEncodings{$_}) ? $RecordEncodings{$_} : $_)
+ => $self->{records}{$_}),
+ keys(%{$self->{records}})),
+ (-1, ''));
+ $buf = pack('a4n', $self->{aliasCreator}, length($buf) + 6) . $buf;
+
+ if(!$out) {
+ return($buf);
+ }
+ elsif(ref($out) eq 'GLOB') {
+ print $out $buf;
+ }
+ else {
+ open(my $outfh, '>', $out) || die;
+ print $outfh $buf;
+ }
+}
+
+1;