view faptool.php @ 1096:bbc0a3d0b51e

Major renaming / refactor of site messages. Some that were previously modifiable from admin interface are now "hardcoded" in the configuration file. Having these settings made modifiable from there made no sense and just took space in the UI.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 27 Jan 2017 22:15:06 +0200
parents 1f77195b4f95
children 0a2117349f46
line wrap: on
line source

#!/usr/bin/php
<?php
//
// FAPWeb - Simple Web-based Demoparty Management System
// Special entry/preview/etc backend management commandline utility
// (C) Copyright 2014-2017 Tecnic Software productions (TNSP)
//
if (!file_exists(realpath(dirname(__FILE__))."/mconfig.inc.php"))
{
  die(
    "ERROR: Missing site configuration file. Please copy ".
    "'mconfig.inc.php.example' to 'mconfig.inc.php' and ".
    "edit it as needed.\n");
}

require_once "mconfig.inc.php";
require_once "msite.inc.php";


function wtGetExecutable($name, $path = FALSE)
{
  if (stChkSetting($name."_exe"))
    return stGetSetting($name."_exe");
  else
    return $name;
}


function wtGetExecutableArgs($name)
{
  if (stChkSetting($name."_args"))
    return " ".stGetSetting($name."_args")." ";
  else
    return "";
}


function wtConvertImage($inFilename, $outFilename, $outDim, $outFormat, $outQuality, $thumb, $useGfxConv)
{
  global $setPreviewPath;
  $isTemp = FALSE;

  if ($useGfxConv)
  {
    // Oh great .. we need gfxconv here because Imagick handles ILBM like shit
    $tmpFilename = tempnam($setPreviewPath, "tmp");
    $isTemp = TRUE;
    if (wtExec(wtGetExecutable("gfxconv"),
      wtGetExecutableArgs("gfxconv").
      escapeshellarg($inFilename)." -f png -o ".escapeshellarg($tmpFilename),
      0) === false)
      return FALSE;

    if (!file_exists($tmpFilename))
    {
      echo "ERROR: gfxconv did not output a temporary conversion inbetween.\n";
      return FALSE;
    }
  }
  else
    $tmpFilename = $inFilename;

  // Create conversion entity
  $img = new Imagick($tmpFilename);
  if ($img === FALSE)
  {
    echo "ERROR: Oh noes! ImageMagick could not digest the file '".$tmpFilename."' (".$inFilename.")\n";
    return FALSE;
  }

  if ($outDim !== FALSE)
  {
    // Get dimensions, setup background  
    $dim = $img->getImageGeometry();
//    $img->setBackgroundColor(imagick::COLOR_BLACK);
    $img->setGravity(imagick::GRAVITY_CENTER);

    // Act based on image size vs. desired size and $thumb mode
    if ($thumb || $dim["width"] > $outDim[0] || $dim["height"] > $outDim[1])
    {
      // Image is larger
      $img->resizeImage($outDim[0], $outDim[1], Imagick::FILTER_QUADRATIC, 1);
      $img->setImageExtent($outDim[0], $outDim[1]);
      $img->normalizeImage();
      $img->unsharpMaskImage(0, 0.5, 1, 0.05);
    }
    else
    if ($dim["width"] < $outDim[0] || $dim["height"] < $outDim[1])
    {
      // Image is smaller than requested dimension(s)?
      $img->resizeImage($outDim[0], $outDim[1], Imagick::FILTER_POINT, 1);
      $img->setImageExtent($outDim[0], $outDim[1]);
    }
  }

  $img->setFormat($outFormat);
  $img->setCompressionQuality($outQuality);

  $img->stripImage();
  $img->writeImage($outFilename);
  $img->removeImage();
  return TRUE;
}


function wtRenderSample($inFilename, $outFilename)
{
  $sfreq     = intval(stGetSetting("sampleFreq"));
  $sduration = intval(stGetSetting("sampleDuration"));
  $schannels = intval(stGetSetting("sampleChannels"));

  return wtExec(
    wtGetExecutable("openmpt123")
    ,
    "--force --quiet ".
    "--samplerate ".$sfreq." ".
    "--channels ".$schannels." ".
    "--end-time ".($sduration)." ".
    wtGetExecutableArgs("openmpt123").
    escapeshellarg($inFilename)." -o ".escapeshellarg($outFilename),
    0);
}


