summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/controllers/file.php186
-rw-r--r--application/helpers/filebin_helper.php22
-rw-r--r--application/models/file_mod.php214
3 files changed, 210 insertions, 212 deletions
diff --git a/application/controllers/file.php b/application/controllers/file.php
index b8306b5bc..c84620d4f 100644
--- a/application/controllers/file.php
+++ b/application/controllers/file.php
@@ -62,14 +62,190 @@ class File extends CI_Controller {
if(isset($_FILES['file'])) {
$this->do_upload();
} elseif ($id != "file" && $this->file_mod->id_exists($id)) {
- $this->file_mod->download();
+ $this->_download();
} elseif ($id && $id != "file") {
- $this->file_mod->non_existent();
+ $this->_non_existent();
} else {
$this->upload_form();
}
}
+ function _download()
+ {
+ $id = $this->uri->segment(1);
+ $mode = $this->uri->segment(2);
+
+ $filedata = $this->file_mod->get_filedata($id);
+ $file = $this->file_mod->file($filedata['hash']);
+
+ if (!$this->file_mod->valid_id($id)) {
+ $this->non_existent();
+ return;
+ }
+
+ // don't allow unowned files to be downloaded
+ if ($filedata["user"] == 0) {
+ $this->file_mod->non_existent();
+ return;
+ }
+
+ // helps to keep traffic low when reloading
+ $etag = $filedata["hash"]."-".$filedata["date"];
+
+ // autodetect the mode for highlighting if the URL contains a / after the ID (/ID/)
+ // /ID/mode disables autodetection
+ $autodetect_mode = !$mode && substr_count(ltrim($this->uri->uri_string(), "/"), '/') >= 1;
+
+ if ($autodetect_mode) {
+ $mode = $this->file_mod->get_highlight_mode($filedata["mimetype"], $filedata["filename"]);
+ }
+
+ // resolve aliases of modes
+ // this is mainly used for compatibility
+ $mode = $this->file_mod->resolve_mode_alias($mode);
+
+ // create the qr code for /ID/
+ if ($mode == "qr") {
+ handle_etag($etag);
+ header("Content-disposition: inline; filename=\"".$id."_qr.png\"\n");
+ header("Content-Type: image/png\n");
+ passthru('qrencode -s 10 -o - '.escapeshellarg(site_url($id).'/'));
+ exit();
+ }
+
+ // user wants to the the plain file
+ if ($mode == 'plain') {
+ handle_etag($etag);
+ rangeDownload($file, $filedata["filename"], "text/plain");
+ exit();
+ }
+
+ if ($mode == 'info') {
+ $this->_display_info($id);
+ return;
+ }
+
+ // if there is no mimetype mapping we can't highlight it
+ $can_highlight = $this->file_mod->can_highlight($filedata["mimetype"]);
+
+ $filesize_too_big = filesize($file) > $this->config->item('upload_max_text_size');
+
+ if (!$can_highlight || $filesize_too_big || !$mode) {
+ // prevent javascript from being executed and forbid frames
+ // this should allow us to serve user submitted HTML content without huge security risks
+ foreach (array("X-WebKit-CSP", "X-Content-Security-Policy") as $header_name) {
+ header("$header_name: allow 'none'; img-src *; media-src *; font-src *; style-src * 'unsafe-inline'; script-src 'none'; object-src *; frame-src 'none'; ");
+ }
+ handle_etag($etag);
+ rangeDownload($file, $filedata["filename"], $filedata["mimetype"]);
+ exit();
+ }
+
+ $this->data['title'] = htmlspecialchars($filedata['filename']);
+ $this->data['id'] = $id;
+
+ header("Content-Type: text/html\n");
+
+ $this->data['current_highlight'] = htmlspecialchars($mode);
+ $this->data['timeout'] = $this->file_mod->get_timeout_string($id);
+
+ echo $this->load->view($this->var->view_dir.'/html_header', $this->data, true);
+
+ // highlight the file and chache the result
+ $this->load->library("MemcacheLibrary");
+ if (! $cached = $this->memcachelibrary->get($filedata['hash'].'_'.$mode)) {
+ ob_start();
+ if ($mode == "rmd") {
+ echo '<td class="markdownrender">'."\n";
+ passthru('perl '.FCPATH.'scripts/Markdown.pl '.escapeshellarg($file));
+ } elseif ($mode == "ascii") {
+ echo '<td class="code"><pre class="text">'."\n";
+ passthru('perl '.FCPATH.'scripts/ansi2html '.escapeshellarg($file));
+ echo "</pre>\n";
+ } else {
+ echo '<td class="numbers"><pre>';
+ // generate line numbers (links)
+ passthru('perl -ne \'print "<a href=\"#n$.\" class=\"no\" id=\"n$.\">$.</a>\n"\' '.escapeshellarg($file));
+ echo '</pre></td><td class="code">'."\n";
+ $this->load->library('geshi');
+ $this->geshi->initialize(array('set_language' => $mode, 'set_source' => file_get_contents($file), 'enable_classes' => 'true'));
+ echo $this->geshi->parse_code();
+ }
+ $cached = ob_get_contents();
+ ob_end_clean();
+ $this->memcachelibrary->set($filedata['hash'].'_'.$mode, $cached, 100);
+ }
+ echo $cached;
+
+ echo $this->load->view($this->var->view_dir.'/html_footer', $this->data, true);
+
+ return;
+ }
+
+ function _display_info($id)
+ {
+ $this->data["title"] .= " - Info $id";
+ $this->data["filedata"] = $this->file_mod->get_filedata($id);
+ $this->data["id"] = $id;
+ $this->data['timeout'] = $this->file_mod->get_timeout_string($id);
+
+ $this->load->view($this->var->view_dir.'/header', $this->data);
+ $this->load->view($this->var->view_dir.'/file_info', $this->data);
+ $this->load->view($this->var->view_dir.'/footer', $this->data);
+ }
+
+ function _non_existent()
+ {
+ $this->data["title"] .= " - Not Found";
+ $this->output->set_status_header(404);
+ $this->load->view($this->var->view_dir.'/header', $this->data);
+ $this->load->view($this->var->view_dir.'/non_existent', $this->data);
+ $this->load->view($this->var->view_dir.'/footer', $this->data);
+ }
+
+ function _show_url($id, $mode)
+ {
+ $redirect = false;
+
+ if (!$this->muser->logged_in()) {
+ // keep the upload but require the user to login
+ $this->session->set_userdata("last_upload", array(
+ "id" => $id,
+ "mode" => $mode
+ ));
+ $this->session->set_flashdata("uri", "file/claim_id");
+ $this->muser->require_access();
+ }
+
+ if ($mode) {
+ $this->data['url'] = site_url($id).'/'.$mode;
+ } else {
+ $this->data['url'] = site_url($id).'/';
+
+ $filedata = $this->file_mod->get_filedata($id);
+ $file = $this->file_mod->file($filedata['hash']);
+ $type = $filedata['mimetype'];
+ $mode = $this->file_mod->should_highlight($type);
+
+ // If we detected a highlightable file redirect,
+ // otherwise show the URL because browsers would just show a DL dialog
+ if ($mode) {
+ $redirect = true;
+ }
+ }
+
+ if (is_cli_client()) {
+ $redirect = false;
+ }
+ if ($redirect) {
+ redirect($this->data['url'], "location", 303);
+ } else {
+ $this->load->view($this->var->view_dir.'/header', $this->data);
+ $this->load->view($this->var->view_dir.'/show_url', $this->data);
+ $this->load->view($this->var->view_dir.'/footer', $this->data);
+ }
+ }
+
function client()
{
$this->data['title'] .= ' - Client';
@@ -278,7 +454,7 @@ class File extends CI_Controller {
file_put_contents($file, $content);
chmod($file, 0600);
$this->file_mod->add_file($hash, $id, $filename);
- $this->file_mod->show_url($id, false);
+ $this->_show_url($id, false);
}
// Handles uploaded files
@@ -337,7 +513,7 @@ class File extends CI_Controller {
move_uploaded_file($_FILES['file']['tmp_name'], $file);
chmod($file, 0600);
$this->file_mod->add_file($hash, $id, $filename);
- $this->file_mod->show_url($id, $extension);
+ $this->_show_url($id, $extension);
}
function claim_id()
@@ -357,7 +533,7 @@ class File extends CI_Controller {
$this->session->unset_userdata("last_upload");
- $this->file_mod->show_url($id, $last_upload["mode"]);
+ $this->_show_url($id, $last_upload["mode"]);
}
/* Functions below this comment can only be run via the CLI
diff --git a/application/helpers/filebin_helper.php b/application/helpers/filebin_helper.php
index d9a490bd6..f6663144e 100644
--- a/application/helpers/filebin_helper.php
+++ b/application/helpers/filebin_helper.php
@@ -221,4 +221,26 @@ function link_with_mtime($file)
return $link;
}
+function handle_etag($etag)
+{
+ $etag = strtolower($etag);
+ $modified = true;
+
+ if(isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
+ $oldtag = trim(strtolower($_SERVER['HTTP_IF_NONE_MATCH']), '"');
+ if($oldtag == $etag) {
+ $modified = false;
+ } else {
+ $modified = true;
+ }
+ }
+
+ header('Etag: "'.$etag.'"');
+
+ if (!$modified) {
+ header("HTTP/1.1 304 Not Modified");
+ exit();
+ }
+}
+
# vim: set noet:
diff --git a/application/models/file_mod.php b/application/models/file_mod.php
index f203f8ef9..a60292138 100644
--- a/application/models/file_mod.php
+++ b/application/models/file_mod.php
@@ -9,17 +9,13 @@
class File_mod extends CI_Model {
- public $data;
-
function __construct()
{
parent::__construct();
- $this->data =& get_instance()->data;
$this->load->model("muser");
}
// Returns an unused ID
- // TODO: make threadsafe
function new_id()
{
$id = random_alphanum(3,6);
@@ -79,7 +75,6 @@ class File_mod extends CI_Model {
}
// Add a hash to the DB
- // TODO: Should only update not insert; see new_id()
function add_file($hash, $id, $filename)
{
$userid = $this->muser->get_userid();
@@ -103,58 +98,6 @@ class File_mod extends CI_Model {
", array($userid, $id));
}
- function show_url($id, $mode)
- {
- $redirect = false;
-
- if (!$this->muser->logged_in()) {
- // keep the upload but require the user to login
- $this->session->set_userdata("last_upload", array(
- "id" => $id,
- "mode" => $mode
- ));
- $this->session->set_flashdata("uri", "file/claim_id");
- $this->muser->require_access();
- }
-
- if ($mode) {
- $this->data['url'] = site_url($id).'/'.$mode;
- } else {
- $this->data['url'] = site_url($id).'/';
-
- $filedata = $this->get_filedata($id);
- $file = $this->file($filedata['hash']);
- $type = $filedata['mimetype'];
- $mode = $this->mime2mode($type);
-
- // If we detected a highlightable file redirect,
- // otherwise show the URL because browsers would just show a DL dialog
- if ($mode) {
- $redirect = true;
- }
- }
-
- if (is_cli_client()) {
- $redirect = false;
- }
- if ($redirect) {
- redirect($this->data['url'], "location", 303);
- } else {
- $this->load->view($this->var->view_dir.'/header', $this->data);
- $this->load->view($this->var->view_dir.'/show_url', $this->data);
- $this->load->view($this->var->view_dir.'/footer', $this->data);
- }
- }
-
- function non_existent()
- {
- $this->data["title"] .= " - Not Found";
- $this->output->set_status_header(404);
- $this->load->view($this->var->view_dir.'/header', $this->data);
- $this->load->view($this->var->view_dir.'/non_existent', $this->data);
- $this->load->view($this->var->view_dir.'/footer', $this->data);
- }
-
// remove old/invalid/broken IDs
function valid_id($id)
{
@@ -194,140 +137,6 @@ class File_mod extends CI_Model {
return true;
}
- private function handle_etag($etag) {
- $etag = strtolower($etag);
- $modified = true;
-
- if(isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
- $oldtag = trim(strtolower($_SERVER['HTTP_IF_NONE_MATCH']), '"');
- if($oldtag == $etag) {
- $modified = false;
- } else {
- $modified = true;
- }
- }
-
- header('Etag: "'.$etag.'"');
-
- if (!$modified) {
- header("HTTP/1.1 304 Not Modified");
- exit();
- }
- }
-
- // download a given ID
- // TODO: make smaller
- function download()
- {
- $id = $this->uri->segment(1);
- $mode = $this->uri->segment(2);
-
- $filedata = $this->get_filedata($id);
- $file = $this->file($filedata['hash']);
-
- if (!$this->valid_id($id)) {
- $this->non_existent();
- return;
- }
-
- // don't allow unowned files to be downloaded
- if ($filedata["user"] == 0) {
- $this->non_existent();
- return;
- }
-
- // helps to keep traffic low when reloading
- $etag = $filedata["hash"]."-".$filedata["date"];
-
- $type = $filedata['mimetype'];
-
- // autodetect the mode for highlighting if the URL contains a / after the ID (/ID/)
- // /ID/mode disables autodetection
- $autodetect_mode = !$mode && substr_count(ltrim($this->uri->uri_string(), "/"), '/') >= 1;
-
- if ($autodetect_mode) {
- $mode = $this->get_highlight_mode($type, $filedata["filename"]);
- }
- // resolve aliases of modes
- // this is mainly used for compatibility
- $mode = $this->resolve_mode_alias($mode);
-
- // create the qr code for /ID/
- if ($mode == "qr") {
- $this->handle_etag($etag);
- header("Content-disposition: inline; filename=\"".$id."_qr.png\"\n");
- header("Content-Type: image/png\n");
- passthru('qrencode -s 10 -o - '.escapeshellarg(site_url($id).'/'));
- exit();
- }
-
- // user wants to the the plain file
- if ($mode == 'plain') {
- $this->handle_etag($etag);
- rangeDownload($file, $filedata["filename"], "text/plain");
- exit();
- }
-
- if ($mode == 'info') {
- $this->display_info($id);
- return;
- }
-
- // if there is no mimetype mapping we can't highlight it
- $can_highlight = $this->can_highlight($type);
-
- $filesize_too_big = filesize($file) > $this->config->item('upload_max_text_size');
-
- if (!$can_highlight || $filesize_too_big || !$mode) {
- $this->handle_etag($etag);
- foreach (array("X-WebKit-CSP", "X-Content-Security-Policy") as $header_name) {
- header("$header_name: allow 'none'; img-src *; media-src *; font-src *; style-src * 'unsafe-inline'; script-src 'none'; object-src *; frame-src 'none'; ");
- }
- rangeDownload($file, $filedata["filename"], $type);
- exit();
- }
-
- $this->data['title'] = htmlspecialchars($filedata['filename']);
- $this->data['id'] = $id;
-
- header("Content-Type: text/html\n");
-
- $this->data['current_highlight'] = htmlspecialchars($mode);
- $this->data['timeout'] = $this->get_timeout_string($id);
-
- echo $this->load->view($this->var->view_dir.'/html_header', $this->data, true);
-
- // highlight the file and chache the result
- $this->load->library("MemcacheLibrary");
- if (! $cached = $this->memcachelibrary->get($filedata['hash'].'_'.$mode)) {
- ob_start();
- if ($mode == "rmd") {
- echo '<td class="markdownrender">'."\n";
- passthru('perl '.FCPATH.'scripts/Markdown.pl '.escapeshellarg($file));
- } elseif ($mode == "ascii") {
- echo '<td class="code"><pre class="text">'."\n";
- passthru('perl '.FCPATH.'scripts/ansi2html '.escapeshellarg($file));
- echo "</pre>\n";
- } else {
- echo '<td class="numbers"><pre>';
- // generate line numbers (links)
- passthru('perl -ne \'print "<a href=\"#n$.\" class=\"no\" id=\"n$.\">$.</a>\n"\' '.escapeshellarg($file));
- echo '</pre></td><td class="code">'."\n";
- $this->load->library('geshi');
- $this->geshi->initialize(array('set_language' => $mode, 'set_source' => file_get_contents($file), 'enable_classes' => 'true'));
- echo $this->geshi->parse_code();
- }
- $cached = ob_get_contents();
- ob_end_clean();
- $this->memcachelibrary->set($filedata['hash'].'_'.$mode, $cached, 100);
- }
- echo $cached;
-
- echo $this->load->view($this->var->view_dir.'/html_footer', $this->data, true);
-
- exit();
- }
-
function get_timeout_string($id)
{
$filedata = $this->get_filedata($id);
@@ -356,22 +165,6 @@ class File_mod extends CI_Model {
}
}
- function display_info($id)
- {
- $this->data["title"] .= " - Info $id";
- $this->data["filedata"] = $this->get_filedata($id);
- $this->data["id"] = $id;
- $this->data['timeout'] = $this->get_timeout_string($id);
-
- if (!isset($this->data["can_delete"])) {
- $this->data["can_delete"] = false;
- }
-
- $this->load->view($this->var->view_dir.'/header', $this->data);
- $this->load->view($this->var->view_dir.'/file_info', $this->data);
- $this->load->view($this->var->view_dir.'/footer', $this->data);
- }
-
function delete_id($id)
{
$this->muser->require_access();
@@ -401,6 +194,13 @@ class File_mod extends CI_Model {
return true;
}
+ function should_highlight($type)
+ {
+ if ($this->mime2mode($type)) return true;
+
+ return false;
+ }
+
// Allow certain types to be highlight without doing it automatically
function can_highlight($type)
{