summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Lejeck <peter.lejeck@gmail.com>2013-10-31 13:01:18 +0100
committerPeter Lejeck <peter.lejeck@gmail.com>2013-10-31 13:01:18 +0100
commitafc3e0f15e6c4e69d17fd5a84253a436a4fba4fc (patch)
tree196fcab3f38edf81a00b9b95b4bc64c0a9ee2713
parent3cb3570707b13e5e2ae3097a7e872d6c798f7db8 (diff)
Move upload.php into static dir, and do hardcore refactoring
-rw-r--r--static/classes/UploadedFile.class.php32
-rw-r--r--static/includes/database.inc.php6
-rw-r--r--static/includes/settings.inc.php19
-rw-r--r--static/upload.php154
-rw-r--r--upload.php81
5 files changed, 211 insertions, 81 deletions
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 @@
+<?php
+
+class UploadedFile {
+ /* Public attributes */
+ public $name;
+ public $mime;
+ public $tempfile;
+ public $error;
+ public $size;
+
+ /* Cached checksums */
+ private $sha1;
+ private $crc32;
+
+ /**
+ * Generates the SHA1 or returns the cached SHA1 hash for the file.
+ */
+ public function get_sha1 () {
+ if (! $this->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 @@
+<?php
+include_once 'settings.inc.php';
+
+/* NOTE: we don't have to unref the PDO because we're not long-running */
+$db = new PDO(POMF_DB_CONN, POMF_DB_USER, POMF_DB_PASS);
+?>
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 @@
+<?php
+/**
+ * PDO Connection data
+ */
+// PDO socket
+define('POMF_DB_CONN', 'mysql:host=localhost;dbname=pomf');
+// PDO user
+define('POMF_DB_USER', 'pomf');
+// PDO password
+define('POMF_DB_PASS', '***');
+
+/**
+ * File stuff
+ */
+// Root location of files
+define('POMF_FILES_ROOT', '/mnt/disk1/pomf/files/');
+// How many times to retry when exists() before giving up
+define('POMF_FILES_RETRIES', 5);
+?>
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 @@
+<?php
+include_once 'classes/UploadedFile.class.php';
+include_once 'includes/settings.inc.php';
+include_once 'includes/database.inc.php';
+
+/**
+ * Generates a name for the file, retrying until we get an unused one
+ *
+ * @param UploadedFile $file
+ * @returns string
+ */
+function generate_name ($file) {
+ // We start at N retries, and --N until we give up
+ $tries = POMF_FILES_RETRIES;
+ // We rip out the extension using pathinfo
+ // TODO: figure out a solution for .tar.gz and similar files?
+ $ext = pathinfo($file->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 @@
-<?php
-function generate_name ($name, $grill) {
- if (!isset($tries)) $tries = 5;
- $ext = '.' . pathinfo($name, PATHINFO_EXTENSION);
- $fuck = substr($grill, 0, 3);
- do {
- $newname = '';
- $newname .= chr(mt_rand(ord("a"), ord("z")));
- $newname .= $fuck;
- $newname .= chr(mt_rand(ord("a"), ord("z")));
- $newname .= $ext;
-
- if (--$tries == 0) return false;
- } while (file_exists('/mnt/disk1/pomf/files/'.$newname));
-
- return $newname;
-}
-
-
- //Upload and whatnot
- function upload (){
- $static_root = "/mnt/disk1/pomf/files/";
- $out = array( "files" => 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?");
-}
-
-
-?>