function wtConvertSample($inFilename, $outFilename, $outOpts)
{
  $sfreq     = intval(stGetSetting("sampleFreq"));
  $sduration = intval(stGetSetting("sampleDuration"));
  $schannels = intval(stGetSetting("sampleChannels"));

  $optStr = "";
  foreach ($outOpts as $okey => $oval)
    $optStr .= $okey." ".$oval." ";

  return wtExec(
    wtGetExecutable("avconv"),
    wtGetExecutableArgs("avconv").
    "-y -v 1 -t ".intval($sduration)." ".
    "-i ".escapeshellarg($inFilename).
    " ".$optStr." -ac ".$schannels.
    " -map_metadata -1 ".
    escapeshellarg($outFilename));
}


function wtEntryToSource($compo, $inFilename, $edata, $entryFilename, &$outData, &$outFilename, $force)
{
  // Does compo preview type match this file class?
  if ($edata["class"] != $compo["preview_type"])
    return FALSE;

  switch ($edata["class"])
  {
    case EFILE_AUDIO: $fext = "wav"; break;
    case EFILE_IMAGE: $fext = "png"; break;
    default:
      return FALSE;
  }

  $outFilename = stReplaceFileExt($entryFilename, "_preview.".$fext);
  if (!$force && file_exists($outFilename) && filemtime($outFilename) >= filemtime($entryFilename))
    return TRUE;

  printf("GENERATING: %s -> %s\n", $inFilename, $outFilename);

  switch ($edata["class"])
  {
    case EFILE_AUDIO:
      if ($edata["mime"] == "audio/x-mod")
        $res = wtRenderSample($inFilename, $outFilename);
      else
        $res = wtConvertSample($inFilename, $outFilename,
          array("-f" => "wav"));
      break;
    
    case EFILE_IMAGE:
      $res = wtConvertImage(
        $inFilename,
        $outFilename,
        FALSE, "PNG", 9,
        FALSE, ($edata["mime"] == "gfx"));
        break;
  }

  return $res;
}


function wtUnpackArchiveTo($atype, $filename, $path)
{
  // Check file type before doing anything
  echo "INFO: Preparing to unpack archive file '".$filename."' ...\n";
  switch ($atype)
  {
    case "LHA":
      $exe = wtGetExecutable("lha");
      $args = "x ".escapeshellarg($filename);
      break;

    case "ZIP":
      $exe = wtGetExecutable("unzip");
      $args = "-d ".escapeshellarg($path)." ".escapeshellarg($filename);
      break;

    case "RAR":
      $exe = wtGetExecutable("rar");
      $args = "x -w".escapeshellarg($path)." ".escapeshellarg($filename);
      break;

    case "7ZIP":
      $exe = wtGetExecutable("7z");
      $args = "x -o".escapeshellarg($path)." ".escapeshellarg($filename);
      break;

    default:
      echo "Unsupported archive file type: ".$atype."\n";
      return FALSE;
  }

  // Delete any pre-existing directory
  wtPurgeDir($path);

  // Create temporary directory for unpacking
  wtMakeDir($path, 0755);

  // Save current working directory and chdir to target
  $cwd = getcwd();
  if (!is_dir($path) || chdir($path) === false)
  {
    echo "ERROR: Failed to chdir to '".$path."', can't unpack archive.\n";
    return FALSE;
  }

  // Unpack archive
  $ret = wtExec($exe, $args);

  // Return to stored cwd
  chdir($cwd);
  return $ret;
}


