diff options
Diffstat (limited to 'application/controllers/file.php')
-rw-r--r-- | application/controllers/file.php | 186 |
1 files changed, 181 insertions, 5 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 |