Fuse-PDF

 view release on metacpan or  search on metacpan

lib/Fuse/PDF/ContentFS.pm  view on Meta::CPAN

   my ($self) = @_;
   return {
      type => 'd',
      content => {
         map { $_ => \&_page } 1 .. $self->{pdf}->numPages,
      },
   };
}

sub _revisions {
   my ($self) = @_;
   my @revisions = map { $_->{pdf}->{content} } $self->all_revisions;
   return {
      type => 'd',
      content => {
         map { @revisions - $_ => { type => 'f', content => $revisions[$_] } } 0 .. $#revisions,
      },
   };
}

sub _metadata {
   my ($self) = @_;

   my $trailer = $self->{pdf}->{trailer};
   my %meta;
   if ($trailer->{Info}) {
      %meta = (%{$self->{pdf}->getValue($trailer->{Info})}, %meta);
   }
   if ($trailer->{ID} && 'array' eq $trailer->{ID}->{type}) {
      $meta{ID} = CAM::PDF::Node->new('string', $self->{pdf}->writeAny($trailer->{ID}));
   }
   #print STDERR "@{[sort keys %meta]}\n";
   my @keys = grep { $SCALARS{$meta{$_}->{type}} } keys %meta;
   return {
      type => 'd',
      content => {
         map { $_ => { type => 'f', content => $meta{$_}->{value} } } @keys,
      },
   };
}

sub _root {
   my ($self) = @_;
   return {
      type => 'd',
      content => {
         metadata => \&_metadata,
         revisions => \&_revisions,
         pages => \&_pages,
         filesystems => \&_filesystems,
      },
   };
}

sub _file {
   my ($self, $path) = @_;

   my $nsymlinks = 0;

   my @dirs = ($self->_root);
   my @path = split m{/}xms, $path;

   for (my $i = 0; $i < @path; ++$i) {    ##no critic(ProhibitCStyleForLoops)
      my $entry = $path[$i];
      next if q{} eq $entry;

      my $type = $dirs[-1]->{type};
      return ENOTDIR() if 'd' ne $type;
      next if q{.} eq $entry;
      if (q{..} eq $entry) {
         pop @dirs;
         return EACCESS() if !@dirs;      # tried to get parent of root
      }

      my $next = $dirs[-1]->{content}->{$entry};
      return ENOENT() if !$next;
      
      if ('CODE' eq ref $next) {
         $next = $self->$next($i, \@path);
      }
      return ENOENT() if !$next;
      if ('HASH' ne ref $next) {
         my $rest_of_path = join q{/}, q{}, @path[$i+1 .. $#path];
         #print STDERR "passing on $rest_of_path to ".ref($next)."\n";
         return ($next, $rest_of_path);
      }

      my $f = $next;
      if ('l' eq $f->{type}) {
         if ($i != $#path) {
            return ELOOP() if ++$nsymlinks >= $ELOOP_LIMIT;
            my $linkpath = $f->{content};

            # cannot leave the filesystem; must be relative
            return EACCESS() if $linkpath =~ m{\A /}xms;

            splice @path, $i + 1, 0, split m{/}xms, $linkpath;
         }
      }
      push @dirs, $f;
   }

   return $dirs[-1] || ENOENT();
}

1;

__END__

=pod

=for stopwords pdf runtime EIO

=head1 NAME

Fuse::PDF::ContentFS - Represent actual PDF document properties as files

=head1 SYNOPSIS

    use Fuse::PDF::ContentFS;
    my $fs = Fuse::PDF::ContentFS->new({pdf => CAM::PDF->new('my_doc.pdf')});
    $fs->fs_read('/');

or

    % mount_pdf --all my_doc.pdf /Volumes/my_doc_pdf
    % cd /Volumes/my_doc_pdf
    % ls
    filesystems  metadata  pages  revisions
    % ls metadata/
    CreationDate  Creator  ID  ModDate  Producer
    % cat metadata/Producer
    Adobe PDF library 5.00
    % ls pages
    1
    % ls pages/1
    fonts  images  layout.txt  text
    % ls pages/1/text
    formatted_text.txt  plain_text.txt      
    % cat pages/1/text/plain_text.txt 
    F u s e : : P D F  -  E m b e d  a  f i l e s y s t e m  i n  a  P D F  d o c u 
    m e n t
    C h r i s  D o l a n  < c d o l a n @ c p a n . o r g >
    T o  g e t  s o f t w a r e  t h a t  c a n  i n t e r a c t  w i t h  t h i s  
    f i l e s y s t e m ,  s e e
    h t t p : / / s e a r c h . c p a n . o r g / d i s t / F u s e - P D F /
    % cat pages/1/fonts/TT0/BaseFont 
    HISDQN+Helvetica
    % ls pages/1/images/
    1.pdf  2.pdf  3.pdf  4.pdf
    % open pages/1/images/1.pdf
    % cd /
    % umount /Volumes/my_doc_pdf

=head1 LICENSE

Copyright 2007-2008 Chris Dolan, I<cdolan@cpan.org>



( run in 1.332 second using v1.01-cache-2.11-cpan-71847e10f99 )