function wtHandleEntryPreview($compo, $entry, $mode)
{
  global $fileTypeData, $setEntryPath;

  // Get current preview file(s) data
  if (!stGetPreviewFileData($compo, $entry, $pdata))
    return FALSE;

  // Get entry file data
  $efile = stFetchSQL("SELECT * FROM files WHERE deleted=0 AND id=".$entry["file_id"]);

  // Check preview file(s) status
  if ($mode == "sta" || $mode == "lis")
  {
    printf(" %03d | %s%s%s | %-40s | %-5s | %s\n",
      $entry["id"],
      ($efile !== false) ? "E" : ".",
      isset($pdata["file"]) ? "P" : ".",
      $pdata["valid"] ? "V" : ".",
      substr($entry["name"]." by ".$entry["author"], 0, 40),
      isset($pdata["file"]) ? $pdata["file"]["filetype"] : "",
      isset($pdata["file"]) ? $pdata["file"]["filename"] : ""
      );
    return TRUE;
  }
  else
  if ($mode != "gen" && $mode != "upd")
    die("ERROR: Unsupported previews mode ".$mode."\n");

  $force = ($mode == "upd");

  // Check validity of previews
  if ($pdata["valid"] && !$force)
    return TRUE;

  // Okay, no valid previews .. lets see what we can do ..
  // First, check if we have a source preview file
  if (!isset($pdata["file"]))
  {
    // No source preview, check if we have entry file either?
    if ($efile === false)
    {
      echo
        "INFO: No entry file for ".wtNiceName($compo, $entry, $efile).
        ", can't attempt to generate preview.\n";
      return FALSE;
    }

    // Actual entry filename + path
    $filename = stMakePath(FALSE, TRUE, array($setEntryPath, $compo["cpath"], $efile["filename"]));
    if (!file_exists($filename))
    {
      echo "ERROR: Entry file '".$filename."' for ".wtNiceName($compo, $entry, FALSE)." does not exist!\n";
      return FALSE;
    }

    // Preview source file does not exist, let's see ..
    $edata = stProbeFileInfo($filename, TRUE);
    if ($edata === false)
    {
      echo
        "ERROR: Invalid/unsupported file type for entry ".wtNiceName($compo, $entry, $efile)."\n";
      return FALSE;
    }

    $found = FALSE;
    if ($edata["class"] == EFILE_ARCHIVE)
    {
      // Entry is an archive file ..
      $path = stMakePath(FALSE, FALSE, array($setEntryPath, "UNPACKS", $efile["filename"]));

      if (wtUnpackArchiveTo($efile["filetype"], $filename, $path) === false)
        return FALSE;

      // Scan through files ...
      $dir = opendir($path);
      while (($dentry = readdir($dir)) !== false)
      {
        $fname = $path."/".$dentry;
        if ($dentry != "." && $dentry != "..")
        {
          if (is_dir($fname))
            echo "XXX: ".$dentry." :: ".$fname."\n";
          else
          if (is_file($fname) &&
            ($mdata = stProbeFileInfo($fname, TRUE)) !== false &&
            ($found = wtEntryToSource($compo, $fname, $mdata, $filename, $pdata, $outFilename, $force)) === true)
            break;
        }
      }

      // Cleanup
      closedir($dir);
      wtPurgeDir($path);
    }
    else
    if ($edata["class"] == $compo["preview_type"])
    {
      // Single file
      $found = wtEntryToSource($compo, $filename, $edata, $filename, $pdata, $outFilename, $force);
    }
    
    if (!$found)
    {
      echo "WARNING: Could not generate preview from entry ".wtNiceName($compo, $entry, $efile)."\n";
      return FALSE;
    }

    $inFilename = $outFilename;
  }
  else
    $inFilename = stMakePath(FALSE, TRUE, array($setEntryPath, $compo["cpath"], $pdata["file"]["filename"]));

  // Check validity vs.
  if (!$force)
  {
    $valid = TRUE;
    $inMTime = filemtime($inFilename);
    foreach ($pdata["files"] as $stype => $sdata)
    {
      if (!file_exists($sdata["file"]) || filemtime($sdata["file"]) < $inMTime)
      {
        $valid = FALSE;
        break;
      }
    }
    if ($valid)
      return TRUE;
  }
  
  //
  // Either we now have a "user specified" source file or
  // a generated source file - in any case, now convert it
  // to the final form(s).
  //
  switch ($compo["preview_type"])
  {
    case EFILE_AUDIO:
      // Convert to each specified sample type (MP3, Ogg, etc.)
      foreach (stGetSetting("sampleTypes") as $stype => $sopts)
      {
        wtConvertSample(
          $inFilename,
          $pdata["files"][$stype]["file"],
          $sopts
          );
      }
      break;

    case EFILE_IMAGE:
      // Images we convert to bigger image and thumbnail
      wtConvertImage(
        $inFilename,
        $pdata["files"]["image"]["file"],
        stGetSetting("previewImageSize"),
        stGetSetting("previewImageType"),
        stGetSetting("previewImageQuality"),
        FALSE, FALSE);

      wtConvertImage(
        $inFilename,
        $pdata["files"]["thumb"]["file"],
        stGetSetting("previewThumbSize"),
        stGetSetting("previewThumbType"),
        stGetSetting("previewThumbQuality"),
        TRUE, FALSE);
      break;
  }

  return TRUE;
}


