Logo  

CS479/579 - Web Programming II

Displaying ./code/images/upload.php

<?php
include "config.php";
include "auth.php";

$auth = new Auth();
if ($auth->authenticated() == false) header("location: login.php");
$uid = $auth->uid;

if (!isset($_FILES['upload'])) header("location: index.php");

try {

  for($i=0; $i < count($_FILES['upload']['error']); $i++) {
    // Undefined | Multiple Files | $_FILES Corruption Attack
    // If this request falls under any of them, treat it invalid.
    if (
        !isset($_FILES['upload']['error'][$i]) ||
        is_array($_FILES['upload']['error'][$i])
    ) {
        throw new RuntimeException('Invalid parameters.');
    }

    // Check $_FILES['upload']['error'] value.
    switch ($_FILES['upload']['error'][$i]) {
        case UPLOAD_ERR_OK:
            break;
        case UPLOAD_ERR_NO_FILE:
            throw new RuntimeException('No file sent.');
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            throw new RuntimeException('Exceeded filesize limit.');
        default:
            throw new RuntimeException('Unknown errors.');
    }

    // You should also check filesize here.
    if ($_FILES['upload']['size'][$i] > 1000000000) {
        throw new RuntimeException('Exceeded filesize limit.');
    }

    // DO NOT TRUST $_FILES['upload']['mime'] VALUE !!
    // Check MIME Type by yourself.
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    if (false === $ext = array_search(
        $finfo->file($_FILES['upload']['tmp_name'][$i]),
        array(
            'jpg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
        ),
        true
    )) {
        throw new RuntimeException('Invalid file format.');
    }

    // You should name it uniquely.
    // DO NOT USE $_FILES['upload']['name'] WITHOUT ANY VALIDATION !!
    $location = $auth->createSID() . "." . $ext;
    // $location= sprintf('%s.%s', sha1_file($_FILES['upload']['tmp_name'][$i]), $ext);
    $dest = sprintf("./uploads/%s", $location);

    if (!move_uploaded_file($_FILES['upload']['tmp_name'][$i], $dest)) {
        throw new RuntimeException('Failed to move uploaded file.');
    }

    // Note how the paths are single quoted in the command to be executed, as the
    // filename may have $'s in them:
    shell_exec("convert './uploads/$location' -scale 320x './uploads/thumb/$location'");
    $res = shell_exec("identify './uploads/$location' | tr ' ' '\n' | tail +3 | head -1");
    list($width,$height) = explode("x", trim($res));

    $meta = json_encode(["width" => $width, "height" => $height, "likes" => 0, "dislikes" => 0, "tags" => []]);

// +----------+--------------+------+-----+---------------------+-------+
// | Field    | Type         | Null | Key | Default             | Extra |
// +----------+--------------+------+-----+---------------------+-------+
// | uid      | int(12)      | NO   | MUL | 0                   |       |
// | location | varchar(512) | NO   |     |                     |       |
// | name     | varchar(256) | NO   |     |                     |       |
// | meta     | text         | NO   |     | '{}'                |       |
// | created  | timestamp    | NO   |     | current_timestamp() |       |
// | tags     | text         | NO   |     | '[]'                |       |
// +----------+--------------+------+-----+---------------------+-------+

    $name = htmlspecialchars($_FILES['upload']['name'][$i]);

    $stmt = $myconn->prepare("insert into img_image (`uid`, `location`, `name`, `meta`)
      VALUES (?, ?, ?, ?)");
    if ($stmt === false)
      throw new RuntimeException('Prepare failed [' . $myconn->error . ']');

    $stmt->bind_param("isss", $uid, $location, $name, $meta);
    if ($stmt->execute() === false) {
       throw new RuntimeException('Database insert failed [' . $myconn->error . ']');
    }
    $stmt->close();
  }
  header("location: index.php");

} catch (RuntimeException $e) {
    echo "<h1>" . $e->getMessage() . "</h1>";
    echo "<pre>";
    var_dump($_FILES);
    echo "</pre>";
    echo "<br><a href='index.php'> Back to main page. </a>";
}
?>