<?php
session_start();
if (empty($_SESSION['login'])) {
  $_SESSION['login'] = false;
}
// change if you want no inpact
date_default_timezone_set('Europe/Paris');
// soshot only accept request by 127.0.0.1
$GLOBALS['config']['onlyLocalServer'] = false;
// No form for post url only acces by GET method
$GLOBALS['config']['NoWebPage'] = false;
// After 3 critical error ban user
$GLOBALS['config']['maxErrorBeforeBan'] = 3;
// Ban for 60 minutes
$GLOBALS['config']['banTime'] = 60;
// default url for form
$GLOBALS['config']['defaultUrl'] = 'https://duckduckgo.com/';
// default size for thumbnail
$GLOBALS['config']['defaultThumbSize'] = '120x90';
// list of available size for thumb
$GLOBALS['config']['thumbSize'] = array(
  's' => '120x90',
  'm' => '200x160',
  'l' => '300x240',
  'xl' => '400x320',
  'xxl' => '500x400'
);
// create thumshot 1280x1024
$GLOBALS['config']['activeFullSize'] = false;
// create thumbshot of complete page
$GLOBALS['config']['activeComplete'] = false;
// Remove image older than 12 hours
$GLOBALS['config']['expireCache'] = 12;
// Disable exec command and use cron task
$GLOBALS['config']['disableExec'] = true;
// Enable log for success, suspect, error
$GLOBALS['config']['log'] = true;
if (file_exists('cache/config/options.php')) {
  require 'cache/config/options.php';
}
if (get_magic_quotes_gpc()) {
  function stripslashes_deep($value) {
    $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
    return $value;
  }

  $_POST = array_map('stripslashes_deep', $_POST);
  $_GET = array_map('stripslashes_deep', $_GET);
  $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
}
if (!empty($_POST)) {
  $ui = $_POST;
  $ui['request'] = 'form';
  $ui['iw'] = 1;
  unset($_POST);
}
if (!empty($_GET)) {
  $ui = $_GET;
  $ui['request'] = 'api';
  unset($_GET);
}
if (empty($ui['request'])) {
  $ui['request'] = '';
}
if (empty($ui['p'])) {
  $ui['p'] = 'index';
}
if (empty($ui['fr'])) {
  $ui['fr'] = '';
}
if (empty($ui['t'])) {
  $ui['t'] = 't';
}
if (isset($ui['logout']) && (int)$ui['logout'] === 1) {
  session_destroy();
  header("Location:?");
  exit();
}
if (!file_exists('cache/config/genConf.php')) {
  $serverKey = install();
  $ui['p'] = 'install';
}
require 'cache/config/genConf.php';
if ($GLOBALS['config']['pwd'] === 'install' && $ui['p'] !== 'install') {
  reloadInstall();
  header("Location:?");
}
if (($GLOBALS['config']['onlyLocalServer'] === true && $_SERVER['REMOTE_ADDR'] !== '127.0.0.1') || checkIfBan() === true) {
  header("HTTP/1.0 404 Not Found");
  echo "<h1>404 Not Found</h1>";
  echo "The page that you have requested could not be found.";
  exit();
}
if ($GLOBALS['config']['NoWebPage'] === true && empty($_GET)) {
  header("HTTP/1.0 404 Not Found");
  echo "<h1>404 Not Found</h1>";
  echo "The page that you have requested could not be found.";
  exit();
}
function testExistImg($file) {
  if ($GLOBALS['config']['activeFullSize'] && $GLOBALS['config']['activeComplete']) {
    if (file_exists($file.'_thumb.png') && file_exists($file.'.png') && file_exists($file.'_complete.png')) {
      return true;
    } else {
      return false;
    }
  } elseif ($GLOBALS['config']['activeFullSize']) {
    if (file_exists($file.'_thumb.png') && file_exists($file.'.png')) {
      return true;
    } else {
      return false;
    }
  } elseif ($GLOBALS['config']['activeComplete']) {
    if (file_exists($file.'_thumb.png') && file_exists($file.'_complete.png')) {
      return true;
    } else {
      return false;
    }
  } else {
    if (file_exists($file.'_thumb.png')) {
      return true;
    } else {
      return false;
    }
  }
}

