<?php if (!defined('PmWiki')) exit();

// Copyright 2006 Thomas Pitschel (parts adapted from attachdel.php)
// This is pmwiki code for including text files formatted in type
// writer style in wiki pages. The basic syntax is 
//
// (:includefile filename options:)
//
// and available options are 
//  "ext=txt" for specifying a collection of files by extension, 
//  "header=on|bold" to display the filename before the inclusion, 
//  "fontsize=8pt" for specifying the font size used, and
//  "order=[-]name|size|time|atime|mtime|ctime" for usual ordering,
// where atime, mtime, ctime are the times of last access or modification,
// and creation respectively.
//
// If filename is not given at least the "ext" option must be set.
// The filename must not contain relative paths _upward_ the dir
// hierarchy. Permission to include a file is based on the 
// permission level defined in $HandleAuth['includefile'] (which 
// defaults to read), with respect to the page where the markup 
// is located.
//
// Installation: copy IncludeFile.php to your cookbook directory and
// add include_once("$FarmId/cookbook/IncludeFile.php"); to your
// local/config.php.
//
// ver0.1, Aug 2006, ThomasP
//
// More info on www.pmwiki.org/wiki/Cookbook/IncludeFile

Markup('includefile', '<block',
  '/\\(:includefile\\s*(.*?):\\)/ei',
  "Keep(includeTextAsCodeFunc('$pagename',PSS('$1')))");
   
// Specify which permission level is required to _view_ the contents
// of files in the page directory: (here "read").
// Note that anyone with read and edit privileges on a page can thus
// display the contents of _all_ files in the corresponding directory,
// so is effectively granted a download permission!! Disable edit
// to display exactly the files you wish from a given directory.
SDV($HandleAuth['includefile'], 'read'); 

function getFormattedFileContents($filename, $fullfilename, &$opt) {
  if (@$opt['fontsize'] && preg_match('/^[0-9]{1,3}pt$/', $opt['fontsize'])) // with security check
    $htmlStyles = "font-size:" . $opt['fontsize'] . ";"; 

  $filecontents = implode('', file($fullfilename));
  $filecontentsEscaped = htmlspecialchars($filecontents);
  $filecontentsEscaped = str_replace(" ", "&nbsp;", $filecontentsEscaped);
  $filecontentsEscaped = str_replace("\n", "<br />", $filecontentsEscaped);
  $result = "<code class='escaped' style='$htmlStyles'>" . 
            $filecontentsEscaped . "</code>\n";
  $result = "<div style='margin-top:7px;'>\n" . $result . "</div>\n"; 
                               
  if (@$opt['header']) {
    $result = ((@$opt['header'] == 'bold') ? 
              "<b>$filename:</b>" : "$filename:") . "<br />\n" . $result;
  }
  return $result;
}

function includeTextAsCodeFunc($pagename, $args) {
  global $UploadDir, $UploadPrefixFmt;
  global $AuthFunction, $HandleAuth;

  $opt = ParseArgs($args);
  if (!(@$opt[''][0]) && !(@$opt['ext'])) 
    return "(:includefile:) failed: no arguments given.<br />\n";

  // retrieve filename from options and make sure it is well-behaved:
  $filename = @$opt[''][0]; $filename = str_replace('..', '', $filename);

  // permission check for accessing files in this page dir:
  if (!$AuthFunction($pagename, $HandleAuth['includefile'], false))
    return "(:includefile:) failed: Insufficient privileges to include files " .
           "from this directory.<br />\n";
  
  if (!(@$opt['ext'])) {
    $fullfilename = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename) . "/$filename";
      // This currently supports only including from the directory directly belonging to the wiki page.
      // No relative or absolute paths (as described on my (ThomasP) profile page) allowed at the moment.
    if (file_exists($fullfilename)) {
      return getFormattedFileContents($filename, $fullfilename, $opt);
    }
    return "(:includefile $filename:) failed: Could not open $filename in " .
           "directory for page $pagename.<br />\n";
  } else { // have a pattern instead of a single file
    $matchext = '/\\.('
                . implode('|', preg_split('/\\W+/', $opt['ext'], -1, PREG_SPLIT_NO_EMPTY))
                . ')$/i';
    $targetdir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
    $dirp = @opendir($targetdir);
    if (!$dirp) return "(:includefile:) failed: Unable to open $targetdir. <br />\n";
    $filelist = array();
    while (($filename=readdir($dirp)) !== false) {
      if ($filename{0} == '.') continue;
      if (@$matchext && !preg_match(@$matchext, $filename)) continue;
      if (strstr(@$opt['order'], 'size')) {
        $stat = stat("$targetdir/$filename");
	$filelist[$stat['size']] = $filename;
      } else
      if (strstr(@$opt['order'], 'atime')) {
        $stat = stat("$targetdir/$filename");
	$filelist[$stat['atime']] = $filename;
      } else
      if (strstr(@$opt['order'], 'ctime')) {
        $stat = stat("$targetdir/$filename");
	$filelist[$stat['ctime']] = $filename;
      } else
      if (strstr(@$opt['order'], 'time')) { // this includes the case "mtime"
        $stat = stat("$targetdir/$filename");
	$filelist[$stat['mtime']] = $filename;
      } else
      if (strstr(@$opt['order'], 'name')) {
	$filelist[$filename] = $filename;
      } else { // default
	$filelist[$filename] = $filename;
      }
    }
    closedir($dirp);
    if (@$opt['order']{0} == '-') arsort($filelist);
    else asort($filelist);
    $result = '';
    foreach($filelist as $sortkey=>$filename) {
      $result .= getFormattedFileContents($filename, "$targetdir/$filename", $opt) . "\n";
    }
    return $result;
  }
}