<?php if (!defined('PmWiki')) exit();
/**
  Local Directory List for PmWiki
  Written by (c) Petko Yotov 2009-2024
  Partly based on upload.php written by Patrick Michaud

  This text is written for PmWiki; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published
  by the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version. See pmwiki.php for full details
  and lack of warranty.

  Copyright 2009-2024 Petko Yotov www.pmwiki.org/petko
  Copyright 2004-2007 Patrick R. Michaud www.pmichaid.com
*/
# Version date
$RecipeInfo['DirList']['Version'] = '20241030';
SDV($EnableUpload, 1);

Markup('dirlist', 'block',
  '/^\\(:dirlist\\s*(.*?):\\)/i',
  "FmtDirList");

SDVA($HTMLStylesFmt, array(
'dirlist' => "table.dirlist td.d { font-weight: bold; }
table.dirlist td.s, table.dirlist td.t { text-align: right; }
",
// table.dirlist { border: 1px solid #dddddd; }
// table.dirlist td { border: 1px outset #dddddd; padding: 0px 2px; margin:2px; } 
));

SDVA($HandleActions, array( 'dirlistget' => 'HandleDirListGet' ));

SDVA($DirList, array(
  'Root' => "$FarmD/pub",
  'dirline'  => '<tr><td class="d"><a href="{$PageUrl}?dir=%4$s">%1$s</a></td><td class="s" data-sort="%5$d">%2$s</td><td class="t" data-sort="%6$d">%3$s</td></tr>',
  'fileline' => '<tr><td class="f"><a href="{$PageUrl}?action=dirlistget&amp;f=%4$s">%1$s</a></td><td class="s" data-sort="%5$d">%2$s</td><td class="t" data-sort="%6$d">%3$s</td></tr>',
  'listwrap' => '<table class="dirlist simpletable sortable filterable" border="0"><caption>%2$s</caption>
  <thead><tr>
    <th>$[Name]</th>
    <th>$[Size]</th>
    <th>$[Modified]</th>
  </tr></thead>
  <tbody>%1$s</tbody></table>',
  'defaultfilter' => "-*~,-*.bak",
  'parent' => '..',
  'TimeFmt' => "<time datetime='%L'>$TimeFmt</time>",
  'EncodeFn' => 'rawurlencode',
));

function FmtDirList($m) {
  extract($GLOBALS['MarkupToHTML']);
  global $DirList;
  $defn = $DirList['EncodeFn'];
  $opt = ParseArgs($m[1]);

  $Root = (@$opt[''][0]>'')? "{$DirList['Root']}/{$opt[''][0]}" : $DirList['Root'];
  
  $Ddir = preg_replace('!^\\/+!', '', stripmagic(@$_GET['dir']));
  
  $dir = ($Ddir>'')? "$Root/$Ddir" : $Root;
  
  $Fdir = substr($dir, strlen($DirList['Root'])+1);
  
  $dir = str_replace(array('..', '//'), array('', '/'), $dir);

  $filelist = $dirlist = array();
  $dirp = @opendir($dir);
  if($dirp) {
    while (($file=readdir($dirp)) !== false) {
      if ($file[0] == '.') continue;
      
      $f = "$dir/$file";
	  
      if(@$opt['dirfilter']>'' && is_dir($f)) {
        $a = MatchNames(array($file), $opt['dirfilter']);
        if(count($a)!=1) continue;
      }
      elseif(@$opt['filter']>'' && !is_dir($f)) {
        $a = MatchNames(array($file), $opt['filter']);
        if(count($a)!=1) continue;
      }

      if(intval(@$opt['nodefaultfilter'])==0) {
        $a = MatchNames(array($file), $DirList['defaultfilter']);
        if(count($a)!=1) continue;
      }
      $utime = intval(@filemtime($f));
      $time = PSFT($DirList['TimeFmt'], $utime);
      $time = preg_replace("/( datetime=')@/", '$1', $time);
      $usize = intval(@filesize($f));
      $size = FileSizeCompact($usize, 1, 1024);
      if(is_dir($f) ) $dirlist[$file] = array( $size, $time, $usize, $utime);
      else $filelist[$file] = array( $size, $time, $usize, $utime);
    }
    closedir($dirp);
    ksort($dirlist,  SORT_LOCALE_STRING);
    ksort($filelist, SORT_LOCALE_STRING);
  }
  else return "Failed to open '$dir'.";
  $dirup = implode('/', array_slice(explode('/', $Ddir), 0, -1));


  $html = "";
  if( ! IsEnabled($opt['nodirs'], 0)) {
    if($Ddir>'') $html .= sprintf($DirList['dirline'], $DirList['parent'], '', '', $dirup, '', '');
    foreach($dirlist as $name=>$a) {
      $url = $defn(preg_replace('!^\\/+!', '', "$Ddir/$name"));
      $html .= sprintf($DirList['dirline'], $name, $a[0], $a[1], $url, $a[2], $a[3]);
    }
  }
  if( ! IsEnabled($opt['nofiles'], 0)) {
    foreach($filelist as $name=>$a) {
      $url =  $defn(preg_replace('!^\\/+!', '',"$Fdir/$name"));
      $html .= sprintf($DirList['fileline'], $name, $a[0], $a[1], $url, $a[2], $a[3]);
    }
  }
  $wrap = sprintf($DirList['listwrap'], $html, $dir);
  return FmtPageName($wrap, $pagename);
}

function HandleDirListGet($pagename, $auth = 'read') {
  global $DirList, $DownloadDisposition, $UploadExts;
  SDV($DownloadDisposition, "inline");
  $page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
  if (!$page) Abort("?cannot read $pagename");
  
  $f = str_replace(array('..', '/.'), array('', ''), @$_REQUEST['f']);
  $f = preg_replace('/^\\/+/', '', $f);

  $filepath = $DirList['Root'].'/'.$f;
  if (!$f || !file_exists($filepath)) {
    header("HTTP/1.0 404 Not Found");
    Abort("?requested file not found");
    exit();
  }
  preg_match('/\\.([^.]+)$/',$filepath,$match);
  if (@$UploadExts[@$match[1]])
    header("Content-Type: {$UploadExts[@$match[1]]}");
  else header("Content-Type: text/plain");
  header("Content-Length: ".filesize($filepath));
  $upname = preg_replace("/^.*?\\/+/", '', $f);
  header("Content-disposition: $DownloadDisposition; filename=\"$upname\"");
  $fp = fopen($filepath, "r");
  if ($fp) {
    while (!feof($fp)) echo fread($fp, 4096);
    fclose($fp);
  }
  exit();
}