/**
 * Run the bash script for generate thumbnail
 *
 * @author Knah Tsaeb
 * @date 2013-02-12
 * @param $url (string) url for thumbshot
 * @param $hashUrl (hash) hash($url)
 * @param $width (string) size of thumbnail 190x90
 * @param $onlyThumb (bool)
 * @param $waitForResult (bool)
 * @return
 */
function launchScript($url, $hashUrl, $width, $size, $waitForResult = false) {
  $hashUrl = escapeshellarg($hashUrl);
  $url = escapeshellarg($url);
  $width = escapeshellarg($width);
  if ($GLOBALS['config']['activeFullSize'] && $GLOBALS['config']['activeComplete']) {
    $renderType = 'trc';
  } elseif ($GLOBALS['config']['activeFullSize']) {
    $renderType = 'tr';
  } elseif ($GLOBALS['config']['activeComplete']) {
    $renderType = 'tc';
  } else {
    $renderType = 't';
  }
  if ($GLOBALS['config']['disableExec'] === false) {
    chdir('bin/');
    if ($waitForResult === false) {
      exec('bash thumb_server.sh '.$url.' '.$hashUrl.' '.$width.' '.$size.' '.$renderType.' > /dev/null &', $result);
    } else {
      exec('bash thumb_server.sh '.$url.' '.$hashUrl.' '.$width.' '.$size.' '.$renderType.' 1', $result);
    }
    chdir('../');
  } else {
    makeQueueFile($url, $hashUrl, $width, $size, $renderType);
    $result = 0;
  }
  return $result;
}

function makeQueueFile($url, $hashUrl, $width, $size, $renderType) {
  $url = str_replace('\'', '', $url);
  $hashUrl = str_replace('\'', '', $hashUrl);
  $width = str_replace('\'', '', $width);
  if (!file_exists('cache/cronTask/'.$hashUrl.'.hash')) {
    $data = $url.' '.$hashUrl.' '.$width.' '.$size.' '.$renderType."\n";
    file_put_contents('cache/cronTask/'.$hashUrl.'.hash', $data);
  }
}

function testValidUrl($url) {
  $url = trim($url);
  if (filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED)) {
    $url = parse_url($url);
    if (!in_array($url['scheme'], array(
      'http',
      'https'
    ))) {
      return array('msg' => 'Url must be start by http or https.');
    }
    return true;
  } else {
    return array('msg' => 'Not a valid url.');
  }
}

function genToken() {
  $token = sha1(uniqid(rand(), true).'_'.mt_rand());
  $_SESSION['token'] = $token;
  $_SESSION['tokenTime'] = time();
  return $token;
}

function verifToken($token) {
  if ($token !== $_SESSION['token'] || $_SESSION['tokenTime'] <= time() - 24000) {
    ban();
    die('So Long, and Thanks for All the Fish.');
  }
}

function checkIfBan() {
  require 'cache/logs/banUser.php';
  $userIp = $_SERVER['REMOTE_ADDR'];
  if (isset($banList[$userIp]) && $banList[$userIp]['nbBan'] >= $GLOBALS['config']['maxErrorBeforeBan'] && $banList[$userIp]['lastBan'] + $GLOBALS['config']['banTime'] > time()) {
    return true;
  } elseif (isset($banList[$userIp]) && $banList[$userIp]['lastBan'] + $GLOBALS['config']['banTime'] < time()) {
    unban();
    return false;
  } else {
    return false;
  }
}

function ban() {
  require 'cache/logs/banUser.php';
  $userIp = $_SERVER['REMOTE_ADDR'];
  if (isset($banList[$userIp])) {
    $banList[$userIp]['lastBan'] = time();
    $banList[$userIp]['nbBan']++;
  } else {
    $banList[$userIp]['lastBan'] = time();
    $banList[$userIp]['nbBan'] = 1;
  }
  file_put_contents('cache/logs/banUser.php', "<?php\n\$banList=".var_export($banList, true).";\n?>");
}