function wtHandleEntry($compo, $entry, $mode)
{
}


//
// Crop a filename to specified length
//
function wtCropFilename($filename, $len)
{
  if ($len !== FALSE && strlen($filename) > $len)
  {
    // Check if the filename has a path and attempt
    // to get the filename extension
    $fext = "";
    $dpos = strrpos($filename, "/");
    if (($spos = strrpos($filename, ".")) !== FALSE &&
      ($dpos === FALSE || $dpos < $spos))
      $fext = substr($filename, $spos);

    // Is the filename extension too long, if yes, just dump it
    if (strlen($fext) >= $len)
      $fext = "";

    return substr($filename, 0, $len - strlen($fext) - 1).$fext;
  }
  else
    return $filename;
}


//
// Recursively goes through directory/files and subdirectories,
// cropping file/dir names to specified length.
//
function wtCropFilenamesRec($path, $len)
{
  $dir = opendir($path);
  while (($dentry = readdir($dir)) !== false)
  {
    $fname = $path."/".$dentry;
    $nname = $path."/".wtCropFilename($dentry, $len);
    if ($dentry != "." && $dentry != "..")
    {
      if (is_dir($fname))
      {
        wtCropFilenamesRec($fname, $len);
        if (rename($fname, $nname) === false)
        {
          echo "ERROR: Could not rename DIR '".$fname."' -> '".$nname."'.\n";
          return FALSE;
        }
      }
      else
      if (is_file($fname) && rename($fname, $nname) === false)
      {
        echo "ERROR: Could not rename FILE '".$fname."' -> '".$nname."'.\n";
        return FALSE;
      }
    }
  }
  closedir($dir);
}


