summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2014-11-08 17:25:31 +0100
committerFlorian Pritz <bluewind@xinu.at>2014-11-28 14:51:03 +0100
commite60b5468afe0a0d6aa9dab2e6dcf9d186dd168fd (patch)
tree10f8edd85a0758a86f60ee113457766bee322d1d
parenta6655941189e692c4ff06aa41a65e4ac7f0e82fd (diff)
Signed-off-by: Florian Pritz <bluewind@xinu.at>
-rw-r--r--application/controllers/file.php59
-rw-r--r--application/helpers/filebin_helper.php27
-rw-r--r--application/models/mfile.php53
3 files changed, 91 insertions, 48 deletions
diff --git a/application/controllers/file.php b/application/controllers/file.php
index 2617d4840..25fbd27e3 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -90,7 +90,7 @@ class File extends MY_Controller {
$etag = "";
foreach ($files as $filedata) {
- $etag = sha1($etag.$filedata["hash"]);
+ $etag = sha1($etag.$filedata["data_id"]);
}
// handle some common "lexers" here
@@ -128,7 +128,7 @@ class File extends MY_Controller {
handle_etag($etag);
$filedata = $files[0];
- $filepath = $this->mfile->file($filedata["hash"]);
+ $filepath = $this->mfile->file($filedata["data_id"]);
$this->ddownload->serveFile($filepath, $filedata["filename"], "text/plain");
exit();
}
@@ -136,7 +136,7 @@ class File extends MY_Controller {
$this->load->library("output_cache");
foreach ($files as $key => $filedata) {
- $file = $this->mfile->file($filedata['hash']);
+ $file = $this->mfile->file($filedata['data_id']);
// autodetect the lexer for highlighting if the URL contains a / after the ID (/ID/)
// /ID/lexer disables autodetection
@@ -272,9 +272,9 @@ class File extends MY_Controller {
{
// highlight the file and cache the result, fall back to plain text if $lexer fails
foreach (array($lexer, "text") as $lexer) {
- $highlit = cache_function($filedata['hash'].'_'.$lexer, 100,
+ $highlit = cache_function($filedata['data_id'].'_'.$lexer, 100,
function() use ($filedata, $lexer, $is_multipaste) {
- $file = $this->mfile->file($filedata['hash']);
+ $file = $this->mfile->file($filedata['data_id']);
if ($lexer == "rmd") {
ob_start();
@@ -323,7 +323,7 @@ class File extends MY_Controller {
private function _tooltip_for_image($filedata)
{
$filesize = format_bytes($filedata["filesize"]);
- list($width, $height) = getimagesize($this->mfile->file($filedata["hash"]));
+ list($width, $height) = getimagesize($this->mfile->file($filedata["data_id"]));
$upload_date = date("r", $filedata["date"]);
$tooltip = "${filedata["id"]} - $filesize<br>";
@@ -405,7 +405,7 @@ class File extends MY_Controller {
$filename = $filedata["id"]."-".$filedata["filename"];
}
assert(!isset($seen[$filename]));
- $a->addFile($this->mfile->file($filedata["hash"]), $filename);
+ $a->addFile($this->mfile->file($filedata["data_id"]), $filename);
$seen[$filename] = true;
}
$archive->gzip_compress();
@@ -457,7 +457,7 @@ class File extends MY_Controller {
if (count($ids) == 1) {
$filedata = $this->mfile->get_filedata($id);
- $file = $this->mfile->file($filedata['hash']);
+ $file = $this->mfile->file($filedata['data_id']);
$type = $filedata['mimetype'];
$lexer = $this->mfile->should_highlight($type);
@@ -531,7 +531,7 @@ class File extends MY_Controller {
$filedata = $this->mfile->get_filedata($repaste_id);
if ($filedata !== false && $this->mfile->can_highlight($filedata["mimetype"])) {
- $this->data["textarea_content"] = file_get_contents($this->mfile->file($filedata["hash"]));
+ $this->data["textarea_content"] = file_get_contents($this->mfile->file($filedata["data_id"]));
}
}
@@ -568,11 +568,11 @@ class File extends MY_Controller {
show_error("Failed to get file data");
}
- $cache_key = $filedata['hash'].'_thumb_'.$thumb_size;
+ $cache_key = $filedata['data_id'].'_thumb_'.$thumb_size;
$thumb = cache_function($cache_key, 100, function() use ($filedata, $thumb_size){
$CI =& get_instance();
- $img = new libraries\Image($this->mfile->file($filedata["hash"]));
+ $img = new libraries\Image($this->mfile->file($filedata["data_id"]));
$img->makeThumb($thumb_size, $thumb_size);
$thumb = $img->get(IMAGETYPE_JPEG);
@@ -596,8 +596,9 @@ class File extends MY_Controller {
$user = $this->muser->get_userid();
$query = $this->db
- ->select('id, filename, mimetype, date, hash, filesize')
+ ->select('files.id, filename, mimetype, date, hash, hash_collision_counter, filesize')
->from('files')
+ ->join('file_storage', 'file_storage.id = files.file_storage_id')
->where('user', $user)
->where_in('mimetype', array('image/jpeg', 'image/png', 'image/gif'))
->order_by('date', 'desc')
@@ -609,7 +610,7 @@ class File extends MY_Controller {
continue;
}
$query[$key]["tooltip"] = $this->_tooltip_for_image($item);
- $query[$key]["orientation"] = libraries\Image::get_exif_orientation($this->mfile->file($item["hash"]));
+ $query[$key]["orientation"] = libraries\Image::get_exif_orientation($this->mfile->file($item["data_id"]));
}
$this->data["items"] = $query;
@@ -630,7 +631,7 @@ class File extends MY_Controller {
// key: database field name; value: display name
$fields = array(
- "id" => "ID",
+ "files.id" => "ID",
"filename" => "Filename",
"mimetype" => "Mimetype",
"date" => "Date",
@@ -647,14 +648,16 @@ class File extends MY_Controller {
$items = $this->db->select(implode(',', array_keys($fields)))
->from('files')
+ ->join('file_storage', 'file_storage.id = files.file_storage_id')
->where('user', $user)
->get()->result_array();
$query = $this->db->query("
- SELECT m.url_id id, sum(f.filesize) filesize, m.date, '' hash, '' mimetype, concat(count(*), ' file(s)') filename
+ SELECT m.url_id id, sum(fs.filesize) filesize, m.date, '' hash, '' mimetype, concat(count(*), ' file(s)') filename
FROM multipaste m
JOIN multipaste_file_map mfm ON m.multipaste_id = mfm.multipaste_id
JOIN files f ON f.id = mfm.file_url_id
+ JOIN file_storage fs ON f.file_storage_id = fs.id
WHERE m.user_id = ?
GROUP BY m.url_id
", array($user))->result_array();
@@ -688,8 +691,9 @@ class File extends MY_Controller {
$total_size = $this->db->query("
SELECT sum(filesize) sum
FROM (
- SELECT DISTINCT hash, filesize
+ SELECT DISTINCT hash, hash_collision_counter, filesize
FROM files
+ JOIN file_storage ON file_storage.id = files.file_storage_id
WHERE user = ?
) sub
", array($user))->row_array();
@@ -950,6 +954,9 @@ class File extends MY_Controller {
}
foreach ($files as $key => $file) {
+ // FIXME: use refactored code from api-rework branch here
+ // FIXME: remove hash_collision_counter from db and simply use the
+ // ID (so we can atomically insert and the get the last_insert_id
$limits = $this->muser->get_upload_id_limits();
$id = $this->mfile->new_id($limits[0], $limits[1]);
$hash = md5_file($file['tmp_name']);
@@ -1078,7 +1085,7 @@ class File extends MY_Controller {
$small_upload_size = $this->config->item('small_upload_size');
- $query = $this->db->select('hash, id, user')
+ $query = $this->db->select('hash, hash_collision_counter, id, user')
->from('files')
->where('date <', $oldest_time)
->or_where('('.$this->db->_protect_identifiers('user').' = 0 AND '
@@ -1086,7 +1093,7 @@ class File extends MY_Controller {
->get()->result_array();
foreach($query as $row) {
- $file = $this->mfile->file($row['hash']);
+ $file = $this->mfile->file($row['data_id']);
if (!file_exists($file)) {
$this->mfile->delete_id($row["id"]);
continue;
@@ -1095,10 +1102,10 @@ class File extends MY_Controller {
if ($row["user"] == 0 || filesize($file) > $small_upload_size) {
if (filemtime($file) < $oldest_time) {
unlink($file);
- $this->mfile->delete_hash($row["hash"]);
+ $this->mfile->delete_data_id($row["data_id"]);
} else {
$this->mfile->delete_id($row["id"]);
- if ($this->mfile->stale_hash($row["hash"])) {
+ if ($this->mfile->stale_data_id($row["data_id"])) {
unlink($file);
}
}
@@ -1166,9 +1173,9 @@ class File extends MY_Controller {
return;
}
- $hash = $file_data["hash"];
- $this->mfile->delete_hash($hash);
- echo "removed hash \"$hash\"\n";
+ $data_id = $file_data["data_id"];
+ $this->mfile->delete_data_id($data_id);
+ echo "removed data_id \"$data_id\"\n";
}
function update_file_metadata()
@@ -1187,9 +1194,9 @@ class File extends MY_Controller {
->get()->result_array();
foreach ($query as $key => $item) {
- $hash = $item["hash"];
- $filesize = intval(filesize($this->mfile->file($hash)));
- $mimetype = $this->mfile->mimetype($this->mfile->file($hash));
+ $data_id = $item["data_id"];
+ $filesize = intval(filesize($this->mfile->file($data_id)));
+ $mimetype = $this->mfile->mimetype($this->mfile->file($data_id));
$this->db->where('hash', $hash)
->set(array(
diff --git a/application/helpers/filebin_helper.php b/application/helpers/filebin_helper.php
index e5637ce94..acec213a9 100644
--- a/application/helpers/filebin_helper.php
+++ b/application/helpers/filebin_helper.php
@@ -283,4 +283,31 @@ function cache_function($key, $ttl, $function)
return $content;
}
+function files_are_equal($a, $b)
+{
+ $chunk_size = 8*1024;
+
+ // Check if filesize is different
+ if (filesize($a) !== filesize($b)) {
+ return false;
+ }
+
+ // Check if content is different
+ $ah = fopen($a, 'rb');
+ $bh = fopen($b, 'rb');
+
+ $result = true;
+ while (!feof($ah) && !feof($bh)) {
+ if (fread($ah, $chunk_size) !== fread($bh, $chunk_size)) {
+ $result = false;
+ break;
+ }
+ }
+
+ fclose($ah);
+ fclose($bh);
+
+ return $result;
+}
+
# vim: set noet:
diff --git a/application/models/mfile.php b/application/models/mfile.php
index eee2c4e5b..d6851a6ef 100644
--- a/application/models/mfile.php
+++ b/application/models/mfile.php
@@ -70,27 +70,30 @@ class Mfile extends CI_Model {
function get_filedata($id)
{
$query = $this->db
- ->select('id, hash, filename, mimetype, date, user, filesize')
+ ->select('files.id, hash, hash_collision_counter, filename, mimetype, date, user, filesize')
->from('files')
- ->where('id', $id)
+ ->join('file_storage', 'file_storage.id = files.file_storage_id')
+ ->where('files.id', $id)
->limit(1)
->get();
if ($query->num_rows() > 0) {
- return $query->row_array();
+ $data = $query->row_array();
+ $data["data_id"] = $data["hash"]."-".$data["hash_collision_counter"];
+ return $data;
} else {
return false;
}
}
- // return the folder in which the file with $hash is stored
- function folder($hash) {
- return $this->config->item('upload_path').'/'.substr($hash, 0, 3);
+ // return the folder in which the file with $data_id is stored
+ function folder($data_id) {
+ return $this->config->item('upload_path').'/'.substr($data_id, 0, 3);
}
- // Returns the full path to the file with $hash
- function file($hash) {
- return $this->folder($hash).'/'.$hash;
+ // Returns the full path to the file with $data_id
+ function file($data_id) {
+ return $this->folder($data_id).'/'.$data_id;
}
// Return mimetype of file
@@ -136,10 +139,10 @@ class Mfile extends CI_Model {
if (!$filedata) {
return false;
}
- $file = $this->file($filedata['hash']);
+ $file = $this->file($filedata['data_id']);
if (!file_exists($file)) {
- $this->delete_hash($filedata["hash"]);
+ $this->delete_data_id($filedata["data_id"]);
return false;
}
@@ -158,7 +161,7 @@ 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) {
- $this->delete_hash($filedata["hash"]);
+ $this->delete_data_id($filedata["data_id"]);
} else {
$this->delete_id($id);
}
@@ -171,7 +174,7 @@ class Mfile extends CI_Model {
public function get_timeout($id)
{
$filedata = $this->get_filedata($id);
- $file = $this->file($filedata["hash"]);
+ $file = $this->file($filedata["data_id"]);
if ($this->config->item("upload_max_age") == 0) {
return -1;
@@ -195,11 +198,14 @@ class Mfile extends CI_Model {
}
}
- private function unused_file($hash)
+ private function unused_file($data_id)
{
- $query = $this->db->select('id')
+ list ($hash, $hash_collision_counter) = explode("-", $data_id);
+ $query = $this->db->select('files.id')
->from('files')
+ ->join('file_storage', 'file_storage.id = files.file_storage_id')
->where('hash', $hash)
+ ->where('hash_collision_counter', $hash_collision_counter)
->limit(1)
->get();
@@ -238,12 +244,12 @@ class Mfile extends CI_Model {
}
if ($filedata !== false) {
- assert(isset($filedata["hash"]));
- if ($this->unused_file($filedata['hash'])) {
- if (file_exists($this->file($filedata['hash']))) {
- unlink($this->file($filedata['hash']));
+ assert(isset($filedata["data_id"]));
+ if ($this->unused_file($filedata['data_id'])) {
+ if (file_exists($this->file($filedata['data_id']))) {
+ unlink($this->file($filedata['data_id']));
}
- $dir = $this->folder($filedata['hash']);
+ $dir = $this->folder($filedata['data_id']);
if (file_exists($dir)) {
if (count(scandir($dir)) == 2) {
rmdir($dir);
@@ -254,11 +260,14 @@ class Mfile extends CI_Model {
return true;
}
- public function delete_hash($hash)
+ public function delete_data_id($data_id)
{
- $ids = $this->db->select('id')
+ list ($hash, $hash_collision_counter) = explode("-", $data_id);
+ $ids = $this->db->select('files.id')
->from('files')
+ ->join('file_storage', 'file_storage.id = files.file_storage_id')
->where('hash', $hash)
+ ->where('hash_collision_counter', $hash_collision_counter)
->get()->result_array();
foreach ($ids as $entry) {