<commit_before><?php
session_start();
/**
 * Simple webhard in a single file.
 * 
 * https://github.com/webstory/webhard
 *
 * WARNING! This program provides lacks of security.
 * Use this for small, personal purpose only.
 *
 * Most important thing: Discard after use.
 * 
 * @version 0.1.0
 * @author <NAME>(<EMAIL>)
 * @license MIT
 */

/* Security Configuration */
$salt = $_SERVER['SERVER_NAME'];   // Any string
$hash_iteration_count = 54321;     // Higher is better
/**************************/

function path_join($path_arr) {
  $joined_path = implode("/", $path_arr);
  $normalized_path =  preg_replace("/\/+/","/",$joined_path);
  $canonicalized_path = preg_replace("/\/.+?\/\.\./","/", $normalized_path);

  return $canonicalized_path;
}

function is_authorized() {
  return isset($_SESSION['token']) && $_SESSION['token'] == session_id();
}

$method = $_SERVER['REQUEST_METHOD'];
$current_uri = $_SERVER['REQUEST_URI'];

$basepath = dirname(__FILE__);
$path = isset($_GET['dir'])? urldecode($_GET['dir']) : "/";

$curpath = path_join([$basepath, $path]);

// Security check step 1
// Check path is directory
if(!is_dir($curpath)) {
  header('HTTP/1.1 404 Not Found');
  die("<script>alert('".$path." is not a directory.'); window.history.back();</script>");
}

// Security check step 2
// Chroot jail
if(strpos(realpath($curpath),realpath($basepath)) === false) {
  header('HTTP/1.1 403 Forbidden');
  die("<script>alert('Access violation!'); window.history.back();</script>");
}

// Security check step 3
// Is authorized
// Special behavior: Display login dialog
if(!is_authorized()) {
  // Check if login action
  if(isset($_GET['action']) && $_GET['action'] == 'login') {
    // Set default password if not present
    if(!file_exists("password.txt") && !file_exists("password.hash")) {
      file_put_contents("password.txt", "opense<PASSWORD>");
    }

    if(file_exists("password.txt")) {
      $password = trim(file_get_contents("password.txt"));
      $digest = hash_pbkdf2("sha512", $password, $salt, $hash_iteration_count, 64);
      file_put_contents("password.hash", $digest);
      unlink("password.txt");
    }

    $hash1 = file_get_contents("password.hash");
    $hash2 = hash_pbkdf2("sha512", $_POST['password'], $salt, $hash_iteration_count, 64);

    if($hash1 == $hash2) {
      $_SESSION['token'] = session_id();
    }

    ?>
    <script>location.href = "<?=$_SERVER['PHP_SELF']?>?dir=/"</script>
    <?php
  } else { // Not login action
    $method = "AUTH";
  }
}

// Actions router
$action = isset($_GET['action']) ? $_GET['action'] : "";

switch($action) {
  case 'logout':
    session_destroy();
    ?>
    <script>location.href = "<?=$_SERVER['PHP_SELF']?>?dir=/"</script>
    <?php
  break;

  case 'mkdir':
    mkdir(path_join([$curpath,$_GET['name']]));
    ?><commit_msg>password reset logic alwats work now.<commit_after><?php
session_start();
/**
 * Simple webhard in a single file.
 * 
 * https://github.com/webstory/webhard
 *
 * WARNING! This program provides lacks of security.
 * Use this for small, personal purpose only.
 *
 * Most important thing: Discard after use.
 * 
 * @version 0.1.0
 * @author <NAME>(<EMAIL>)
 * @license MIT
 */

/* Security Configuration */
$salt = $_SERVER['SERVER_NAME'];   // Any string
$hash_iteration_count = 54321;     // Higher is better
/**************************/

function path_join($path_arr) {
  $joined_path = implode("/", $path_arr);
  $normalized_path =  preg_replace("/\/+/","/",$joined_path);
  $canonicalized_path = preg_replace("/\/.+?\/\.\./","/", $normalized_path);

  return $canonicalized_path;
}

function is_authorized() {
  return isset($_SESSION['token']) && $_SESSION['token'] == session_id();
}

$method = $_SERVER['REQUEST_METHOD'];
$current_uri = $_SERVER['REQUEST_URI'];

$basepath = dirname(__FILE__);
$path = isset($_GET['dir'])? urldecode($_GET['dir']) : "/";

$curpath = path_join([$basepath, $path]);

// Security check step 1
// Check path is directory
if(!is_dir($curpath)) {
  header('HTTP/1.1 404 Not Found');
  die("<script>alert('".$path." is not a directory.'); window.history.back();</script>");
}

// Security check step 2
// Update password
// Set default password if not present
if(!file_exists("password.txt") && !file_exists("password.hash")) {
  file_put_contents("password.txt", "<PASSWORD>");
}

if(file_exists("password.txt")) {
  $password = trim(file_get_contents("password.txt"));
  $digest = hash_pbkdf2("sha512", $password, $salt, $hash_iteration_count, 64);
  file_put_contents("password.hash", $digest);
  unlink("password.txt");
}

// Security check step 3
// Chroot jail
if(strpos(realpath($curpath),realpath($basepath)) === false) {
  header('HTTP/1.1 403 Forbidden');
  die("<script>alert('Access violation!'); window.history.back();</script>");
}

// Security check step 4
// Is authorized
// Special behavior: Display login dialog
if(!is_authorized()) {
  // Check if login action
  if(isset($_GET['action']) && $_GET['action'] == 'login') {
    $hash1 = file_get_contents("password.hash");
    $hash2 = hash_pbkdf2("sha512", $_POST['password'], $salt, $hash_iteration_count, 64);

    if($hash1 == $hash2) {
      $_SESSION['token'] = session_id();
    }

    ?>
    <script>location.href = "<?=$_SERVER['PHP_SELF']?>?dir=/"</script>
    <?php
  } else { // Not login action
    $method = "AUTH";
  }
}

// Actions router
$action = isset($_GET['action']) ? $_GET['action'] : "";

switch($action) {
  case 'logout':
    session_destroy();
    ?>
    <script>location.href = "<?=$_SERVER['PHP_SELF']?>?dir=/"</script>
    <?php
  break;

  case 'mkdir':
    mkdir(path_join([$curpath,$_GET['name']]));
    ?>
{'fraction_non_alphanumeric': 0.211987270155587, 'fraction_numerical': 0.01326025459688826, 'mean_word_length': 4.311737089201878, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2852052', 'n_tokens_mistral': 1955, 'n_tokens_neox': 1885, 'n_words': 385}