function wtUnpackEntry($compo, $entry, $pathPrefix, $useOrig, $cropNames, $copyOnly)
{
  global $setEntryPath;

  // Get latest file for the entry
  if (($efile = stFetchSQL("SELECT * FROM files WHERE deleted=0 AND id=".$entry["file_id"])) === false)
  {
    echo "INFO: No entry file for ".wtNiceName($compo, $entry, $efile)."\n";
    return FALSE;
  }

  // Create source file full path
  $filename = stMakePath(FALSE, TRUE, array($setEntryPath, $compo["cpath"], $efile["filename"]));

  // Check if the file exists
  if (!file_exists($filename))
  {
    echo "ERROR: Entry file '".$filename."' for ".wtNiceName($compo, $entry, FALSE)." does not exist!\n";
    return FALSE;
  }

  // Get file data
  $edata = stProbeFileInfo($filename, TRUE);
  if ($edata === false)
  {
    echo
      "ERROR: Invalid/unsupported file type for entry ".wtNiceName($compo, $entry, $efile)."\n";
    return FALSE;
  }

  // Make information file contents
  $sbinfo = [
    "FAP Entry Information",
    "=====================",
    "Compo  : ".$compo["name"]." (ID #".$compo["id"].")",
    "Entry  : '".$entry["name"]."' by ".$entry["author"]." (ID #".$entry["id"].")",
    "Show # : ".($entry["show_id"] > 0 ? $entry["show_id"] : "NOT SET!"),
  ];

  if (strlen($entry["info"]) > 0)
  {
    $sbinfo[] = "";
    $sbinfo[] = "INFO:";
    foreach (preg_split("/\r\n|\n|\r/", $entry["info"]) as $sline)
      $sbinfo[] = $sline;
  }

  if (strlen($entry["notes"]) > 0)
  {
    $sbinfo[] = "";
    $sbinfo[] = "INTERNAL NOTES:";
    foreach (preg_split("/\r\n|\n|\r/", $entry["notes"]) as $sline)
      $sbinfo[] = $sline;
  }

  $sbinfo[] = "";
  $sbinfoStr = implode("\n", $sbinfo);

  // Create the destination directory
  if (wtMakeDir(stMakePath(FALSE, FALSE, array($pathPrefix, $compo["cpath"])), 0755) === false)
    return FALSE;

  // Form the destination path and/or filename
  if ($copyOnly)
    $dstFileBase = $useOrig ? $efile["origname"] : $efile["filename"];
  else
    $dstFileBase = wtCropFilename($entry["show_id"]."-".($useOrig ? $efile["origname"] : $efile["filename"]), $cropNames);

  $dstPath = stMakePath(FALSE, FALSE, array($pathPrefix, $compo["cpath"], stReplaceFileExt($dstFileBase, "")));

  // Handle based on class/type and whether we are just copying or not
  if ($copyOnly)
  {
    $dstFilename = stMakePath(FALSE, FALSE, array($pathPrefix, $compo["cpath"], $dstFileBase));
    if (copy($filename, $dstFilename) === false)
    {
      echo "ERROR: Failed to copy '".$filename."' to '".$dstFilename."'\n";
      return FALSE;
    }
  }
  else
  if ($edata["class"] == EFILE_ARCHIVE)
  {
    // Entry is an archive file, so unpack it
    if (wtUnpackArchiveTo($edata["id"], $filename, $dstPath) === false)
      return FALSE;

    // Crop the filenames from the unpacked archive, if we need to
    if ($cropNames !== false)
      wtCropFilenamesRec($dstPath, $cropNames);

  }
  else
  {
    // We have a single file (or copyOnly mode)
    if (wtMakeDir($dstPath, 0755) === false)
      return FALSE;

    $dstFilename = stMakePath(FALSE, FALSE, array($dstPath, wtCropFilename($efile["origname"], $cropNames)));
    if (copy($filename, $dstFilename) === false)
    {
      echo "ERROR: Failed to copy '".$filename."' to '".$dstFilename."'\n";
      return FALSE;
    }
  }

  $dstFilename = stMakePath(FALSE, FALSE, array($dstPath, "fapinfo.txt"));
  if (@file_put_contents($dstFilename, $sbinfoStr) === FALSE)
  {
    echo "ERROR: Failed to output '".$dstFilename."'\n";
    return FALSE;
  }

  return TRUE;
}


//
// Misc helper functions
//

function wtNiceName($compo, $entry, $efile = FALSE)
{
  return sprintf(
    "%d: %s by %s%s",
    $entry["id"],
    $entry["name"],
    $entry["author"],
    ($efile !== false) ? " [".$efile["filename"]." / TYPE: '".$efile["filetype"]."']" : "");
}


function wtExec($exe, $args, $expect = 0)
{
  echo "EXEC: ".$exe." @ ".$args."\n";
  exec(escapeshellcmd($exe)." ".$args, $output, $code);
  if ($code !== $expect)
  {
    echo
      "ERROR: Executing ".$exe.": ".$code."\n".$args."\n".
      "------------------------------------------------\n".
      implode("\n", $output).
      "------------------------------------------------\n";
    return FALSE;
  }
  return TRUE;
}


function wtExecOrDie($exe, $args)
{
  if (wtExec($exe, $args) === false)
    die();
}


