diff options
-rw-r--r-- | system/application/controllers/file.php | 372 | ||||
-rw-r--r-- | system/application/helpers/filebin_helper.php | 7 | ||||
-rw-r--r-- | system/application/libraries/MemcacheLibrary.php | 321 | ||||
-rw-r--r-- | system/application/models/file_mod.php | 734 |
4 files changed, 714 insertions, 720 deletions
diff --git a/system/application/controllers/file.php b/system/application/controllers/file.php index 7d0943bdd..0ed66b511 100644 --- a/system/application/controllers/file.php +++ b/system/application/controllers/file.php @@ -9,192 +9,190 @@ class File extends Controller { - function __construct() - { - parent::Controller(); - $this->load->helper(array('form', 'filebin')); - $this->load->model('file_mod'); - $this->var->cli_client = false; - $this->file_mod->var->cli_client =& $this->var->cli_client; - $this->var->latest_client = trim(file_get_contents(FCPATH.'data/client/latest')); - - // official client uses "fb-client/$version" as useragent - if (strpos($_SERVER['HTTP_USER_AGENT'], 'fb-client') !== false) { - $client_version = substr($_SERVER['HTTP_USER_AGENT'], 10); - if ($this->var->latest_client != $client_version) { - echo "Your are using an old client version. Latest is ".$this->var->latest_client."\n"; - } - $this->var->cli_client = "fb-client"; - } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'libcurl') !== false) { - $this->var->cli_client = "curl"; - } - } - - function index() - { - // Try to guess what the user would like to do. - // File uploads should be checked first because they are usually big and - // take quite some time to upload. - if(isset($_FILES['file'])) { - $this->do_upload(); - } elseif ($this->input->post('content')) { - $this->do_paste(); - } elseif ($this->file_mod->id_exists($this->uri->segment(1))) { - $this->file_mod->download(); - } elseif ($this->var->cli_client) { - die("No upload or unknown ID requested.\n"); - } else { - $this->upload_form(); - } - } - - function client() - { - $data['title'] = 'Client'; - $data['client_link'] = base_url().'data/client/fb-'.$this->var->latest_client.'.tar.gz'; - $data['client_link_dir'] = base_url().'data/client/'; - $data['client_link_deb'] = base_url().'data/client/deb/'; - $data['client_link_slackware'] = base_url().'data/client/slackware/'; - - $this->load->view('file/header', $data); - $this->load->view('file/client', $data); - $this->load->view('file/footer', $data); - } - - function upload_form() - { - $data = array(); - $data['title'] = 'Upload'; - $data['small_upload_size'] = $this->config->item('small_upload_size'); - $data['max_upload_size'] = $this->config->item('upload_max_size'); - - $this->load->view('file/header', $data); - $this->load->view('file/upload_form', $data); - $this->load->view('file/footer', $data); - } - - // Allow CLI clients to query the server for the maxium filesize so they can - // stop the upload before wasting time and bandwith - function get_max_size() - { - echo $this->config->item('upload_max_size'); - } - - // Allow users to delete IDs if their password matches the one used when uploading - function delete() - { - $id = $this->uri->segment(3); - $password = $this->input->post('password'); - if ($this->file_mod->delete_id($id, $password)) { - echo $id." deleted\n"; - } else { - echo 'Couldn\'t delete '.$id."\n"; - } - die(); - } - - // Take the content from post instead of a file - // support textareas on the upload form - // XXX: This requires users of suhosin to adjust maxium post and request size - // TODO: merge with do_upload() - function do_paste() - { - $data = array(); - $content = $this->input->post('content')."\n"; - $extension = $this->input->post('extension'); - // prevent empty pastes from the upload form - if($content === "\n") { - $this->upload_form(); - return; - } - // TODO: Display nice error for cli clients - if(strlen($content) > $this->config->item('upload_max_size')) { - $this->load->view('file/header', $data); - $this->load->view('file/too_big'); - $this->load->view('file/footer'); - return; - } - - $id = $this->file_mod->new_id(); - $hash = md5($content); - $folder = $this->file_mod->folder($hash); - file_exists($folder) || mkdir ($folder); - $file = $this->file_mod->file($hash); - - file_put_contents($file, $content); - chmod($file, 0600); - $this->file_mod->add_file($hash, $id, 'stdin'); - $this->file_mod->show_url($id, $extension); - } - - // Handles uploaded files - // TODO: merge with do_paste() - function do_upload() - { - $data = array(); - $extension = $this->input->post('extension'); - // TODO: Display nice error for cli clients - if(!isset($_FILES['file'])) { - $this->load->view('file/header', $data); - $this->load->view('file/upload_error'); - $this->load->view('file/footer'); - return; - } - if ($_FILES['file']['error'] !== 0) { - $this->upload_form(); - return; - } - $filesize = filesize($_FILES['file']['tmp_name']); - // TODO: Display nice error for cli clients - if ($filesize > $this->config->item('upload_max_size')) { - $this->load->view('file/header', $data); - $this->load->view('file/too_big'); - $this->load->view('file/footer'); - return; - } - - $id = $this->file_mod->new_id(); - $hash = md5_file($_FILES['file']['tmp_name']); - $filename = $_FILES['file']['name']; - $folder = $this->file_mod->folder($hash); - file_exists($folder) || mkdir ($folder); - $file = $this->file_mod->file($hash); - - 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); - } - - // Removes old files - function cron() - { - if ($this->config->item('upload_max_age') == 0) return; - - $oldest_time = (time()-$this->config->item('upload_max_age')); - $small_upload_size = $this->config->item('small_upload_size'); - $query = $this->db->query('SELECT hash, id FROM files WHERE date < ?', - array($oldest_time)); - - foreach($query->result_array() as $row) { - $file = $this->file_mod->file($row['hash']); - if (!file_exists($file)) { - $this->db->query('DELETE FROM files WHERE id = ? LIMIT 1', array($row['id'])); - continue; - } - - if (filesize($file) > $small_upload_size) { - if (filemtime($file) < $oldest_time) { - unlink($file); - $this->db->query('DELETE FROM files WHERE hash = ?', array($row['hash'])); - } else { - $this->db->query('DELETE FROM files WHERE id = ? LIMIT 1', array($row['id'])); - } - } - } - } + function __construct() + { + parent::Controller(); + $this->load->helper(array('form', 'filebin')); + $this->load->model('file_mod'); + $this->var->cli_client = false; + $this->file_mod->var->cli_client =& $this->var->cli_client; + $this->var->latest_client = trim(file_get_contents(FCPATH.'data/client/latest')); + + // official client uses "fb-client/$version" as useragent + if (strpos($_SERVER['HTTP_USER_AGENT'], 'fb-client') !== false) { + $client_version = substr($_SERVER['HTTP_USER_AGENT'], 10); + if ($this->var->latest_client != $client_version) { + echo "Your are using an old client version. Latest is ".$this->var->latest_client."\n"; + } + $this->var->cli_client = "fb-client"; + } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'libcurl') !== false) { + $this->var->cli_client = "curl"; + } + } + + function index() + { + // Try to guess what the user would like to do. + // File uploads should be checked first because they are usually big and + // take quite some time to upload. + if(isset($_FILES['file'])) { + $this->do_upload(); + } elseif ($this->input->post('content')) { + $this->do_paste(); + } elseif ($this->file_mod->id_exists($this->uri->segment(1))) { + $this->file_mod->download(); + } elseif ($this->var->cli_client) { + die("No upload or unknown ID requested.\n"); + } else { + $this->upload_form(); + } + } + + function client() + { + $data['title'] = 'Client'; + $data['client_link'] = base_url().'data/client/fb-'.$this->var->latest_client.'.tar.gz'; + $data['client_link_dir'] = base_url().'data/client/'; + $data['client_link_deb'] = base_url().'data/client/deb/'; + $data['client_link_slackware'] = base_url().'data/client/slackware/'; + + $this->load->view('file/header', $data); + $this->load->view('file/client', $data); + $this->load->view('file/footer', $data); + } + + function upload_form() + { + $data = array(); + $data['title'] = 'Upload'; + $data['small_upload_size'] = $this->config->item('small_upload_size'); + $data['max_upload_size'] = $this->config->item('upload_max_size'); + + $this->load->view('file/header', $data); + $this->load->view('file/upload_form', $data); + $this->load->view('file/footer', $data); + } + + // Allow CLI clients to query the server for the maxium filesize so they can + // stop the upload before wasting time and bandwith + function get_max_size() + { + echo $this->config->item('upload_max_size'); + } + + // Allow users to delete IDs if their password matches the one used when uploading + function delete() + { + $id = $this->uri->segment(3); + $password = $this->input->post('password'); + if ($this->file_mod->delete_id($id, $password)) { + echo $id." deleted\n"; + } else { + echo 'Couldn\'t delete '.$id."\n"; + } + die(); + } + + // Take the content from post instead of a file + // support textareas on the upload form + // XXX: This requires users of suhosin to adjust maxium post and request size + // TODO: merge with do_upload() + function do_paste() + { + $data = array(); + $content = $this->input->post('content')."\n"; + $extension = $this->input->post('extension'); + // prevent empty pastes from the upload form + if($content === "\n") { + $this->upload_form(); + return; + } + // TODO: Display nice error for cli clients + if(strlen($content) > $this->config->item('upload_max_size')) { + $this->load->view('file/header', $data); + $this->load->view('file/too_big'); + $this->load->view('file/footer'); + return; + } + + $id = $this->file_mod->new_id(); + $hash = md5($content); + $folder = $this->file_mod->folder($hash); + file_exists($folder) || mkdir ($folder); + $file = $this->file_mod->file($hash); + + file_put_contents($file, $content); + chmod($file, 0600); + $this->file_mod->add_file($hash, $id, 'stdin'); + $this->file_mod->show_url($id, $extension); + } + + // Handles uploaded files + // TODO: merge with do_paste() + function do_upload() + { + $data = array(); + $extension = $this->input->post('extension'); + // TODO: Display nice error for cli clients + if(!isset($_FILES['file'])) { + $this->load->view('file/header', $data); + $this->load->view('file/upload_error'); + $this->load->view('file/footer'); + return; + } + if ($_FILES['file']['error'] !== 0) { + $this->upload_form(); + return; + } + $filesize = filesize($_FILES['file']['tmp_name']); + // TODO: Display nice error for cli clients + if ($filesize > $this->config->item('upload_max_size')) { + $this->load->view('file/header', $data); + $this->load->view('file/too_big'); + $this->load->view('file/footer'); + return; + } + + $id = $this->file_mod->new_id(); + $hash = md5_file($_FILES['file']['tmp_name']); + $filename = $_FILES['file']['name']; + $folder = $this->file_mod->folder($hash); + file_exists($folder) || mkdir ($folder); + $file = $this->file_mod->file($hash); + + 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); + } + + // Removes old files + function cron() + { + if ($this->config->item('upload_max_age') == 0) return; + + $oldest_time = (time()-$this->config->item('upload_max_age')); + $small_upload_size = $this->config->item('small_upload_size'); + $query = $this->db->query('SELECT hash, id FROM files WHERE date < ?', + array($oldest_time)); + + foreach($query->result_array() as $row) { + $file = $this->file_mod->file($row['hash']); + if (!file_exists($file)) { + $this->db->query('DELETE FROM files WHERE id = ? LIMIT 1', array($row['id'])); + continue; + } + + if (filesize($file) > $small_upload_size) { + if (filemtime($file) < $oldest_time) { + unlink($file); + $this->db->query('DELETE FROM files WHERE hash = ?', array($row['hash'])); + } else { + $this->db->query('DELETE FROM files WHERE id = ? LIMIT 1', array($row['id'])); + } + } + } + } } -# vim: set ts=2 sw=2 et: -/* End of file file.php */ -/* Location: ./system/application/controllers/file.php */ +# vim: set noet: diff --git a/system/application/helpers/filebin_helper.php b/system/application/helpers/filebin_helper.php index 34b231023..3d6c30b76 100644 --- a/system/application/helpers/filebin_helper.php +++ b/system/application/helpers/filebin_helper.php @@ -2,8 +2,9 @@ // Source: http://ibnuyahya.com/format-bytes-to-kb-mb-gb/ function format_bytes($size, $precision = 2){ - $base = log($size) / log(1024); - $suffixes = array('B', 'kB', 'MB', 'GB', 'TB' , 'PB' , 'EB'); - return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; + $base = log($size) / log(1024); + $suffixes = array('B', 'kB', 'MB', 'GB', 'TB' , 'PB' , 'EB'); + return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; } +# vim: set noet: diff --git a/system/application/libraries/MemcacheLibrary.php b/system/application/libraries/MemcacheLibrary.php index 367c85078..dcc08b942 100644 --- a/system/application/libraries/MemcacheLibrary.php +++ b/system/application/libraries/MemcacheLibrary.php @@ -16,167 +16,164 @@ class MemcacheLibrary { - /** - * variable that holds memcached backend instance - * - * @var object - * @access public - */ - public $memcachedInstance; - - /** - * variable that holds servers for the memcache - * - * @var array - * @access public - */ - public $servers = array(); - - - /** - * main CodeIgniter instance - * - * @var object - * @access public - */ - public $CI; - - /** - * constructor function for the library - */ - public function __construct() { - - /* initialize memcached instance */ - if(class_exists("Memcache")) { - $this->memcachedInstance = new Memcache(); - } else { - throw new Exception( - "Memcached client doesn't exists in your PHP configuration" - ); - } - - /* load super CI instance */ - $this->CI =& get_instance(); - - /* load default server info */ - $this->CI->config->load("memcache"); - - /* connect to default server */ - if($this->CI->config->item("MEMCACHE_HOST") && $this->CI->config->item("MEMCACHE_PORT") !== false) { - $this->addServer($this->CI->config->item("MEMCACHE_HOST"), $this->CI->config->item("MEMCACHE_PORT")); - } - - } - - /** - * adder function for the memcache servers - * - * @access public - * @return void - */ - public function addServer($server, $port) { - $this->servers[] = array( - "server" => $server, - "port" => $port, - ); - - $this->memcachedInstance->addServer($server, $port); - } - - /** - * gets related key from the memcache - * - * @access public - */ - public function get($key) { - $this->logDebugMessage(sprintf("%s key requested from memcache", $key)); - return $this->memcachedInstance->get($key); - } - - /** - * sets related key to the memcache - * - * @access public - */ - public function set($key, $value, $expire = null) { - $this->logDebugMessage( - sprintf("%s key set to memcache. (expire: %s)",$key, $expire) - ); - return $this->memcachedInstance->set($key, $value, null, $expire); - } - - /** - * deletes related key from the memcache - * - * @access public - */ - public function delete($key) { - $this->logDebugMessage(sprintf("%s key deleted from memcache.", $key)); - return $this->memcachedInstance->delete($key); - } - - /** - * increments related key from the memcache - * - * @access public - */ - public function increment($key, $offset = 1) { - $this->logDebugMessage(sprintf("%s key incremented %s times", $key, $offset)); - return $this->memcachedInstance->increment($key, $offset); - } - - /** - * decrements related key from the memcache - * - * @access public - */ - public function decrement($key, $offset = 1) { - $this->logDebugMessage(sprintf("%s key decremented %s times", $key, $offset)); - return $this->memcachedInstance->decrement($key, $offset); - } - - /** - * gets running memcached servers. - * - * @access public - * @return array - */ - public function getRunningServers() { - return $this->servers; - } - - /** - * array of server statistics, one entry per server. - * - * @access public - * @return array - */ - public function getStatistics() { - return $this->memcachedInstance->getStats(); - } - - /** - * Invalidates all items from the memcache. - * - * @access public - * @return boolean - */ - public function flush($delay = 0) { - $this->logDebugMessage(sprintf("memcache flushed! (delay: %s)", $delay)); - return $this->memcachedInstance->flush($delay); - } - - /** - * logs the memcache actions to the codeigniter's main logging system. - * - * @access private - */ - private function logDebugMessage($message) { - log_message("debug", $message); - } + /** + * variable that holds memcached backend instance + * + * @var object + * @access public + */ + public $memcachedInstance; + + /** + * variable that holds servers for the memcache + * + * @var array + * @access public + */ + public $servers = array(); + + + /** + * main CodeIgniter instance + * + * @var object + * @access public + */ + public $CI; + + /** + * constructor function for the library + */ + public function __construct() { + + /* initialize memcached instance */ + if(class_exists("Memcache")) { + $this->memcachedInstance = new Memcache(); + } else { + throw new Exception( + "Memcached client doesn't exists in your PHP configuration" + ); + } + + /* load super CI instance */ + $this->CI =& get_instance(); + + /* load default server info */ + $this->CI->config->load("memcache"); + + /* connect to default server */ + if($this->CI->config->item("MEMCACHE_HOST") && $this->CI->config->item("MEMCACHE_PORT") !== false) { + $this->addServer($this->CI->config->item("MEMCACHE_HOST"), $this->CI->config->item("MEMCACHE_PORT")); + } + + } + + /** + * adder function for the memcache servers + * + * @access public + * @return void + */ + public function addServer($server, $port) { + $this->servers[] = array( + "server" => $server, + "port" => $port, + ); + + $this->memcachedInstance->addServer($server, $port); + } + + /** + * gets related key from the memcache + * + * @access public + */ + public function get($key) { + $this->logDebugMessage(sprintf("%s key requested from memcache", $key)); + return $this->memcachedInstance->get($key); + } + + /** + * sets related key to the memcache + * + * @access public + */ + public function set($key, $value, $expire = null) { + $this->logDebugMessage( + sprintf("%s key set to memcache. (expire: %s)",$key, $expire) + ); + return $this->memcachedInstance->set($key, $value, null, $expire); + } + + /** + * deletes related key from the memcache + * + * @access public + */ + public function delete($key) { + $this->logDebugMessage(sprintf("%s key deleted from memcache.", $key)); + return $this->memcachedInstance->delete($key); + } + + /** + * increments related key from the memcache + * + * @access public + */ + public function increment($key, $offset = 1) { + $this->logDebugMessage(sprintf("%s key incremented %s times", $key, $offset)); + return $this->memcachedInstance->increment($key, $offset); + } + + /** + * decrements related key from the memcache + * + * @access public + */ + public function decrement($key, $offset = 1) { + $this->logDebugMessage(sprintf("%s key decremented %s times", $key, $offset)); + return $this->memcachedInstance->decrement($key, $offset); + } + + /** + * gets running memcached servers. + * + * @access public + * @return array + */ + public function getRunningServers() { + return $this->servers; + } + + /** + * array of server statistics, one entry per server. + * + * @access public + * @return array + */ + public function getStatistics() { + return $this->memcachedInstance->getStats(); + } + + /** + * Invalidates all items from the memcache. + * + * @access public + * @return boolean + */ + public function flush($delay = 0) { + $this->logDebugMessage(sprintf("memcache flushed! (delay: %s)", $delay)); + return $this->memcachedInstance->flush($delay); + } + + /** + * logs the memcache actions to the codeigniter's main logging system. + * + * @access private + */ + private function logDebugMessage($message) { + log_message("debug", $message); + } } - - - -?> +# vim: set noet: diff --git a/system/application/models/file_mod.php b/system/application/models/file_mod.php index 0ae64410d..20ebe58f4 100644 --- a/system/application/models/file_mod.php +++ b/system/application/models/file_mod.php @@ -9,374 +9,372 @@ class File_mod extends Model { - function __construct() - { - parent::Model(); - } - - // Returns an unused ID - // TODO: make threadsafe - function new_id() - { - $id = $this->random_id(3,6); - - if ($this->id_exists($id) || $id == 'file') { - return $this->new_id(); - } else { - return $id; - } - } - - function id_exists($id) - { - if(!$id) { - return false; - } - - $sql = ' - SELECT id - FROM `files` - WHERE `id` = ? - LIMIT 1'; - $query = $this->db->query($sql, array($id)); - - if ($query->num_rows() == 1) { - return true; - } else { - return false; - } - } - - function get_filedata($id) - { - $sql = ' - SELECT hash,filename,mimetype - 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]; - } 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); - } - - // Returns the full path to the file with $hash - function file($hash) { - return $this->folder($hash).'/'.$hash; - } - - function hash_password($password) - { - return sha1($this->config->item('passwordsalt').$password); - } - - // Returns the password submitted by the user - function get_password() - { - $password = $this->input->post('password'); - if ($password !== false) { - return $this->hash_password($password); - } elseif (isset($_SERVER['PHP_AUTH_PW']) && $_SERVER['PHP_AUTH_PW'] != '') { - return $this->hash_password($_SERVER['PHP_AUTH_PW']); - } - return 'NULL'; - } - - // Add a hash to the DB - // TODO: Should only update not insert; see new_id() - function add_file($hash, $id, $filename) - { - $mimetype = exec(FCPATH.'scripts/mimetype -b --orig-name '.escapeshellarg($filename).' '.escapeshellarg($this->file($hash))); - $query = $this->db->query(' - INSERT INTO `files` (`hash`, `id`, `filename`, `password`, `date`, `mimetype`) - VALUES (?, ?, ?, ?, ?, ?)', - array($hash, $id, $filename, $this->get_password(), time(), $mimetype)); - } - - function show_url($id, $mode) - { - $data = array(); - $redirect = false; - - if ($mode) { - $data['url'] = site_url($id).'/'.$mode; - } else { - $data['url'] = site_url($id).'/'; - - $filedata = $this->get_filedata($id); - $file = $this->file($filedata['hash']); - $type = $filedata['mimetype'] ? $filedata['mimetype'] : exec(FCPATH.'scripts/mimetype -b --orig-name '.escapeshellarg($filedata['filename']).' '.escapeshellarg($file)); - $mode = $this->mime2extension($type); - $mode = $this->filename2extension($filedata['filename']) ? $this->filename2extension($filedata['filename']) : $mode; - - // If we detected a highlightable file redirect, - // otherwise show the URL because browsers would just show a DL dialog - if ($mode) { - $redirect = true; - } - } - - if ($this->var->cli_client) { - echo $data['url']."\n"; - } else { - if ($redirect) { - redirect($data['url']); - } else { - $this->load->view('file/header', $data); - $this->load->view('file/show_url', $data); - $this->load->view('file/footer', $data); - } - } - } - - // download a given ID - // TODO: make smaller - function download() - { - $data = array(); - $id = $this->uri->segment(1); - $mode = $this->uri->segment(2); - - $filedata = $this->get_filedata($id); - $file = $this->file($filedata['hash']); - - if ($this->id_exists($id) && file_exists($file)) { - // MODIFIED SINCE SUPPORT -- START - // helps to keep traffic low when reloading an image - $filedate = filectime($file); - $etag = strtolower(md5_file($file)); - $modified = true; - - // No need to check because different files have different IDs/hashes - if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { - $modified = false; - } - - if(isset($_SERVER['HTTP_IF_NONE_MATCH'])) { - $oldtag = trim(strtolower($_SERVER['HTTP_IF_NONE_MATCH']), '"'); - if($oldtag == $etag) { - $modified = false; - } else { - $modified = true; - } - } - // MODIFIED SINCE SUPPORT -- END - - if (!$modified) { - header("HTTP/1.1 304 Not Modified"); - header('Etag: "'.$etag.'"'); - } else { - $type = $filedata['mimetype'] ? $filedata['mimetype'] : exec(FCPATH.'scripts/mimetype -b --orig-name '.escapeshellarg($filedata['filename']).' '.escapeshellarg($file)); - - // /$mode at the end of the URL overwrites autodetection - if (!$mode && substr_count(ltrim($this->uri->uri_string(), "/"), '/') >= 1) { - $mode = $this->mime2extension($type); - $mode = $this->filename2extension($filedata['filename']) ? $this->filename2extension($filedata['filename']) : $mode; - } - - // TODO: cleanup conditions - if ($mode && $mode != 'plain' && $mode != 'qr' - && $this->mime2extension($type) - && filesize($file) <= $this->config->item('upload_max_text_size') - ) { - $data['title'] = $filedata['filename']; - $data['raw_link'] = site_url($id); - $data['new_link'] = site_url(); - $data['plain_link'] = site_url($id.'/plain'); - $data['auto_link'] = site_url($id).'/'; - $data['rmd_link'] = site_url($id.'/rmd'); - - header("Content-Type: text/html\n"); - if ($mode) { - $data['current_highlight'] = $mode; - } else { - $data['current_highlight'] = $this->mime2extension($type); - } - echo $this->load->view('file/html_header', $data, true); - $this->load->library("MemcacheLibrary"); - if (! $cached = $this->memcachelibrary->get($filedata['hash'].'_'.$mode)) { - ob_start(); - if ($mode == "rmd") { - echo '<td class="markdownrender">'."\n"; - passthru('/usr/bin/perl /usr/bin/perlbin/vendor/Markdown.pl '.escapeshellarg($file)); - } else { - echo '<td class="numbers"><pre>'; - // generate line numbers (links) - passthru('/usr/bin/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->output(); - } - $cached = ob_get_contents(); - ob_end_clean(); - $this->memcachelibrary->set($filedata['hash'].'_'.$mode, $cached, 100); - } - echo $cached; - echo $this->load->view('file/html_footer', $data, true); - } else { - if ($mode == 'plain') { - header("Content-Type: text/plain\n"); - } elseif ($mode == "qr") { - header("Content-disposition: inline; filename=\"".$id."_qr.png\"\n"); - header("Content-Type: image/png\n"); - passthru('/usr/bin/qrencode -s 10 -o - '.escapeshellarg(site_url($id).'/')); - exit(); - } else { - header("Content-Type: ".$type."\n"); - } - header("Content-disposition: inline; filename=\"".$filedata['filename']."\"\n"); - header("Content-Length: ".filesize($file)."\n"); - header("Last-Modified: ".date('D, d M Y H:i:s', $filedate)." GMT"); - header('Etag: "'.$etag.'"'); - $fp = fopen($file,"r"); - while (!feof($fp)) { - echo fread($fp,4096); - } - fclose($fp); - } - } - exit(); - } else { - // TODO: remove -controller function has been removed - $this->load->view('file/header'); - $this->load->view('file/non_existant'); - $this->load->view('file/footer'); - } - } - - private function unused_file($hash) - { - $sql = ' - SELECT id - FROM `files` - WHERE `hash` = ? - LIMIT 1'; - $query = $this->db->query($sql, array($hash)); - - if ($query->num_rows() == 0) { - return true; - } else { - return false; - } - } - - function delete_id($id, $password) - { - $filedata = $this->get_filedata($id); - $password = $this->get_password(); - - if ($password == "NULL") { - return false; - } - - if(!$this->id_exists($id)) { - return false; - } - - $sql = ' - DELETE - FROM `files` - WHERE `id` = ? - AND password = ? - LIMIT 1'; - $this->db->query($sql, array($id, $password)); - - if($this->id_exists($id)) { - return false; - } - - if($this->unused_file($filedata['hash'])) { - unlink($this->file($filedata['hash'])); - @rmdir($this->folder($filedata['hash'])); - } - return true; - } - - // Generate a random ID - private function random_id($min_length, $max_length) - { - $random = ''; - $char_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - $char_list .= "abcdefghijklmnopqrstuvwxyz"; - $char_list .= "1234567890"; - $length = rand()%($max_length-$min_length) + $min_length; - - for($i = 0; $i < $max_length; $i++) { - if (strlen($random) == $length) break; - $random .= substr($char_list,(rand()%(strlen($char_list))), 1); - } - return $random; - } - - // Map MIME types to extensions needed for highlighting - function mime2extension($type) - { - $typearray = array( - 'text/plain' => 'text', - 'text/x-python' => 'python', - 'text/x-csrc' => 'c', - 'text/x-chdr' => 'c', - 'text/x-c++hdr' => 'c', - 'text/x-c++src' => 'cpp', - 'text/x-patch' => 'diff', - 'text/x-lua' => 'lua', - 'text/x-java' => 'java', - 'text/x-haskell' => 'haskell', - 'text/x-literate-haskell' => 'haskell', - 'text/x-subviewer' => 'bash', - 'text/x-makefile' => 'make', - #'text/x-log' => 'log', - 'text/html' => 'html', - 'text/css' => 'css', - 'message/rfc822' => 'email', - #'image/svg+xml' => 'xml', - 'application/x-perl' => 'perl', - 'application/xml' => 'xml', - 'application/javascript' => 'javascript', - 'application/x-desktop' => 'text', - 'application/x-m4' => 'text', - 'application/x-awk' => 'text', - 'application/x-java' => 'java', - 'application/x-php' => 'php', - 'application/x-ruby' => 'ruby', - 'application/x-shellscript' => 'bash', - 'application/x-x509-ca-cert' => 'text', - 'application/mbox' => 'email', - 'application/x-genesis-rom' => 'text', - 'application/x-applix-spreadsheet' => 'actionscript' - ); - if (array_key_exists($type, $typearray)) return $typearray[$type]; - - if (strpos($type, 'text/') === 0) return 'text'; - - # default - return false; - } - - // Map special filenames to extensions - function filename2extension($name) - { - $namearray = array( - 'PKGBUILD' => 'bash', - '.vimrc' => 'vim' - ); - if (array_key_exists($name, $namearray)) return $namearray[$name]; - - return false; - } + function __construct() + { + parent::Model(); + } + + // Returns an unused ID + // TODO: make threadsafe + function new_id() + { + $id = $this->random_id(3,6); + + if ($this->id_exists($id) || $id == 'file') { + return $this->new_id(); + } else { + return $id; + } + } + + function id_exists($id) + { + if(!$id) { + return false; + } + + $sql = ' + SELECT id + FROM `files` + WHERE `id` = ? + LIMIT 1'; + $query = $this->db->query($sql, array($id)); + + if ($query->num_rows() == 1) { + return true; + } else { + return false; + } + } + + function get_filedata($id) + { + $sql = ' + SELECT hash,filename,mimetype + 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]; + } 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); + } + + // Returns the full path to the file with $hash + function file($hash) { + return $this->folder($hash).'/'.$hash; + } + + function hash_password($password) + { + return sha1($this->config->item('passwordsalt').$password); + } + + // Returns the password submitted by the user + function get_password() + { + $password = $this->input->post('password'); + if ($password !== false) { + return $this->hash_password($password); + } elseif (isset($_SERVER['PHP_AUTH_PW']) && $_SERVER['PHP_AUTH_PW'] != '') { + return $this->hash_password($_SERVER['PHP_AUTH_PW']); + } + return 'NULL'; + } + + // Add a hash to the DB + // TODO: Should only update not insert; see new_id() + function add_file($hash, $id, $filename) + { + $mimetype = exec(FCPATH.'scripts/mimetype -b --orig-name '.escapeshellarg($filename).' '.escapeshellarg($this->file($hash))); + $query = $this->db->query(' + INSERT INTO `files` (`hash`, `id`, `filename`, `password`, `date`, `mimetype`) + VALUES (?, ?, ?, ?, ?, ?)', + array($hash, $id, $filename, $this->get_password(), time(), $mimetype)); + } + + function show_url($id, $mode) + { + $data = array(); + $redirect = false; + + if ($mode) { + $data['url'] = site_url($id).'/'.$mode; + } else { + $data['url'] = site_url($id).'/'; + + $filedata = $this->get_filedata($id); + $file = $this->file($filedata['hash']); + $type = $filedata['mimetype'] ? $filedata['mimetype'] : exec(FCPATH.'scripts/mimetype -b --orig-name '.escapeshellarg($filedata['filename']).' '.escapeshellarg($file)); + $mode = $this->mime2extension($type); + $mode = $this->filename2extension($filedata['filename']) ? $this->filename2extension($filedata['filename']) : $mode; + + // If we detected a highlightable file redirect, + // otherwise show the URL because browsers would just show a DL dialog + if ($mode) { + $redirect = true; + } + } + + if ($this->var->cli_client) { + echo $data['url']."\n"; + } else { + if ($redirect) { + redirect($data['url']); + } else { + $this->load->view('file/header', $data); + $this->load->view('file/show_url', $data); + $this->load->view('file/footer', $data); + } + } + } + + // download a given ID + // TODO: make smaller + function download() + { + $data = array(); + $id = $this->uri->segment(1); + $mode = $this->uri->segment(2); + + $filedata = $this->get_filedata($id); + $file = $this->file($filedata['hash']); + + if ($this->id_exists($id) && file_exists($file)) { + // MODIFIED SINCE SUPPORT -- START + // helps to keep traffic low when reloading an image + $filedate = filectime($file); + $etag = strtolower(md5_file($file)); + $modified = true; + + // No need to check because different files have different IDs/hashes + if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { + $modified = false; + } + + if(isset($_SERVER['HTTP_IF_NONE_MATCH'])) { + $oldtag = trim(strtolower($_SERVER['HTTP_IF_NONE_MATCH']), '"'); + if($oldtag == $etag) { + $modified = false; + } else { + $modified = true; + } + } + // MODIFIED SINCE SUPPORT -- END + + if (!$modified) { + header("HTTP/1.1 304 Not Modified"); + header('Etag: "'.$etag.'"'); + } else { + $type = $filedata['mimetype'] ? $filedata['mimetype'] : exec(FCPATH.'scripts/mimetype -b --orig-name '.escapeshellarg($filedata['filename']).' '.escapeshellarg($file)); + + // /$mode at the end of the URL overwrites autodetection + if (!$mode && substr_count(ltrim($this->uri->uri_string(), "/"), '/') >= 1) { + $mode = $this->mime2extension($type); + $mode = $this->filename2extension($filedata['filename']) ? $this->filename2extension($filedata['filename']) : $mode; + } + + // TODO: cleanup conditions + if ($mode && $mode != 'plain' && $mode != 'qr' + && $this->mime2extension($type) + && filesize($file) <= $this->config->item('upload_max_text_size') + ) { + $data['title'] = $filedata['filename']; + $data['raw_link'] = site_url($id); + $data['new_link'] = site_url(); + $data['plain_link'] = site_url($id.'/plain'); + $data['auto_link'] = site_url($id).'/'; + $data['rmd_link'] = site_url($id.'/rmd'); + + header("Content-Type: text/html\n"); + if ($mode) { + $data['current_highlight'] = $mode; + } else { + $data['current_highlight'] = $this->mime2extension($type); + } + echo $this->load->view('file/html_header', $data, true); + $this->load->library("MemcacheLibrary"); + if (! $cached = $this->memcachelibrary->get($filedata['hash'].'_'.$mode)) { + ob_start(); + if ($mode == "rmd") { + echo '<td class="markdownrender">'."\n"; + passthru('/usr/bin/perl /usr/bin/perlbin/vendor/Markdown.pl '.escapeshellarg($file)); + } else { + echo '<td class="numbers"><pre>'; + // generate line numbers (links) + passthru('/usr/bin/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->output(); + } + $cached = ob_get_contents(); + ob_end_clean(); + $this->memcachelibrary->set($filedata['hash'].'_'.$mode, $cached, 100); + } + echo $cached; + echo $this->load->view('file/html_footer', $data, true); + } else { + if ($mode == 'plain') { + header("Content-Type: text/plain\n"); + } elseif ($mode == "qr") { + header("Content-disposition: inline; filename=\"".$id."_qr.png\"\n"); + header("Content-Type: image/png\n"); + passthru('/usr/bin/qrencode -s 10 -o - '.escapeshellarg(site_url($id).'/')); + exit(); + } else { + header("Content-Type: ".$type."\n"); + } + header("Content-disposition: inline; filename=\"".$filedata['filename']."\"\n"); + header("Content-Length: ".filesize($file)."\n"); + header("Last-Modified: ".date('D, d M Y H:i:s', $filedate)." GMT"); + header('Etag: "'.$etag.'"'); + $fp = fopen($file,"r"); + while (!feof($fp)) { + echo fread($fp,4096); + } + fclose($fp); + } + } + exit(); + } else { + // TODO: remove -controller function has been removed + $this->load->view('file/header'); + $this->load->view('file/non_existant'); + $this->load->view('file/footer'); + } + } + + private function unused_file($hash) + { + $sql = ' + SELECT id + FROM `files` + WHERE `hash` = ? + LIMIT 1'; + $query = $this->db->query($sql, array($hash)); + + if ($query->num_rows() == 0) { + return true; + } else { + return false; + } + } + + function delete_id($id, $password) + { + $filedata = $this->get_filedata($id); + $password = $this->get_password(); + + if ($password == "NULL") { + return false; + } + + if(!$this->id_exists($id)) { + return false; + } + + $sql = ' + DELETE + FROM `files` + WHERE `id` = ? + AND password = ? + LIMIT 1'; + $this->db->query($sql, array($id, $password)); + + if($this->id_exists($id)) { + return false; + } + + if($this->unused_file($filedata['hash'])) { + unlink($this->file($filedata['hash'])); + @rmdir($this->folder($filedata['hash'])); + } + return true; + } + + // Generate a random ID + private function random_id($min_length, $max_length) + { + $random = ''; + $char_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $char_list .= "abcdefghijklmnopqrstuvwxyz"; + $char_list .= "1234567890"; + $length = rand()%($max_length-$min_length) + $min_length; + + for($i = 0; $i < $max_length; $i++) { + if (strlen($random) == $length) break; + $random .= substr($char_list,(rand()%(strlen($char_list))), 1); + } + return $random; + } + + // Map MIME types to extensions needed for highlighting + function mime2extension($type) + { + $typearray = array( + 'text/plain' => 'text', + 'text/x-python' => 'python', + 'text/x-csrc' => 'c', + 'text/x-chdr' => 'c', + 'text/x-c++hdr' => 'c', + 'text/x-c++src' => 'cpp', + 'text/x-patch' => 'diff', + 'text/x-lua' => 'lua', + 'text/x-java' => 'java', + 'text/x-haskell' => 'haskell', + 'text/x-literate-haskell' => 'haskell', + 'text/x-subviewer' => 'bash', + 'text/x-makefile' => 'make', + #'text/x-log' => 'log', + 'text/html' => 'html', + 'text/css' => 'css', + 'message/rfc822' => 'email', + #'image/svg+xml' => 'xml', + 'application/x-perl' => 'perl', + 'application/xml' => 'xml', + 'application/javascript' => 'javascript', + 'application/x-desktop' => 'text', + 'application/x-m4' => 'text', + 'application/x-awk' => 'text', + 'application/x-java' => 'java', + 'application/x-php' => 'php', + 'application/x-ruby' => 'ruby', + 'application/x-shellscript' => 'bash', + 'application/x-x509-ca-cert' => 'text', + 'application/mbox' => 'email', + 'application/x-genesis-rom' => 'text', + 'application/x-applix-spreadsheet' => 'actionscript' + ); + if (array_key_exists($type, $typearray)) return $typearray[$type]; + + if (strpos($type, 'text/') === 0) return 'text'; + + # default + return false; + } + + // Map special filenames to extensions + function filename2extension($name) + { + $namearray = array( + 'PKGBUILD' => 'bash', + '.vimrc' => 'vim' + ); + if (array_key_exists($name, $namearray)) return $namearray[$name]; + + return false; + } } -# vim: set ts=2 sw=2 et: -/* End of file file_mod.php */ -/* Location: ./system/application/models/file_mod.php */ +# vim: set noet: |