App-Phoebe

 view release on metacpan or  search on metacpan

lib/App/Phoebe/WebDAV.pm  view on Meta::CPAN

      or $path =~ m!^/file/?$! and $depth ne "0";
  push(@resources, map { "/file/$_" } files($stream, $host, $space, $re))
      if $id and $path eq "/file/$id";

  my $doc = XML::LibXML::Document->new('1.0', 'utf-8');
  my $multistat = $doc->createElement('D:multistatus');
  $multistat->setAttribute('xmlns:D', 'DAV:');
  $doc->setDocumentElement($multistat);

  my $dir = wiki_dir($host, $space);

  for my $resource (@resources) {
    # skip "hidden" files in the Unix world
    # and prevent path traversal using ..
    next if $resource =~ m!/\.!;
    # Names
    my $mime;
    my $is_dir;
    my $filename;
    if ($resource eq "/") {
      $filename = $dir;
      $is_dir = 1;
      $mime = "inode/directory";
    } elsif ($resource =~ m!/([^/]+)/$!) {
      # the raw directory is a "fake" and is actually the page directory
      $filename = $dir . ($1 eq "raw" ? "/page" : $resource);
      $is_dir = 1;
      $mime = "inode/directory";
    } elsif ($resource =~ m!/page/([^/]+)$!) {
      $filename = $dir . "/page/$1.gmi";
      $is_dir = 0;
      $mime = "text/html";
    } elsif ($resource =~ m!/raw/([^/]+)$!) {
      # the raw directory is a "fake" and is actually the page directory
      $filename = $dir . "/page/$1.gmi";
      $is_dir = 0;
      $mime = "text/plain";
    } elsif ($resource =~ m!/file/([^/]+)$!) {
      $filename = $dir . $resource;
      $is_dir = 0;
      if (-f "$dir/meta/$1") {
	# MIME-type for files requires opening the meta files! 😭
	my %meta = (map { split(/: /, $_, 2) } split /\n/, read_text "$dir/meta/$1");
	if ($meta{'content-type'}) {
	  $mime = $meta{'content-type'};
	}
      }
      $mime //= "application/octet-stream"; # fallback for binary files
    } else {
      $log->error("Requested $resource");
      next;
    }

    $log->debug("Processing $dir$resource");

    # A stat call for every file and every page! 😭
    my ($size, $mtime, $ctime, $sb) = (0, 0, 0);
    if ($resource eq "/login/") {
      $size = "";
      $mtime = $ctime = time;
    } elsif ($sb = stat($filename)) {
      $size = $sb->size;
      $mtime = $sb->mtime;
      $ctime = $sb->ctime;
    }

    # Modified time is stringified human readable HTTP::Date style
    $mtime = time2str($mtime);

    # Created time is ISO format: We need to tidy up the date format - isoz
    # isn't exactly what we want
    $ctime = time2isoz($ctime);
    $ctime =~ s/ /T/;
    $ctime =~ s/Z//;

    my $resp = $doc->createElement('D:response');
    $multistat->addChild($resp);
    my $href = $doc->createElement('D:href');
    $href->appendText(to_url($space, $resource));
    $resp->addChild($href);
    my $okprops = $doc->createElement('D:prop');
    my $nfprops = $doc->createElement('D:prop');
    my $prop;
    if ($reqinfo eq 'prop') {
      my %prefixes = ('DAV:' => 'D');
      my $i        = 0;
      for my $reqprop (@reqprops) {
        my ($ns, $name) = @$reqprop;
        if ($ns eq 'DAV:' && $name eq 'creationdate') {
          $prop = $doc->createElement('D:creationdate');
          $prop->appendText($ctime);
          $okprops->addChild($prop);
        } elsif ($ns eq 'DAV:' && $name eq 'getcontentlength') {
          $prop = $doc->createElement('D:getcontentlength');
          $prop->appendText($size);
          $okprops->addChild($prop);
        } elsif ($ns eq 'DAV:' && $name eq 'getcontenttype') {
          $prop = $doc->createElement('D:getcontenttype');
	  $prop->appendText($mime);
          $okprops->addChild($prop);
        } elsif ($ns eq 'DAV:' && $name eq 'getlastmodified') {
          $prop = $doc->createElement('D:getlastmodified');
          $prop->appendText($mtime);
          $okprops->addChild($prop);
        } elsif ($ns eq 'DAV:' && $name eq 'resourcetype') {
          $prop = $doc->createElement('D:resourcetype');
          if ($is_dir) {
            my $col = $doc->createElement('D:collection');
            $prop->addChild($col);
          }
          $okprops->addChild($prop);
        } else {
          my $prefix = $prefixes{$ns};
          if (!defined $prefix) {
            $prefix = 'i' . $i++;
	    # mod_dav sets <response> 'xmlns' attribute - whatever
            #$nfprops->setAttribute("xmlns:$prefix", $ns);
            $resp->setAttribute("xmlns:$prefix", $ns);
            $prefixes{$ns} = $prefix;
          }
          $prop = $doc->createElement("$prefix:$name");



( run in 2.151 seconds using v1.01-cache-2.11-cpan-437f7b0c052 )