function unBan() {
  require 'cache/logs/banUser.php';
  $userIp = $_SERVER['REMOTE_ADDR'];
  unset($banList[$userIp]);
  file_put_contents('cache/logs/banUser.php', "<?php\n\$banList=".var_export($banList, true).";\n?>");
}

function install() {
  if (!is_writable('cache')) {
    die('Make dir "cache" writable');
  }
  if (!is_dir('cache/config') && !mkdir('cache/config', 0705)) {
    die('Error on create dir "cache/config".');
  }
  if (!is_dir('cache/img') && !mkdir('cache/img', 0705)) {
    die('Error on create dir "cache/img".');
  }
  if (!is_dir('cache/logs') && !mkdir('cache/logs', 0705)) {
    die('Error on create dir "cache/logs".');
  }
  if (!is_dir('cache/logs/suspect') && !mkdir('cache/logs/suspect', 0705)) {
    die('Error on create dir "cache/logs/suspect".');
  }
  if (!is_dir('cache/logs/retry') && !mkdir('cache/logs/retry', 0705)) {
    die('Error on create dir "cache/logs/retry".');
  }
  if (!is_dir('cache/logs/other') && !mkdir('cache/logs/other', 0705)) {
    die('Error on create dir "cache/logs/other".');
  }
  if (!is_dir('cache/tmp') && !mkdir('cache/tmp', 0705)) {
    die('Error on create dir "cache/tmp".');
  }
  if (!is_dir('cache/cronTask') && !mkdir('cache/cronTask', 0705)) {
    die('Error on create dir "cache/cronTask".');
  }
  $salt = sha1(uniqid(rand(), true).'_'.mt_rand());
  $serverKey = substr(sha1(uniqid(rand(), true).'_'.mt_rand().$salt), 0, 12);
  $encryptServerKey = sha1($serverKey.$salt);
  if (!is_file('cache/config/genConf.php')) {
    file_put_contents('cache/config/genConf.php', "<?php\n\$GLOBALS['config']['serverKey'] = '$encryptServerKey';\n\$GLOBALS['config']['salt'] = '$salt';\n\$GLOBALS['config']['pwd'] = 'install';\n?>");
  }
  if (!is_file('cache/config/serverOptions.php')) {
    touch('cache/config/serverOptions.php');
  }
  if (!is_file('cache/index.html')) {
    touch('cache/index.html');
  }
  if (!is_file('cache/config/options.php')) {
    file_put_contents('cache/config/options.php', "<?php\n\n?>");
  }
  if (!is_file('cache/logs/banUser.php')) {
    file_put_contents('cache/logs/banUser.php', "<?php\n\n?>");
  }
  $GLOBALS['config']['serverKey'] = $encryptServerKey;
  $GLOBALS['config']['salt'] = $salt;
  $GLOBALS['config']['pwd'] = 'install';
  return $serverKey;
}

function checkInstall() {
  if (!is_file('.htaccess')) {
    file_put_contents('.htaccess', "AddDefaultCharset UTF-8\nOptions -Indexes\nDirectoryIndex index.php index.html\nFileETag none\nSetOutputFilter DEFLATE\n");
  }
  if (!is_file('cache/logs/.htaccess')) {
    file_put_contents('cache/logs/.htaccess', "Allow from none\nDeny from all\n");
  }
  if (!is_file('cache/config/.htaccess')) {
    file_put_contents('cache/config/.htaccess', "Allow from none\nDeny from all\n");
  }
  if (!is_file('cache/cronTask/.htaccess')) {
    file_put_contents('cache/config/.htaccess', "Allow from none\nDeny from all\n");
  }
  if (!is_file('bin/.htaccess')) {
    file_put_contents('bin/.htaccess', "Allow from none\nDeny from all\n");
  }
}

