summaryrefslogtreecommitdiffstats
path: root/application/models
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2014-08-29 17:41:33 +0200
committerFlorian Pritz <bluewind@xinu.at>2014-08-29 17:43:19 +0200
commitd7621c2c01074bdcabd6a8c1a8e95c95d00319bf (patch)
treebfcff5599f26939f185bd0208538b56f39a3dc57 /application/models
parent08c68f84f4a8519912e31f85823694186de804cf (diff)
add multipaste support
Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'application/models')
-rw-r--r--application/models/mfile.php118
-rw-r--r--application/models/mmultipaste.php160
2 files changed, 246 insertions, 32 deletions
diff --git a/application/models/mfile.php b/application/models/mfile.php
index c900b297c..427c74a18 100644
--- a/application/models/mfile.php
+++ b/application/models/mfile.php
@@ -71,15 +71,14 @@ class Mfile extends CI_Model {
function get_filedata($id)
{
$sql = '
- SELECT hash, filename, mimetype, date, user, filesize
+ SELECT id, hash, filename, mimetype, date, user, filesize
FROM `files`
WHERE `id` = ?
LIMIT 1';
$query = $this->db->query($sql, array($id));
- if ($query->num_rows() == 1) {
- $return = $query->result_array();
- return $return[0];
+ if ($query->num_rows() > 0) {
+ return $query->row_array();
} else {
return false;
}
@@ -214,10 +213,15 @@ class Mfile extends CI_Model {
$mimetype = $this->mimetype($this->file($hash));
$filesize = filesize($this->file($hash));
- $query = $this->db->query('
- INSERT INTO `files` (`hash`, `id`, `filename`, `user`, `date`, `mimetype`, `filesize`)
- VALUES (?, ?, ?, ?, ?, ?, ?)',
- array($hash, $id, $filename, $userid, time(), $mimetype, $filesize));
+ $this->db->insert("files", array(
+ "id" => $id,
+ "hash" => $hash,
+ "filename" => $filename,
+ "date" => time(),
+ "user" => $userid,
+ "mimetype" => $mimetype,
+ "filesize" => $filesize,
+ ));
}
function adopt($id)
@@ -241,9 +245,7 @@ class Mfile extends CI_Model {
$file = $this->file($filedata['hash']);
if (!file_exists($file)) {
- if (isset($filedata["hash"])) {
- $this->db->query('DELETE FROM files WHERE hash = ?', array($filedata['hash']));
- }
+ $this->delete_hash($filedata["hash"]);
return false;
}
@@ -262,10 +264,9 @@ class Mfile extends CI_Model {
// if the file has been uploaded multiple times the mtime is the time
// of the last upload
if (filemtime($file) < $remove_before) {
- unlink($file);
- $this->db->query('DELETE FROM files WHERE hash = ?', array($filedata['hash']));
+ $this->delete_hash($filedata["hash"]);
} else {
- $this->db->query('DELETE FROM files WHERE id = ? LIMIT 1', array($id));
+ $this->delete_id($id);
}
return false;
}
@@ -273,13 +274,28 @@ class Mfile extends CI_Model {
return true;
}
- function get_timeout_string($id)
+ public function get_timeout($id)
{
$filedata = $this->get_filedata($id);
$file = $this->file($filedata["hash"]);
+ if ($this->config->item("upload_max_age") == 0) {
+ return -1;
+ }
+
if (filesize($file) > $this->config->item("small_upload_size")) {
- return date("r", $filedata["date"] + $this->config->item("upload_max_age"));
+ return $filedata["date"] + $this->config->item("upload_max_age");
+ } else {
+ return -1;
+ }
+ }
+
+ public function get_timeout_string($id)
+ {
+ $timeout = $this->get_timeout($id);
+
+ if ($timeout >= 0) {
+ return date("r", $timeout);
} else {
return "unknown";
}
@@ -301,34 +317,72 @@ class Mfile extends CI_Model {
}
}
- function delete_id($id)
+ public function delete_id($id)
{
$filedata = $this->get_filedata($id);
- $userid = $this->muser->get_userid();
- if (!$this->id_exists($id)) {
- return false;
- }
-
- $sql = '
- DELETE
- FROM `files`
- WHERE `id` = ?
- AND user = ?
- LIMIT 1';
- $this->db->query($sql, array($id, $userid));
+ // Delete the file and all multipastes using it
+ // Note that this does not delete all relations in multipaste_file_map
+ // which is actually done by a SQL contraint.
+ // TODO: make it work properly without the constraint
+ $this->db->query('
+ DELETE m, mfm, f
+ FROM files f
+ LEFT JOIN multipaste_file_map mfm ON f.id = mfm.file_url_id
+ LEFT JOIN multipaste m ON mfm.multipaste_id = m.multipaste_id
+ WHERE f.id = ?
+ ', array($id));
if ($this->id_exists($id)) {
return false;
}
- if ($this->unused_file($filedata['hash'])) {
- unlink($this->file($filedata['hash']));
- @rmdir($this->folder($filedata['hash']));
+ if ($filedata !== false) {
+ assert(isset($filedata["hash"]));
+ if ($this->unused_file($filedata['hash'])) {
+ unlink($this->file($filedata['hash']));
+ $dir = $this->folder($filedata['hash']);
+ if (count(scandir($dir)) == 2) {
+ rmdir($dir);
+ }
+ }
}
return true;
}
+ public function delete_hash($hash)
+ {
+ // Delete all files with this hash and all multipastes using any of those files
+ // Note that this does not delete all relations in multipaste_file_map
+ // which is actually done by a SQL contraint.
+ // TODO: make it work properly without the constraint
+ $this->db->query('
+ DELETE m, mfm, f
+ FROM files f
+ LEFT JOIN multipaste_file_map mfm ON f.id = mfm.file_url_id
+ LEFT JOIN multipaste m ON mfm.multipaste_id = m.multipaste_id
+ WHERE f.hash = ?
+ ', array($hash));
+
+ if (file_exists($this->file($hash))) {
+ unlink($this->file($hash));
+ $dir = $this->folder($hash);
+ if (count(scandir($dir)) == 2) {
+ rmdir($dir);
+ }
+ }
+ return true;
+ }
+
+ public function get_owner($id)
+ {
+ return $this->db->query("
+ SELECT user
+ FROM files
+ WHERE id = ?
+ ", array($id))->row_array()["user"];
+ }
+
public function get_lexers() {
return cache_function('lexers', 1800, function() {
$lexers = array();
diff --git a/application/models/mmultipaste.php b/application/models/mmultipaste.php
new file mode 100644
index 000000000..723132a50
--- /dev/null
+++ b/application/models/mmultipaste.php
@@ -0,0 +1,160 @@
+<?php
+/*
+ * Copyright 2014 Florian "Bluewind" Pritz <bluewind@server-speed.net>
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+class Mmultipaste extends CI_Model {
+
+ function __construct()
+ {
+ parent::__construct();
+ $this->load->model("muser");
+ $this->load->model("mfile");
+ }
+
+ /**
+ * Returns an unused ID
+ *
+ * @param min minimal length of the resulting ID
+ * @param max maximum length of the resulting ID
+ */
+ public function new_id($min = 3, $max = 6)
+ {
+ static $id_blacklist = NULL;
+
+ if ($id_blacklist == NULL) {
+ // This prevents people from being unable to access their uploads
+ // because of URL rewriting
+ $id_blacklist = scandir(FCPATH);
+ $id_blacklist[] = "file";
+ $id_blacklist[] = "user";
+ }
+
+ $max_tries = 100;
+
+ for ($try = 0; $try < $max_tries; $try++) {
+ $id = "m-".random_alphanum($min, $max);
+
+ // TODO: try to insert the id into file_groups instead of checking with
+ // id_exists (prevents race conditio)
+ if ($this->id_exists($id) || in_array($id, $id_blacklist)) {
+ continue;
+ }
+
+ $this->db->insert("multipaste", array(
+ "url_id" => $id,
+ "user_id" => $this->muser->get_userid(),
+ "date" => time(),
+ ));
+
+ return $id;
+ }
+
+ show_error("Failed to find unused ID after $max_tries tries.");
+ }
+
+ public function id_exists($id)
+ {
+ if (!$id) {
+ return false;
+ }
+
+ $sql = '
+ SELECT multipaste.url_id
+ FROM multipaste
+ WHERE multipaste.url_id = ?
+ LIMIT 1';
+ $query = $this->db->query($sql, array($id));
+
+ if ($query->num_rows() == 1) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function valid_id($id)
+ {
+ $files = $this->get_files($id);
+ foreach ($files as $file) {
+ if (!$this->mfile->valid_id($file["id"])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public function delete_id($id)
+ {
+ $this->db->query('
+ DELETE m, mfm
+ FROM multipaste m
+ LEFT JOIN multipaste_file_map mfm ON mfm.multipaste_id = m.multipaste_id
+ WHERE m.url_id = ?
+ ', array($id));
+
+ if ($this->id_exists($id)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function get_owner($id)
+ {
+ return $this->db->query("
+ SELECT user_id
+ FROM multipaste
+ WHERE url_id = ?
+ ", array($id))->row_array()["user_id"];
+ }
+
+ public function get_multipaste($id)
+ {
+ return $this->db->query("
+ SELECT url_id, user_id, date
+ FROM multipaste
+ WHERE url_id = ?
+ ", array($id))->row_array();
+ }
+
+ public function get_files($url_id)
+ {
+ $ret = array();
+
+ $query = $this->db->query("
+ SELECT mfm.file_url_id
+ FROM multipaste_file_map mfm
+ JOIN multipaste m ON m.multipaste_id = mfm.multipaste_id
+ WHERE m.url_id = ?
+ ORDER BY mfm.sort_order
+ ", array($url_id))->result_array();
+
+ foreach ($query as $row) {
+ $filedata = $this->mfile->get_filedata($row["file_url_id"]);
+ $ret[] = $filedata;
+ }
+
+ return $ret;
+ }
+
+ public function get_multipaste_id($url_id)
+ {
+ $query = $this->db->query("
+ SELECT multipaste_id
+ FROM multipaste
+ WHERE url_id = ?
+ ", array($url_id));
+
+ if ($query->num_rows() > 0) {
+ return $query->row_array()["multipaste_id"];
+ }
+
+ return false;
+ }
+
+}