<?php
/*
Viscacha - A bulletin board solution for easily managing your content
Copyright (C) 2004-2009 The Viscacha Project
Author: Matthias Mohr (et al.)
Publisher: The Viscacha Project, http://www.viscacha.org
Start Date: May 22, 2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
if (defined('VISCACHA_CORE') == false) { die('Error: Hacking Attempt'); }
define('UPLOAD_ERR_FILE_INDEX', 1);
define('UPLOAD_ERR_FILE_SIZE', 2);
define('UPLOAD_ERR_IMAGE_WIDTH', 3);
define('UPLOAD_ERR_IMAGE_HEIGHT', 4);
define('UPLOAD_ERR_FILE_TYPE', 5);
define('UPLOAD_ERR_COPY', 6);
define('UPLOAD_ERR_FILE_EXISTS', 7);
class uploader {
var $file;
var $path;
var $file_types;
var $error;
var $max_filesize;
var $max_image_width;
var $max_image_height;
var $new_filename;
var $copy_func;
/**
* Konstruktor - Initializes the variables.
*/
function uploader () {
$this->file = array();
$this->path = dirname(__FILE__).DIRECTORY_SEPARATOR;
$this->file_types = array();
$this->new_filename = null;
$this->error = null;
$this->max_filesize = viscacha_function_exists('ini_maxupload') ? ini_maxupload() : 0;
$this->max_image_width = 0;
$this->max_image_height = 0;
$this->copy_func = 'move_uploaded_file';
}
/**
* Set the maximum file size.
*
* Set the maximum file size in bytes ($size), allowable by the object. 0 = unlimited
* NOTE: PHP's configuration file also can control the maximum upload size.
* To upload larger files, you'll have to change the php.ini file first.
*
* @param int file size in bytes
*/
function max_filesize($size){
$this->max_filesize = intval($size);
}
/**
* Set maximum image dimensions.
*
* Sets the maximum pixel dimensions. Will only be checked if the
* uploaded file is an image.
*
* @param int maximum pixel width of image uploads
* @param int maximum pixel height of image uploads
*
*/
function max_image_size($width, $height){
$this->max_image_width = intval($width);
$this->max_image_height = intval($height);
}
/**
* Sets allowed file types.
*
* Sets the allowed file types. Specify the extensions without leading dot!
* If you do not specify any extensions, the followeing will be used:
* zip, rar, doc, pdf, txt, gif, png, jpg
* If you specify an empty array, all extensions are allowed.
*
* @param array File types/Extensions
*
*/
function file_types($accept_type = null){
if (is_array($accept_type) == true) {
$this->file_types = array_map('strtolower', $accept_type);
}
else {
$this->file_types = array('zip','rar','doc','pdf','txt','gif','png','jpg');
}
}
/**
* Set the upload path
*
* @param string Path
*/
function set_path($path) {
$this->path = $path;
if ($path[strlen($path)-1] != '/' && $path[strlen($path)-1] != '\\') {
$this->path .= '/';
}
}
/**
* Rename the uploaded file.
*
* Renames the uploaded file to $newname. Specify the new name without extension!
*
* @param string New file name (without extension)
*/
function rename_file($newname){
$this->new_filename = $newname;
}
/**
* Upload a file.
*
* Checks if the file is acceptable and uploads it to PHP's default upload diretory
*
* @param string Name of form field
* @return boolean
*/
function upload($index) {
global $imagetype_extension;
if (!isset($_FILES[$index]) || !is_array($_FILES[$index])) {
$this->error = UPLOAD_ERR_FILE_INDEX;
return false;
}
// Copy PHP's global $_FILES array to a local array
$indexes = array('extension','size','width','height','tmp_name','raw_name','form','type','name','image','filename');
foreach ($indexes as $key) {
$this->file[$key] = isset($_FILES[$index][$key]) ? $_FILES[$index][$key] : null;
}
// Set input field name
$this->file['form'] = $index;
// Get extension
$this->file['extension'] = strtolower(get_extension($this->file['name']));
// Get file size
if (empty($this->file['size']) == true) {
$this->file['size'] = filesize($this->file['tmp_name']);
}
// Set mime type
if (empty($this->file['type']) == true) {
if (viscacha_function_exists('mime_content_type') == true) {
$this->file['type'] = mime_content_type($this->file['name']);
}
}
// Check image data (height, width, image)
if(in_array($this->file['extension'], $imagetype_extension) == true) {
$this->file['image'] = true;
$properties = @getimagesize($this->file['tmp_name']);
if (is_array($properties) == false) {
$this->file['image'] = false;
}
else {
$this->file['width'] = $properties[0];
$this->file['height'] = $properties[1];
if (empty($this->file['type']) == true) {
$this->file['type'] = image_type_to_mime_type($properties[2]);
}
}
}
else {
$this->file['image'] = false;
}
// Set raw_name
$this->file['raw_name'] = substr($this->file['name'], 0, -(strlen($this->file['extension'])+1) );
$this->file['filename'] = $this->file['name'];
// test max file size
if($this->max_filesize > 0 && $this->file['size'] > $this->max_filesize ) {
$this->error = UPLOAD_ERR_FILE_SIZE;
return false;
}
// test max image size
if($this->file['image'] == true) {
if($this->max_image_width > 0 && $this->file['width'] > $this->max_image_width) {
$this->error = UPLOAD_ERR_IMAGE_WIDTH;
return false;
}
if($this->max_image_height > 0 && $this->file['height'] > $this->max_image_height) {
$this->error = UPLOAD_ERR_IMAGE_HEIGHT;
return false;
}
}
// check to see if the file is of type specified
if(count($this->file_types) > 0) {
if(in_array($this->file['extension'], $this->file_types) == false) {
$this->error = UPLOAD_ERR_FILE_TYPE;
return false;
}
}
if (!is_uploaded_file($this->file['tmp_name'])) {
$this->copy_func = 'copy';
}
return true;
}
/**
* Save uploaded file.
*
* Cleans up the filename, copies the file from PHP's temp location to $path,
* and checks the overwrite_mode
*
* @param path string File path to your upload directory
* @param overwrite_mode int 0 = rename if filename already exists (file.txt becomes file_1.txt)
* 1 = overwrite existing file
* 2 = do nothing if a file exists
* @return boolean
*/
function save_file($path = null, $overwrite_mode = 0){
if ($this->error != null) {
return false;
}
if ($path != null && strlen($path) > 0) {
$this->path = $path;
if ($path[strlen($path)-1] != '/' && $path[strlen($path)-1] != '\\') {
$this->path .= '/';
}
}
$success = false;
if ($this->new_filename != null) {
$this->file['raw_name'] = $this->new_filename;
}
else {
// Secure file name
$this->file['raw_name'] = convert2adress($this->file['raw_name'], false, '_');
}
$new_path = $this->path.$this->file['raw_name'].'.'.$this->file['extension'];
switch(intval($overwrite_mode)) {
case 1: // overwrite mode
if (call_user_func($this->copy_func, $this->file['tmp_name'], $new_path)) {
$success = true;
$this->file['tmp_name'] = $new_path;
}
else {
$success = false;
$this->error = UPLOAD_ERR_COPY;
}
break;
case 2: // do nothing
if(file_exists($this->path . $this->file["name"])){
$this->error = UPLOAD_ERR_FILE_EXISTS;
$success = false;
}
else {
if (call_user_func($this->copy_func, $this->file['tmp_name'], $new_path)) {
$success = true;
$this->file['tmp_name'] = $new_path;
}
else {
$success = false;
$this->error = UPLOAD_ERR_COPY;
}
}
break;
default: // create new with incremental extension
$n = 0;
while(file_exists($new_path) == true) {
$n++;
$new_path = $this->path.$this->file['raw_name'].'_'.$n.'.'.$this->file['extension'];
}
if ($n > 0) {
$this->file['raw_name'] .= '_'.$n;
}
if (call_user_func($this->copy_func, $this->file['tmp_name'], $new_path)) {
$success = true;
$this->file['tmp_name'] = $new_path;
}
else {
$success = false;
$this->error = UPLOAD_ERR_COPY;
}
}
$this->file['filename'] = $this->file['raw_name'].'.'.$this->file['extension'];
// Clean up text file line breaks
if(substr($this->file['type'], 0, 4) == 'text') {
$this->cleanup_text_file();
}
if (isset($GLOBALS['filesystem'])) {
global $filesystem;
$filesystem->chmod($this->file['tmp_name'], 0666);
}
else {
@chmod($this->file['tmp_name'], 0666);
}
return $success;
}
/**
* Get information from file-Variable
*
* Gets some information from the $this->file-Variable. There are some information about the uploaded file saved.
* Possible Indices are:
* string 'extension'
* int 'size'
* int 'width'
* int 'height'
* string 'tmp_name'
* string 'raw_name'
* string 'form'
* string 'type'
* string 'name'
* string 'filename'
* boolean 'image'
*
* @param string Index
* @return mixed
*/
function fileinfo($index) {
return isset($this->file[$index]) ? $this->file[$index] : null;
}
/**
* Checks whether an error occured (true) or not (false).
*
* @return boolean
*/
function upload_failed() {
return ($this->error != null);
}
/**
* Gets the correct error message.
*
* Methoed tries to use $lang-Object. If not available, hardcoded english phrases will be used.
*
* @return string error message
*/
function get_error() {
if ($this->error == null) {
return false;
}
$lang = new lang();
$lang->group("classes");
switch($this->error) {
case UPLOAD_ERR_FILE_INDEX:
$message = $lang->phrase('upload_error_noupload');
break;
case UPLOAD_ERR_FILE_SIZE:
$lang->assign('mfs', formatFilesize($this->max_filesize));
$message = $lang->phrase('upload_error_maxfilesize');
break;
case UPLOAD_ERR_IMAGE_WIDTH:
case UPLOAD_ERR_IMAGE_HEIGHT:
$lang->assign('mih', $this->max_image_height > 0 ? numbers($this->max_image_height) : $lang->phrase('upload_unspecified'));
$lang->assign('miw', $this->max_image_width > 0 ? numbers($this->max_image_width) : $lang->phrase('upload_unspecified'));
$message = $lang->phrase('upload_error_maximagesize');
break;
case UPLOAD_ERR_FILE_TYPE:
$lang->assign('aft', implode(', ', $this->file_types));
$message = $lang->phrase('upload_error_wrongfiletype');
break;
case UPLOAD_ERR_COPY:
$message = $lang->phrase('upload_error_noaccess');
break;
case UPLOAD_ERR_FILE_EXISTS:
$message = $lang->phrase('upload_error_fileexists');
break;
default:
$message = $lang->phrase('upload_error_default');
}
if (!empty($this->file['name'])) {
return "{$this->file['name']}: {$message}";
}
else {
return $message;
}
}
/**
* Converts line breaks in text files.
*
* Convert Mac (\r) and/or Unix (\n) line breaks to Windows (\r\n) by opening and rewriting the file on the server
*/
function cleanup_text_file(){
$fcontents = @file_get_contents($this->file['tmp_name']);
$fcontents = preg_replace("/(\r\n|\r|\n)/", "\r\n", $fcontents);
@file_put_contents($this->file['tmp_name'], $fcontents);
}
}
?>