function removeOlderThan($dir = 'cache/img/shortLive') {
  if (is_dir($dir)) {
    $objects = scandir($dir);
    foreach ($objects as $object) {
      if ($object !== '.' && $object !== '..' && $object) {
        if (filetype($dir.'/'.$object) === 'dir') {
          removeOlderThan($dir.'/'.$object);
        } else {
          if (fileatime($dir.'/'.$object) < time() - 3600 * $GLOBALS['config']['expireCache']) {
            unlink($dir.'/'.$object);
          }
        }
      }
    }
    reset($objects);
  }
}

function pathForFile($size, $hashUrl) {
  $startPath = substr($hashUrl, 0, 2).'/'.substr($hashUrl, 2, 2).'/';
  if(empty($size)){
    $size = tryDetectSize($startPath.$hashUrl);
  }
  $file = 'cache/img/'.$size.'/'.$startPath.$hashUrl;
  return $file;
}

function tryDetectSize($file) {
  if (is_file('cache/img/s/'.$file.'_thumb.png')) {
    return 's';
  }
  if (is_file('cache/img/m/'.$file.'_thumb.png')) {
    return 'm';
  }
  if (is_file('cache/img/l/'.$file.'_thumb.png')) {
    return 'l';
  }
  if (is_file('cache/img/xl/'.$file.'_thumb.png')) {
    return 'xl';
  }
  if (is_file('cache/img/xxl/'.$file.'_thumb.png')) {
    return 'xxl';
  }
}

function validHash($hash) {
  if (empty($hash)) {
    die('You talking to me');
  }
  if (!preg_match('/^[0-9a-f]{40}$/i', $hash)) {
    die('I don\'t understand biiip bip bip biiiip bip bip bip biiiiiiip biip ...');
  }
  return $hash;
}

function checkAdmin($pwd) {
  $pwd = sha1($GLOBALS['config']['salt'].$pwd.$GLOBALS['config']['serverKey']);
  if (validHash($pwd) !== $GLOBALS['config']['pwd']) {
    ban();
    die('1, 2, 3, 4, 5 ? That\'s amazing ! I\'ve got the same combination on my luggage !');
  }
  $_SESSION['login'] = true;
  return true;
}