function wtPurgeDir($path)
{
  if ($path != "" && $path !== false && file_exists($path) && is_dir($path))
  {
//    echo "PURGING: ".$path."\n";
    foreach (scandir($path) as $file)
    if ($file !== "." && $file !== "..")
    {
      $sub = $path."/".$file;
      if (is_dir($sub))
        wtPurgeDir($sub);
      else
        unlink($sub);
    }
    rmdir($path);
  }
}


function wtMakeDir($path, $perm)
{
  if (!file_exists($path))
  {
    echo "INFO: Creating ".$path."\n";
    if (mkdir($path, $perm, TRUE) === false)
      die("Could not create directory '".$path."'\n");
  }
}


function wtInitializeDirs()
{
  global
    $setEntryPath, $setPreviewPath, $setThumbDir,
    $setEntryPathPerms, $setPrevPathPerms;

  echo "Checking for missing directories ...\n";
  wtMakeDir($setEntryPath, $setEntryPathPerms);
  wtMakeDir($setPreviewPath, $setPrevPathPerms);

  foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
  {
    wtMakeDir(stMakePath(FALSE, FALSE, array($setEntryPath, $compo["cpath"])), $setEntryPathPerms);
    wtMakeDir(stMakePath(FALSE, FALSE, array($setPreviewPath, $compo["cpath"])), $setPrevPathPerms);
    wtMakeDir(stMakePath(FALSE, FALSE, array($setPreviewPath, $compo["cpath"], $setThumbDir)), $setPrevPathPerms);
  }
}


function wtPrintCompoHeader($compo)
{
  global $setTermWidth;
  printf("==%'=-".($setTermWidth-2)."s\n",
    sprintf("[ #%03d - %s ]", $compo["id"], substr($compo["name"], 0, 40))
    );
}


function wtPrintDivider($chr = "-")
{
  global $setTermWidth;
  echo str_repeat($chr, $setTermWidth)."\n";
}


function wtShowHelp()
{
  global $argv;
  echo
    "faptool - Do stuff with FAPWeb database\n".
    "(C) Copyright 2014-2017 ccr/TNSP\n".
    "\n".
    "Usage: ".$argv[0]." <command> [args]\n".
    "Where command is one of following:\n".
    "\n".
    "  init\n".
    "     Create directories for entries and previews, if needed.\n".
    "\n".
/*
    "  clean [delete|crap]\n".
    "     Clean files marked to be deleted and 'stale' files. This includes\n".
    "     any old or stale preview files and entry files.\n".
    "     Without 'delete' parameter just checks and shows what would deleted.\n".
    "     'crap' parameter will purge EVERYTHING that is NOT in the database,\n".
    "     e.g. any other files, like temp files, etc. DANGEROUS IF YOU DO NOT\n".
    "     KNOW WHAT YOU ARE DOING!!!!!\n".
    "\n".
*/
    "  probe <filename> [filename2 ..]\n".
    "     Probe specified file for file information.\n".
    "\n".
    "  previews <cmd> [args]\n".
    "    Where <cmd> is one of:\n".
    "    status [cid]  - List files and show what is missing, etc. (All or <cid>)\n".
    "    generate   - Generate preview files that are missing OR out of date.\n".
    "               (older then preview source file OR entry file where appropriate)\n".
    "\n".
    "  entry <cmd> [args]\n".
    "    status [cid]  - List entries for all compos or <cid>.\n".
    "    unpack <path> - Create subdirs and copy all entries UNPACKED there.\n".
    "    release <path> - Like unpack, but just copies files (does not unpack archives).\n".
    "\n".
    "    add <cid> <filename> - Add a new entry with file.\n".
    "       Entry info + notes for internal use will be prompted.\n".
    "    pre <eid> <filename> - Add file as preview for entry id.\n".
    "    del <eid> - Delete entry (does not delete files).\n".
/*
    "\n".
    "    package <lha|zip|rar|7z>\n".
    "       Repackages/packages entries (unpacks first if archive),\n".
    "       and adds generated infofile.txt to packages.\n".
*/
    "\n";
}


