home *** CD-ROM | disk | FTP | other *** search
- package PPM::Compat;
- $VERSION = '3.00';
-
- use strict;
- use Data::Dumper;
- use XML::Parser;
-
- use constant PPM_PORT_PERL => 14533;
-
- sub read_ppm_xml {
- my ($file, $conf, $reps, $inst, $cmd, $extra) = @_;
- my $parser = XML::Parser->new(Style => 'Tree');
- my $tree = $parser->parsefile($file);
-
- die "Error: node PPMCONFIG not found in ppm.xml"
- unless $tree->[0] eq 'PPMCONFIG';
- $tree = $tree->[1];
-
- my $parse_elem = sub {
- my $ref = shift;
- my $tree = shift;
- my $key = shift;
- my $req = shift;
- my $content = shift; $content = 2 unless defined $content;
- my $cref = shift;
- my $i;
- for ($i=0; $i<@$tree; $i++) { last if $tree->[$i] eq $key }
- die "error: missing $key element in ppm.xml"
- if $req && $i >= @$tree;
- return if $i >= @$tree;
- $cref->($ref, $key, $content, $tree->[$i+1]) if $cref;
- $ref->{$key} = $tree->[$i+1][$content] unless $cref;
- };
-
- my $parse_attr = sub {
- my $ref = shift;
- my $tree = shift;
- my $key = shift;
- my $req = shift;
- my $keephash = shift;
- my $cref = shift;
- die "error: missing $key attribute in ppm.xml"
- if $req && not exists $tree->[0]{$key};
- $cref->($ref, $key, $keephash, $tree->[0]{$key}) if $cref;
- $ref->{$key} = $keephash ? $tree->[0] : $tree->[0]{$key} unless $cref;
- };
-
- $inst->{PPMPRECIOUS} = [];
- $parse_elem->($inst, $tree, 'PPMPRECIOUS', 0);
- for (split ';', $inst->{PPMPRECIOUS}) {
- push @{$inst->{precious}}, $_;
- }
- delete $inst->{PPMPRECIOUS};
-
- for (my $i=0; $i<@$tree; $i++) {
- my $k = $tree->[$i];
- my $v = $tree->[$i+1];
- if ($k eq 'OPTIONS') {
- my $tmp = $^O eq 'MSWin32' ? 'C:\Temp' : '/tmp';
- my @opts = qw(BUILDDIR DOWNLOADSTATUS REBUILDHTML);
- @$conf{@opts} = ($tmp, 16384, 0);
- $parse_attr->($conf, $v, 'BUILDDIR', 0);
- $parse_attr->($conf, $v, 'DOWNLOADSTATUS', 0);
- $parse_attr->($conf, $v, 'REBUILDHTML', 0);
- @$conf{qw(tempdir downloadbytes rebuildhtml)} = @$conf{@opts};
- delete @$conf{@opts};
-
- $cmd->{IGNORECASE} = 1;
- $parse_attr->($cmd, $v, 'IGNORECASE', 0);
- $cmd->{'case-sensitivity'} = $cmd->{IGNORECASE} ? '0' : '1';
- delete $cmd->{IGNORECASE};
-
- $inst->{ROOT} = '';
- $parse_attr->($inst, $v, 'ROOT', 0);
- $inst->{root} = $inst->{ROOT} if $inst->{ROOT};
- delete $inst->{ROOT};
-
- $parse_attr->($extra, $v, 'CLEAN', 0);
- $parse_attr->($extra, $v, 'CONFIRM', 0);
- $parse_attr->($extra, $v, 'FORCEINSTALL', 0);
- $parse_attr->($extra, $v, 'MORE', 0);
- $parse_attr->($extra, $v, 'TRACE', 0);
- $parse_attr->($extra, $v, 'TRACEFILE', 0);
- $parse_attr->($extra, $v, 'VERBOSE', 0);
- }
- elsif ($k eq 'PLATFORM') {
- @$inst{qw(CPU OSVALUE OSVERSION)} = ('x86', $^O, '0,0,0,0');
- $parse_attr->($inst, $v, 'CPU', 0);
- $parse_attr->($inst, $v, 'OSVALUE', 1);
- $parse_attr->($inst, $v, 'OSVERSION', 0);
- }
- elsif ($k eq 'REPOSITORY') {
- my %r;
- $parse_attr->(\%r, $v, 'LOCATION', 1);
- $parse_attr->(\%r, $v, 'NAME', 1);
- $parse_attr->(\%r, $v, 'USERNAME', 0);
- $parse_attr->(\%r, $v, 'PASSWORD', 0);
- fix_location(\$r{LOCATION});
-
- $reps->{$r{NAME}} = {
- url => $r{LOCATION},
- (defined $r{USERNAME} ? (username => $r{USERNAME}) : ()),
- (defined $r{PASSWORD} ? (password => $r{PASSWORD}) : ()),
- };
- }
- elsif ($k eq 'PACKAGE') {
- my %r;
- $parse_attr->(\%r, $v, 'NAME', 1);
- $parse_elem->(\%r, $v, 'LOCATION', 1);
- $parse_elem->(\%r, $v, 'INSTPACKLIST', 1);
- $parse_elem->(\%r, $v, 'INSTROOT', 1);
- $parse_elem->(\%r, $v, 'INSTDATE', 1);
- fix_location(\$r{LOCATION});
-
- # Regenerates the PPD: I wish XML::Parser could do this...
- my $cb = sub {
- my ($ref, $key, $index, $tree) = @_;
- my $i;
- for ($i=0; $i<@$tree; $i++) { last if $tree->[$i] eq 'SOFTPKG' }
- my $ppd = generate_ppd($tree->[$i], $tree->[$i+1]);
- $ref->{ppd} = $ppd if $ppd;
- };
- $parse_elem->(\%r, $v, 'INSTPPD', 1, 2, $cb);
- next if ($r{NAME} eq 'libwin32' and $^O ne 'MSWin32');
- $inst->{$r{NAME}} = \%r;
- }
- }
- }
-
- sub repository {
- my $rep = shift;
- my $ver = $^V ? sprintf("%vd", substr($^V,0,2)) : $];
-
- my $ppm3 = "http://ppm.ActiveState.com/PPM/ppmserver%s.plex?urn:/PPM/Server/SQL";
- my $ppm2 = "http://ppm.ActiveState.com/cgibin/PPM/ppmserver%s.pl?urn:/PPMServer";
- my $www = "http://ppm.ActiveState.com/PPMPackages/%s";
-
- my $verplat1 = "";
- my $verplat2 = $ver;
-
- if ($^V and $^V ge v5.8.0) {
- my %osmap = (MSWin32 => "windows");
- my $plat = $osmap{$^O} || $^O;
- $verplat1 = "-$ver-$plat";
- $verplat2 = "$ver-$plat";
- }
- my %reps = (
- ppm3 => sprintf($ppm3, $verplat1),
- ppm2 => sprintf($ppm2, $verplat1),
- www => sprintf($www, $verplat2),
- );
- return $reps{$rep};
- }
-
- sub fix_location {
- my $ref = shift;
- if ($$ref =~ m{^soap://}i and $$ref =~ m{ActiveState}) {
- $$ref = repository('www');
- }
- $$ref =~ s{soap://}{http://}i;
- if ($$ref =~ m[ActiveState.com/cgibin/PPM/ppmserver.pl\?]i) {
- $$ref = repository('ppm3');
- }
- }
-
- sub generate_ppd {
- my $tagname = shift;
- my $tree = shift;
- my $ppd = _generate_ppd($tagname, $tree);
- return qq{<?xml version="1.0" encoding="UTF-8"?>\n$ppd};
- }
- sub _generate_ppd {
- my $tagname = shift;
- my $tree = shift;
- return undef unless $tagname;
- my @lines;
- my $line = '<' . $tagname;
- if (%{$tree->[0] || {}}) {
- for my $key (keys %{$tree->[0]}) {
- my $val = $tree->[0]{$key};
- $line .= qq{ $key="$val"};
- }
- }
- $line .= '>';
- $line .= xml_encode(ref($tree->[2]) ? "\n" : $tree->[2]);
- push @lines, $line;
- my $start = ref($tree->[2]) ? 1 : 3;
- for (my $j=$start; $j<@$tree; $j++) {
- next unless $tree->[$j] =~ /^[A-Z]+$/;
- push @lines, _generate_ppd($tree->[$j], $tree->[$j+1]);
- }
- push @lines, "</$tagname>\n";
- wantarray ? @lines : join '', @lines;
- }
-
- sub xml_encode {
- local $_ = shift || '';
- s/&/&/g;
- s/</</g;
- s/>/>/g;
- $_;
- }
-
- sub batchify {
- my $exe = shift;
- my $perl = shift || $^X;
- my $batch = $exe;
- $batch =~ s/\.PL$//;
- $batch =~ s/\.pl$//;
- if ($^O eq 'MSWin32') {
- $batch .= '.bat';
- }
- # A bug in system() forces us to convert $exe to an 8.3 pathname on
- # Windows. Presumably there is no workaround in Unix.
- if ($^O eq 'MSWin32') {
- require Win32;
- $exe = Win32::GetShortPathName($exe);
- }
- system($perl, $exe, @_);
- unlink($exe) || die "can't delete $exe: $!";
- return $batch;
- }
-
-