function savePass($passOne, $passTwo, $token) {
  verifToken($token);
  if ($passOne !== $passTwo || empty($passOne) || empty($passTwo)) {
    reloadInstall();
  } else {
    $GLOBALS['config']['pwd'] = sha1($GLOBALS['config']['salt'].$passOne.$GLOBALS['config']['serverKey']);
    $confServerKey = $GLOBALS['config']['serverKey'];
    $confSalt = $GLOBALS['config']['salt'];
    $confPwd = $GLOBALS['config']['pwd'];
    $confFile = '
    <?php
    $GLOBALS[\'config\'][\'serverKey\'] = \''.$confServerKey.'\';
    $GLOBALS[\'config\'][\'salt\'] = \''.$confSalt.'\';
    $GLOBALS[\'config\'][\'pwd\'] = \''.$confPwd.'\';
    ?>';
    file_put_contents('cache/config/genConf.php', $confFile);
  }
  header("Location:?");
}

function reloadInstall() {
  array_map('unlink', glob("cache/config/*"));
}

/**
 * Améliore la sortie print
 *
 * @author  Tatane http://www.tatane.info/index.php/print_rn
 * @author http://www.blog.cactuscrew.com/77-print_rn.html
 * @param $data (array) tableau ou variable à examiner
 * @param $name (string) nom a afficher
 * @return false affiche les clef valeur du tableau $data
 * @example n_print($array, 'Tableau de valeur');
 */
function n_print($data, $name = '') {
  $aBackTrace = debug_backtrace();
  echo '<h2>', $name, '</h2>';
  echo '<fieldset style="border: 1px solid orange; padding: 5px;color: #333; background-color: #fff;">';
  echo '<legend style="border:1px solid orange;padding: 1px;background-color:#eee;color:orange;">
    ',   basename($aBackTrace[0]['file']), ' ligne => ', $aBackTrace[0]['line'], '
  </legend>';
  echo '<pre>',   htmlentities(print_r($data, 1)), '</pre>';
  echo '
</fieldset>
<br />
';
}

function printThumbShot($file, $renderType) {
  ob_end_clean();
  header("Content-type: image/png");
  header('Expires: ', gmdate('D, d M Y H:i:s', time()).' GMT');
  switch ($renderType) {
    case 'c' :
      echo file_get_contents($file.'_complete.png');
      break;
    case 'r' :
      echo file_get_contents($file.'.png');
      break;
    default :
      echo file_get_contents($file.'_thumb.png');
      break;
  }
  exit();
}

function getPage($page) {
  $page = htmlspecialchars($page);
  switch ($page) {
    case 'login' :
      return 'inc/login.php';
      break;
    case 'install' :
      return 'inc/install.php';
      break;
    case 'admin' :
      return 'inc/admin.php';
      break;
    default :
      return 'inc/index.php';
      break;
  }
}

function testIfImg($url) {
  $ext = strtolower(pathinfo($url, PATHINFO_EXTENSION));
  if ($ext === 'jpg' || $ext === 'jpeg' || $ext === 'png' || $ext === 'gif') {
    return $ext;
  } else {
    return false;
  }
}

function makeImgThumb($url, $ext, $hashUrl, $width, $path, $renderType) {
  if (!function_exists('imagecreatefromjpeg')) {
    return false;
  }
  $image = file_get_contents($url);
  $fullSize = file_put_contents('cache/tmp/'.$hashUrl.'.'.$ext, $image);
  if ($ext === 'jpg' || $ext === 'jpeg') {
    $tmpImg = imagecreatefromjpeg('cache/tmp/'.$hashUrl.'.'.$ext);
  }
  if ($ext === 'png') {
    $tmpImg = imagecreatefrompng('cache/tmp/'.$hashUrl.'.'.$ext);
  }
  if ($ext === 'gif') {
    $tmpImg = imagecreatefromgif('cache/tmp/'.$hashUrl.'.'.$ext);
  }
  if (!$tmpImg) {
    unlink('cache/tmp/'.$hashUrl.'.'.$ext);
    return false;
  }
  $w = imagesx($tmpImg);
  $h = imagesy($tmpImg);
  $ystart = 0;
  $yheight = $h;
  if ($h > $w) { $ystart = ($h / 2) - ($w / 2);
    $yheight = $w / 2;
  }
  $nh = min(floor(($h * $width) / $w), $width);
  $im2 = imagecreatetruecolor($width, $nh);
  imagecopyresampled($im2, $tmpImg, 0, 0, 0, $ystart, $width, $nh, $w, $yheight);
  $tempname = 'cache/tmp/'.$hashUrl.'_TEMP.png';
  imagepng($im2, $tempname, 9);
  if (!is_dir($path)) {
    mkdir($path, 0775, true);
  }
  imagedestroy($tmpImg);
  imagedestroy($im2);
  unlink('cache/tmp/'.$hashUrl.'.'.$ext);
  rename($tempname, $path.$hashUrl.'_thumb.png');
  if (file_exists($path.$hashUrl.'_thumb.png')) {
    return true;
  } else {
    return false;
  }
}

/*
 $image = file_get_contents('http://www.url.com/image.jpg');
 file_put_contents('/images/image.jpg', $image); //save the image on your server
 *
 *
 */
checkInstall();
removeOlderThan();
if (empty($defUrl)) {
  $defUrl = $GLOBALS['config']['defaultUrl'];
}
if (isset($ui['s']) && array_key_exists($ui['s'], $GLOBALS['config']['thumbSize'])) {
  $width = $GLOBALS['config']['thumbSize'][$ui['s']];
} else {
  $width = $GLOBALS['config']['defaultThumbSize'];
}
// Generate or return img
if (!empty($ui['request']) && $ui['p'] !== 'install' && $ui['p'] !== 'login' && $ui['p'] !== 'admin') {
  if (empty($ui['url'])) {
    die('You see in this world there\'s two kinds of people, my friend. Those with loaded guns, and those who dig. You dig.');
  }
  $ui['url'] = trim(rawurldecode($ui['url']));
  $ui['url'] = rtrim($ui['url'], '/');
  $hashUrl = sha1($GLOBALS['config']['salt'].$ui['url']);
  $startPath = substr($hashUrl, 0, 2).'/'.substr($hashUrl, 2, 2).'/';
  $file = 'cache/img/'.$ui['s'].'/'.$startPath.$hashUrl;
  $testUrl = testValidUrl($ui['url']);
  $defUrl = $ui['url'];
  if ($ui['request'] === 'form') {
    $file = 'cache/img/shortLive/'.$startPath.$hashUrl;
    $file = 'cache/img/shortLive/'.$startPath.$hashUrl;
  }
  if (testExistImg($file) === true && (int)$ui['fr'] !== 1) {
    if ($ui['request'] === 'api') {
      printThumbShot($file, $ui['t']);
    }
    if ($ui['request'] === 'form') {
      $success = array(
        'normal' => $file.'.png',
        'thumb' => $file.'_thumb.png',
        'complete' => $file.'_complete.png'
      );
    }
  } else {
    if ($ui['request'] === 'api') {
      if (empty($ui['key']) || empty($ui['url'])) {
        die('Are you Ken ?');
      }
      if (sha1($ui['key'].$GLOBALS['config']['salt']) !== $GLOBALS['config']['serverKey']) {
        ban();
        die('I take a chips and give it to Godzilla. I give high kick in Chuck Norris face and I go to ... Humm .... Ehh .... Arg ....... KAMOULOX ! Well done Jean Pierre.');
      }
    } else {
      verifToken($ui['token']);
    }
    if ($testUrl !== true) {
      if (!file_exists('cache/logs/'.$hashUrl.'log')) {
        file_put_contents('cache/logs/suspect/'.$hashUrl.'.log', $_SERVER['REMOTE_ADDR'].' --- '.$ui['url'].' --- '.$hashUrl.' --- '.$width.' --- '.$ui['s'].' --- '.$renderType.' --- true'."\n");
      }
      if ($ui['request'] === 'api') {
        printThumbShot('bin/error');
      } else {
        $success = array(
          'normal' => 'bin/error.png',
          'thumb' => 'bin/error_thumb.png',
          'complete' => 'bin/error.png'
        );
      }
    } else {
      $ext = testIfImg($ui['url']);
      if ($ext !== false) {
        $genWidth = explode("x", $width);
        if ($ui['request'] === 'api') {
          $makeImg = makeImgThumb($ui['url'], $ext, $hashUrl, $genWidth[0], 'cache/img/'.$ui['s'].'/'.$startPath, $ui['t']);
        } else {
          $makeImg = makeImgThumb($ui['url'], $ext, $hashUrl, $genWidth[0], 'cache/img/shortLive/'.$startPath, $ui['t']);
        }
        if ($makeImg === true) {
          $GLOBALS['config']['disableExec'] = true;
          if ($ui['request'] === 'api') {
            printThumbShot($file);
          } else {
            $success = array(
              'normal' => $file.'.png',
              'thumb' => $file.'_thumb.png',
              'complete' => $file.'_complete.png'
            );
          }
        }
      }
      if ((isset($ui['iw']) && (int)$ui['iw'] === 1 && $ui['request'] === 'api')) {
        $res = launchScript($defUrl, $hashUrl, $width, $ui['s'], true);
      } elseif (isset($ui['iw']) && (int)$ui['iw'] === 1 && $ui['request'] === 'form') {
        $res = launchScript($defUrl, $hashUrl, $width, 'shortLive', true);
      } else {
        $res = launchScript($defUrl, $hashUrl, $width, $ui['s'], false);
      }
      if ($ui['request'] === 'api') {
        $file = 'bin/loadingGen';
        printThumbShot($file);
      } else {
        if ($GLOBALS['config']['disableExec'] === true) {
          $file = 'bin/loadingGen';
        }
        $success = array(
          'normal' => $file.'.png',
          'thumb' => $file.'_thumb.png',
          'complete' => $file.'_complete.png'
        );
      }
    }
  }
}
?>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>SoShot</title>
    <meta name="description" content="Personal webshot">
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <?php
    require   getPage($ui['p']);
    ?>
  </body>
</html>