function wtSigHandler($signo)
{
  global $flagQuit;
  switch ($signo)
  {
    case SIGTERM:
      mgFatal("Received SIGTERM.\n");
      break;

    case SIGQUIT:
    case SIGINT:
      $flagQuit = TRUE;
      break;
  }
}


//
// Main program starts
//
stCheckCLIExec();
if ($argc < 2)
{
  wtShowHelp();
  exit;
}

pcntl_signal(SIGTERM, "wtSigHandler");
pcntl_signal(SIGHUP,  "wtSigHandler");
pcntl_signal(SIGQUIT, "wtSigHandler");
pcntl_signal(SIGINT,  "wtSigHandler");

// Try to connect to database
$spec = stGetSetting("sqlDB");
if (($db = stConnectSQLDBSpec($spec)) === false)
  die("Could not connect to SQL database '".$spec."'.\n");

echo "Using database spec '".$spec."'.\n";

// Fetch non-"hardcoded" settings from SQL database
stReloadSettings();

// Set some globals for our benefit
$setTermWidth = 75;
$setEntryPath = stGetSetting("entryPath");
$setPreviewPath = stGetSetting("previewPath");
$setPreviewURL = stGetSetting("previewURL");
$setThumbDir = stGetSetting("thumbnailSubDir");
$setEntryPathPerms = stGetSetting("entryPathPerms");
$setPrevPathPerms = stGetSetting("previewPathPerms");

if ($setEntryPath === FALSE || $setPreviewPath === FALSE ||
    $setPreviewURL === FALSE || $setThumbDir === FALSE ||
    $setEntryPathPerms === FALSE || $setPrevPathPerms === FALSE)
{
  die("Some required settings are not defined in mconfig.inc.php!\n");
}


