From afc3e0f15e6c4e69d17fd5a84253a436a4fba4fc Mon Sep 17 00:00:00 2001 From: Peter Lejeck Date: Thu, 31 Oct 2013 05:01:18 -0700 Subject: Move upload.php into static dir, and do hardcore refactoring --- static/classes/UploadedFile.class.php | 32 +++++++ static/includes/database.inc.php | 6 ++ static/includes/settings.inc.php | 19 +++++ static/upload.php | 154 ++++++++++++++++++++++++++++++++++ upload.php | 81 ------------------ 5 files changed, 211 insertions(+), 81 deletions(-) create mode 100644 static/classes/UploadedFile.class.php create mode 100644 static/includes/database.inc.php create mode 100644 static/includes/settings.inc.php create mode 100644 static/upload.php delete mode 100644 upload.php diff --git a/static/classes/UploadedFile.class.php b/static/classes/UploadedFile.class.php new file mode 100644 index 0000000..5b7ba9b --- /dev/null +++ b/static/classes/UploadedFile.class.php @@ -0,0 +1,32 @@ +sha1) $this->sha1 = sha1_file($this->tempfile); + + return $this->sha1; + } + /** + * Generates the CRC32 or returns the cached CRC32 hash for the file. + */ + public function get_crc32 () { + if (! $this->crc32) $this->crc32 = hash_file('crc32b', $this->tempfile); + + return $this->crc32; + } +} +?> diff --git a/static/includes/database.inc.php b/static/includes/database.inc.php new file mode 100644 index 0000000..2ed0274 --- /dev/null +++ b/static/includes/database.inc.php @@ -0,0 +1,6 @@ + diff --git a/static/includes/settings.inc.php b/static/includes/settings.inc.php new file mode 100644 index 0000000..8a7fc7b --- /dev/null +++ b/static/includes/settings.inc.php @@ -0,0 +1,19 @@ + diff --git a/static/upload.php b/static/upload.php new file mode 100644 index 0000000..da5e311 --- /dev/null +++ b/static/upload.php @@ -0,0 +1,154 @@ +name, PATHINFO_EXTENSION); + // Take the first 3 chars of the CRC32 checksum + $hashchunk = substr($file->get_crc32(), 0, 3); + do { + // If we run out of tries, throw an exception. Should be caught and JSONified. + if ($tries-- == 0) throw new Exception('Gave up trying to find an unused name'); + + // TODO: come up with a better name generating algorithm + $newname = ''; // Filename Generator: + $newname .= chr(mt_rand(ord("a"), ord("z"))); // + random lowercase letter + $newname .= $hashchunk; // + first 3 of crc32b checksum + $newname .= chr(mt_rand(ord("a"), ord("z"))); // + random lowercase letter + $newname .= '.' . $ext; // + '.' + extension + + } while (file_exists(POMF_FILES_ROOT . $newname)); // TODO: check the database instead? + + return $newname; +} + +/** + * Handles the uploading and db entry for a file + * + * @param UploadedFile $file + * @returns array + */ +function upload_file ($file) { + global $db; + + // If the file has an error attached, we just throw it as an exception. + if ($file->error) throw new Exception($file->error); + + // Check if we have a file with that hash in the db + $q = $db->prepare("SELECT hash, filename, size FROM files WHERE hash = (:hash)"); + $q->bindValue('hash', $file->get_sha1()); + $q->execute(); + $result = $q->fetch(); + + // If we found a file with the same checksums, then we can assume it's a dupe + // so we don't bother with it, and just unlink (delete) the tmpfile and return + // the previous data. + if ($result['hash'] === $file->get_sha1()) { + unlink($file->tempfile); + return $result; + } else { + // Generate a name for the file + $newname = generate_name($file); + + // Attempt to move it to the static directory + if (move_uploaded_file($file->tempfile, POMF_FILES_ROOT . $newname)) { + // Add it to the database + $q = $db->prepare('INSERT INTO files (hash, orginalname, filename, size, date, expire, delid)' . + 'VALUES (:hash, :orig, :name, :size, :date, :expires, :delid)'); + $q->bindValue(':hash', $file->get_sha1()); + $q->bindValue(':orig', $file->name); + $q->bindValue(':name', $newname); + $q->bindValue(':size', $file->size); + $q->bindValue(':date', date('Y-m-d')); + $q->bindValue(':expires', null); + $q->bindValue(':delid', sha1($file->tempfile)); + $q->execute(); + + return array( + 'hash' => $file->get_sha1(), + 'name' => $file->name, + 'url' => $newname, + 'size' => $file->size + ); + } else { + throw new Exception('Failed to move file to destination'); + } + } +} + +/** + * Reorganize the $_FILES array into something saner + * + * @param $_FILES + */ +function refiles ($files) { + $out = array(); + for ($i = 0, $n = count($files['name']); $i < $n; ++$i) { + // We create a new UploadedFile instance + $file = new UploadedFile(); + // And fill it with our shit + $file->name = $files['name'][$i]; + $file->mime = $files['type'][$i]; + $file->tempfile = $files['tmp_name'][$i]; + $file->error = $files['error'][$i]; + $file->size = $files['size'][$i]; + $out[] = &$file; + } + return $out; +} + +/** + * Responds to a request in JSON form. + */ +function respond ($code, $res = null) { + if (is_int($code)) { // If the code is an integer, we assume it's a response code + http_response_code($code); + } else { // Otherwise we just assume you left off the code and use the default and shift + http_response_code(200); + $res = $code; + } + + // Now we send the response based on the type + if ($res instanceof Exception) { + // If it's an Exception, we put the message in the error field + echo json_encode(array( + 'success' => false, + 'error' => $res->getMessage() + )); + } elseif (is_array($res)) { + // If it's an Array, we merge it with 'success' => true. + // Note that $res is later in the list, so you can override that. + echo json_encode(array_merge(array( + 'success' => true, + 'error' => null + ), $res)); + } +} + +if (isset($_FILES['files'])) { + try { + $uploads = refiles($_FILES['files']); + foreach ($uploads as $upload) { + $out[] = upload_file($upload); + } + respond(array( + 'files' => $out + )); + } catch (Exception $e) { + respond(500, $e); + } +} else { + respond(500, new Exception('Nigga what you doin\' here?')); +} +?> diff --git a/upload.php b/upload.php deleted file mode 100644 index 5c611fc..0000000 --- a/upload.php +++ /dev/null @@ -1,81 +0,0 @@ - array(), "success" => true); - $files = $_FILES["files"]; - $num_files = count($files["name"]); - - for ($i = 0; $i < $num_files; $i++) { - //Check if file exists already - $filehash = sha1_file($files["tmp_name"][$i]); - $con = new PDO('mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=XXX', 'XXX', 'XXX'); - $do = $con->prepare("SELECT hash, filename FROM files WHERE hash = (:hash)"); - $do->bindParam(':hash', $filehash); - $do->execute(); - $result = $do->fetch(); - if($result[0]==$filehash){ - $out["files"][] = array( - "name" => $files["name"][$i], - "url" => $result[1] - ); - }else{ - $catshit = hash_file('crc32b', $files["tmp_name"][$i]); - $newname = generate_name($files["name"][$i], $catshit); - //Generate delid - $delid = sha1($files["tmp_name"][$i]); - //Try to upload and other shit - if ($newname && $files["error"][$i] == 0 && move_uploaded_file($files["tmp_name"][$i], $static_root.$newname)) { - //Insert info into DB - $do = $con->prepare("INSERT INTO files (hash, orginalname, filename, size, date, expire, delid) VALUES (:hash, :orginname, :filename, :size, :date, :expire, :delid)"); - $do->bindParam(':hash', $filehash); - $do->bindParam(':orginname', $files["name"][$i]); - $do->bindParam(':filename', $newname); - $do->bindParam(':size', $files["size"][$i]); - $do->bindParam(':date', date('Y-m-d')); - $do->bindParam(':expire', $expire); - $do->bindParam(':delid', $delid); - $do->execute(); - $out["files"][] = array( - "name" => $files["name"][$i], - "url" => $newname - ); - //Otherwise return error - } else { - http_response_code(500); - echo json_encode(array( - "success" => false - )); - } - } - } - $con = null; - exit(json_encode($out, JSON_PRETTY_PRINT)); -} - -if(isset($_FILES["files"])){ -upload(); -}else{ -exit("What ya doing here nigga?"); -} - - -?> -- cgit v1.2.3