diff --git a/htdocs/core/ajaxfileupload.php b/htdocs/core/ajaxfileupload.php new file mode 100644 index 00000000000..b4de16856fd --- /dev/null +++ b/htdocs/core/ajaxfileupload.php @@ -0,0 +1,348 @@ +fk_element=$fk_element; + $this->element=$element; + + $this->options = array( + 'script_url' => $_SERVER['PHP_SELF'], + 'upload_dir' => $conf->$element->dir_output . '/' . $fk_element . '/', + 'upload_url' => DOL_URL_ROOT.'/document.php?modulepart='.$element.'&attachment=1&file=/'.$fk_element.'/', + 'param_name' => 'files', + // The php.ini settings upload_max_filesize and post_max_size + // take precedence over the following max_file_size setting: + 'max_file_size' => null, + 'min_file_size' => 1, + 'accept_file_types' => '/.+$/i', + 'max_number_of_files' => null, + 'discard_aborted_uploads' => true, + 'image_versions' => array( + // Uncomment the following version to restrict the size of + // uploaded images. You can also add additional versions with + // their own upload directories: + /* + 'large' => array( + 'upload_dir' => dirname(__FILE__).'/files/', + 'upload_url' => dirname($_SERVER['PHP_SELF']).'/files/', + 'max_width' => 1920, + 'max_height' => 1200 + ), + */ + 'thumbnail' => array( + 'upload_dir' => $conf->$element->dir_output . '/' . $fk_element . '/thumbs/', + 'upload_url' => DOL_URL_ROOT.'/document.php?modulepart='.$element.'&attachment=1&file=/'.$fk_element.'/thumbs/', + 'max_width' => 40, + 'max_height' => 40 + ) + ) + ); + if ($options) { + $this->options = array_merge_recursive($this->options, $options); + } + } + + private function get_file_object($file_name) { + $file_path = $this->options['upload_dir'].$file_name; + if (is_file($file_path) && $file_name[0] !== '.') { + $file = new stdClass(); + $file->name = $file_name; + $file->mime = dol_mimetype($file_name,'',2); + $file->size = filesize($file_path); + $file->url = $this->options['upload_url'].rawurlencode($file->name); + foreach($this->options['image_versions'] as $version => $options) { + if (is_file($options['upload_dir'].$file_name)) { + $file->{$version.'_url'} = $options['upload_url'] + .rawurlencode($file->name); + } + } + $file->delete_url = $this->options['script_url'] + .'?file='.rawurlencode($file->name).'fk_element='.$this->fk_elment.'&element='.$this->element; + $file->delete_type = 'DELETE'; + return $file; + } + return null; + } + + private function get_file_objects() { + return array_values(array_filter(array_map( + array($this, 'get_file_object'), + scandir($this->options['upload_dir']) + ))); + } + + private function create_scaled_image($file_name, $options) { + $file_path = $this->options['upload_dir'].$file_name; + $new_file_path = $options['upload_dir'].$file_name; + list($img_width, $img_height) = @getimagesize($file_path); + if (!$img_width || !$img_height) { + return false; + } + $scale = min( + $options['max_width'] / $img_width, + $options['max_height'] / $img_height + ); + if ($scale > 1) { + $scale = 1; + } + $new_width = $img_width * $scale; + $new_height = $img_height * $scale; + $new_img = @imagecreatetruecolor($new_width, $new_height); + switch (strtolower(substr(strrchr($file_name, '.'), 1))) { + case 'jpg': + case 'jpeg': + $src_img = @imagecreatefromjpeg($file_path); + $write_image = 'imagejpeg'; + break; + case 'gif': + $src_img = @imagecreatefromgif($file_path); + $write_image = 'imagegif'; + break; + case 'png': + $src_img = @imagecreatefrompng($file_path); + $write_image = 'imagepng'; + break; + default: + $src_img = $image_method = null; + } + $success = $src_img && @imagecopyresampled( + $new_img, + $src_img, + 0, 0, 0, 0, + $new_width, + $new_height, + $img_width, + $img_height + ) && $write_image($new_img, $new_file_path); + // Free up memory (imagedestroy does not delete files): + @imagedestroy($src_img); + @imagedestroy($new_img); + return $success; + } + + private function has_error($uploaded_file, $file, $error) { + if ($error) { + return $error; + } + if (!preg_match($this->options['accept_file_types'], $file->name)) { + return 'acceptFileTypes'; + } + if ($uploaded_file && is_uploaded_file($uploaded_file)) { + $file_size = filesize($uploaded_file); + } else { + $file_size = $_SERVER['CONTENT_LENGTH']; + } + if ($this->options['max_file_size'] && ( + $file_size > $this->options['max_file_size'] || + $file->size > $this->options['max_file_size']) + ) { + return 'maxFileSize'; + } + if ($this->options['min_file_size'] && + $file_size < $this->options['min_file_size']) { + return 'minFileSize'; + } + if (is_int($this->options['max_number_of_files']) && ( + count($this->get_file_objects()) >= $this->options['max_number_of_files']) + ) { + return 'maxNumberOfFiles'; + } + return $error; + } + + private function handle_file_upload($uploaded_file, $name, $size, $type, $error) { + $file = new stdClass(); + $file->name = basename(stripslashes($name)); + $file->size = intval($size); + $file->type = $type; + $error = $this->has_error($uploaded_file, $file, $error); + if (!$error && $file->name) { + if ($file->name[0] === '.') { + $file->name = substr($file->name, 1); + } + $file_path = $this->options['upload_dir'].$file->name; + $append_file = is_file($file_path) && $file->size > filesize($file_path); + clearstatcache(); + if ($uploaded_file && is_uploaded_file($uploaded_file)) { + // multipart/formdata uploads (POST method uploads) + if ($append_file) { + file_put_contents( + $file_path, + fopen($uploaded_file, 'r'), + FILE_APPEND + ); + } else { + move_uploaded_file($uploaded_file, $file_path); + } + } else { + // Non-multipart uploads (PUT method support) + file_put_contents( + $file_path, + fopen('php://input', 'r'), + $append_file ? FILE_APPEND : 0 + ); + } + $file_size = filesize($file_path); + if ($file_size === $file->size) { + $file->url = $this->options['upload_url'].rawurlencode($file->name); + foreach($this->options['image_versions'] as $version => $options) { + if ($this->create_scaled_image($file->name, $options)) { + $file->{$version.'_url'} = $options['upload_url'] + .rawurlencode($file->name); + } + } + } else if ($this->options['discard_aborted_uploads']) { + unlink($file_path); + $file->error = 'abort'; + } + $file->size = $file_size; + $file->delete_url = $this->options['script_url'] + .'?file='.rawurlencode($file->name); + $file->delete_type = 'DELETE'; + } else { + $file->error = $error; + } + return $file; + } + + public function get() { + $file_name = isset($_REQUEST['file']) ? + basename(stripslashes($_REQUEST['file'])) : null; + if ($file_name) { + $info = $this->get_file_object($file_name); + } else { + $info = $this->get_file_objects(); + } + header('Content-type: application/json'); + echo json_encode($info); + } + + public function post() { + $upload = isset($_FILES[$this->options['param_name']]) ? + $_FILES[$this->options['param_name']] : array( + 'tmp_name' => null, + 'name' => null, + 'size' => null, + 'type' => null, + 'error' => null + ); + $info = array(); + if (is_array($upload['tmp_name'])) { + foreach ($upload['tmp_name'] as $index => $value) { + $info[] = $this->handle_file_upload( + $upload['tmp_name'][$index], + isset($_SERVER['HTTP_X_FILE_NAME']) ? + $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'][$index], + isset($_SERVER['HTTP_X_FILE_SIZE']) ? + $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'][$index], + isset($_SERVER['HTTP_X_FILE_TYPE']) ? + $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'][$index], + $upload['error'][$index] + ); + } + } else { + $info[] = $this->handle_file_upload( + $upload['tmp_name'], + isset($_SERVER['HTTP_X_FILE_NAME']) ? + $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'], + isset($_SERVER['HTTP_X_FILE_SIZE']) ? + $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'], + isset($_SERVER['HTTP_X_FILE_TYPE']) ? + $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'], + $upload['error'] + ); + } + header('Vary: Accept'); + if (isset($_SERVER['HTTP_ACCEPT']) && + (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false)) { + header('Content-type: application/json'); + } else { + header('Content-type: text/plain'); + } + echo json_encode($info); + } + + public function delete() { + $file_name = isset($_REQUEST['file']) ? + basename(stripslashes($_REQUEST['file'])) : null; + $file_path = $this->options['upload_dir'].$file_name; + $success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path); + if ($success) { + foreach($this->options['image_versions'] as $version => $options) { + $file = $options['upload_dir'].$file_name; + if (is_file($file)) { + unlink($file); + } + } + } + header('Content-type: application/json'); + echo json_encode($success); + } +} + +$upload_handler = new UploadHandler(null,$fk_element,$element); + +header('Pragma: no-cache'); +header('Cache-Control: private, no-cache'); +header('Content-Disposition: inline; filename="files.json"'); + +switch ($_SERVER['REQUEST_METHOD']) { + case 'HEAD': + case 'GET': + $upload_handler->get(); + break; + case 'POST': + $upload_handler->post(); + break; + case 'DELETE': + $upload_handler->delete(); + break; + default: + header('HTTP/1.0 405 Method Not Allowed'); +} +?> \ No newline at end of file diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 7c054b43622..85f1b7e05bf 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -22,7 +22,7 @@ * \file htdocs/core/class/html.formfile.class.php * \ingroup core * \brief File of class to offer components to list and upload files - * \version $Id: html.formfile.class.php,v 1.34 2011/06/30 13:27:20 hregis Exp $ + * \version $Id: html.formfile.class.php,v 1.35 2011/07/03 13:16:46 hregis Exp $ */ @@ -732,6 +732,89 @@ class FormFile // Fin de zone } + /** + * Show form to upload a new file with jquery fileupload + */ + function form_ajaxfileupload($object) + { + global $langs; + + print ''; + + print '
'; + print '
'; + print ''; + print ''; + print '
'; + print ''; + print ''; + print ''; + print ''; + print '
'; + print '
'; + print ''; + print '
'; + print '
'; + print '
'; + print '
'; + + // Include template + include(DOL_DOCUMENT_ROOT.'/core/tpl/ajaxfileupload.tpl.php'); + + } } diff --git a/htdocs/core/tpl/ajaxfileupload.tpl.php b/htdocs/core/tpl/ajaxfileupload.tpl.php new file mode 100644 index 00000000000..d595dec1c68 --- /dev/null +++ b/htdocs/core/tpl/ajaxfileupload.tpl.php @@ -0,0 +1,86 @@ + + * + * 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. + * + * $Id: ajaxfileupload.tpl.php,v 1.1 2011/07/03 13:16:46 hregis Exp $ + */ +?> + + + + + + \ No newline at end of file diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 8fbf3a01061..7054204a43f 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -26,7 +26,7 @@ * \file htdocs/main.inc.php * \ingroup core * \brief File that defines environment for Dolibarr pages only (variables not required by scripts) - * \version $Id: main.inc.php,v 1.747 2011/07/02 05:49:56 hregis Exp $ + * \version $Id: main.inc.php,v 1.748 2011/07/03 13:16:46 hregis Exp $ */ @ini_set('memory_limit', '64M'); // This may be useless if memory is hard limited by your PHP @@ -908,6 +908,11 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs print ''."\n"; // Tooltip print ''."\n"; // JNotify //print ''."\n"; // Lightbox + // jQuery fileupload + if (! empty($conf->global->MAIN_USE_JQUERY_FILEUPLOAD)) + { + print ''."\n"; + } } print ''."\n"; @@ -977,6 +982,14 @@ function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs print ''."\n"; print ''."\n"; } + // File Upload + if (! empty($conf->global->MAIN_USE_JQUERY_FILEUPLOAD)) + { + print ''."\n"; + print ''."\n"; + print ''."\n"; + print ''."\n"; + } // Global js function print ''."\n"; print ''."\n"; diff --git a/htdocs/societe/document.php b/htdocs/societe/document.php index ed7115063da..e496d064662 100644 --- a/htdocs/societe/document.php +++ b/htdocs/societe/document.php @@ -23,7 +23,7 @@ * \file htdocs/societe/document.php * \brief Tab for documents linked to third party * \ingroup societe - * \version $Id: document.php,v 1.30 2011/07/03 08:55:46 hregis Exp $ + * \version $Id: document.php,v 1.31 2011/07/03 13:16:46 hregis Exp $ */ require("../main.inc.php"); @@ -200,17 +200,23 @@ if ($socid > 0) $ret=$html->form_confirm($_SERVER["PHP_SELF"].'?socid='.$_GET["id"].'&urlfile='.urldecode($_GET["urlfile"]), $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile'), 'confirm_deletefile', '', 0, 1); if ($ret == 'html') print '
'; } - - - // Affiche formulaire upload + $formfile=new FormFile($db); - $formfile->form_attach_new_file($_SERVER["PHP_SELF"].'?socid='.$socid,'',0,0,$user->rights->societe->creer); - - - // List of document - $param='&socid='.$object->id; - $formfile->list_of_documents($filearray,$object,'societe',$param); - + + if ($conf->global->MAIN_USE_JQUERY_FILEUPLOAD) + { + $formfile->form_ajaxfileupload($object); + } + else + { + // Affiche formulaire upload + $formfile->form_attach_new_file($_SERVER["PHP_SELF"].'?socid='.$socid,'',0,0,$user->rights->societe->creer); + + + // List of document + $param='&socid='.$object->id; + $formfile->list_of_documents($filearray,$object,'societe',$param); + } print "

"; @@ -274,6 +280,6 @@ else $db->close(); -llxFooter('$Date: 2011/07/03 08:55:46 $ - $Revision: 1.30 $'); +llxFooter('$Date: 2011/07/03 13:16:46 $ - $Revision: 1.31 $'); ?>