// Act according to specified command
switch (stCArgLC(1, 3))
{
  case "-?": case "--h":
    wtShowHelp();
    exit;
    break;

  case "ini":
    //
    // Initialize the data directories etc
    //
    echo "INFO: Checking for missing directories ...\n";
    wtInitializeDirs();
    break;

  case "pro":
    //
    // Probe specified files
    //
    if ($argc < 2)
      die("No filename specified.\n");

    if (($finfo = finfo_open()) === false)
      die("Internal error. Failed to initialize finfo().");

    for ($i = 2; $i < $argc; $i++)
    {
      // Probe one file
      $filename = $argv[$i];
      $sdata = @finfo_file($finfo, $filename, FILEINFO_NONE);
      $smime = @finfo_file($finfo, $filename, FILEINFO_MIME_TYPE);

      echo
        "\n".
        "File   : ".$filename."\n".
        "Probed : ".$sdata."\n".
        "Mime   : ".$smime."\n";

      if (($info = stProbeFileInfo($filename, TRUE)) !== false)
      {
        $tmp = array();
        foreach ($info as $ikey => $ival)
          $tmp[] = $ikey."='".$ival."'";

        echo "Data   : ".implode(", ", $tmp)."\n";
      }
    }

    finfo_close($finfo);
    break;

  case "cle":
    //
    // File cleanup / deletion
    //
    $mode = stCArgLC(2, 3);
    switch ($mode)
    {
      case "del":
      case FALSE:
        foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
        if (stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$compo["id"]) > 0)
        {
          wtPrintCompoHeader($compo);
          wtPrintDivider();

          foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
          {
            foreach (stExecSQL("SELECT * FROM files WHERE entry_id=".$entry["id"]) as $efile)
            {
              if ($efile["deleted"] != 0)
              {
                echo "X";
              }
            }
          }
          echo "\n";
          wtPrintDivider();
        }
        break;
      
      case "cra":
        echo "Not implemented. :D\n";
        break;
      
      default:
        die("ERROR! Invalid entry sub-command '".stCArg(2)."'.\n");
        break;
    }
    break;

  case "ent":
    //
    // Entry files handling
    //
    $mode = stCArgLC(2, 3);
    switch ($mode)
    {
      case "sta":
      case "lis":
        $sql = (stCArg(3) !== FALSE) ? " AND id=".intval(stCArg(3)) : "";
        foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL".$sql) as $compo)
        if (stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$compo["id"]) > 0)
        {
          wtPrintCompoHeader($compo);
          wtPrintDivider();

          foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
            wtHandleEntry($compo, $entry, $mode);

          wtPrintDivider();
        }
        break;

      case "unp":
        if (($setPrefix = stCArg(3)) === FALSE)
          die("Unpack needs a destination path.\n");

        foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
        foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
        {
//          wtUnpackEntry($compo, $entry, $setPrefix, TRUE, 32, FALSE);
          wtUnpackEntry($compo, $entry, $setPrefix, TRUE, FALSE, FALSE);
        }
        break;

      case "rel":
        if (($setPrefix = stCArg(3)) === FALSE)
          die("Releases needs a destination path.\n");

        if (!file_exists($setPrefix) || is_dir($setPrefix))
        {
          // Create new one
          wtMakeDir($setPrefix, 0755);
          
          // Create results.txt if it does not exist
          $resultsFile = stMakePath(FALSE, TRUE, array($setPrefix, "results.txt"));
          if (!file_exists($resultsFile))
          {
            // Use a header file if it exists
            $resultsHeader = "results.logo";
            if (file_exists($resultsHeader) && is_file($resultsHeader))
              $resultsText = file_get_contents($resultsHeader);
            else
            {
              $resultsText = $pageTitle." results";
              $resultsText .= "\n".str_repeat("=", strlen($resultsText))."-- -\n\n";
            }

            file_put_contents(
              $resultsFile,
              $resultsText.stGetCompoResultsASCIIStr(FALSE, 0)
              );
          }
            
          foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL") as $compo)
          foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
          {
            wtUnpackEntry($compo, $entry, $setPrefix, TRUE, FALSE, TRUE);
          }
        }
        break;

      case "pac":
        echo "Not implemented. :D\n";
        break;

      case "add":
        echo "Not implemented. :D\n";
        break;

      default:
        if ($mode == FALSE)
          die("ERROR! Entry command requires a sub-command argument.\n");
        else
          die("ERROR! Invalid entry sub-command '".stCArg(2)."'.\n");
        break;
    }
    break;

  case "pre":
    //
    // Preview files handling
    //
    $mode = stCArgLC(2, 3);
    switch ($mode)
    {
      case "gen":
      case "upd":
      case "sta":
      case "lis":
        $sql = (stCArg(3) !== FALSE) ? " AND id=".intval(stCArg(3)) : "";
        foreach (stExecSQL("SELECT * FROM compos WHERE cpath <> '' AND cpath IS NOT NULL".$sql) as $compo)
        if (stFetchSQLColumn("SELECT COUNT(*) FROM entries WHERE compo_id=".$compo["id"]) > 0)
        {
          wtPrintCompoHeader($compo);
          printf(
            "PrevType : %s\n",
            $previewTypeList[$compo["preview_type"]][0]);

          if ($mode == "sta" || $mode == "lis")
          {
            printf(" %-3s | %-3s | %-40s |\n",
              "#ID", "EPV", "Entry name/author");
          }

          wtPrintDivider("-");

          foreach (stExecSQL("SELECT * FROM entries WHERE compo_id=".$compo["id"]) as $entry)
            wtHandleEntryPreview($compo, $entry, $mode);

          wtPrintDivider("=");
        }
        if ($mode == "sta" || $mode == "lis")
        {
          echo "Flags: E = Entry has file, P = Has preview file, V = Generated previews are up to date.\n";
        }
        break;

      default:
        if ($mode == FALSE)
          die("ERROR! Previews command requires a sub-command argument.\n");
        else
          die("ERROR! Invalid previews sub-command '".stCArg(2)."'.\n");
        break;
    }
    break;

  default:
    echo "ERROR! Invalid operation mode '".stCArg(1)."'.\n";
    break;
}

/* Dummy
{
  
}
*/
?>