<?php /* Question2Answer by Gideon Greenspan and contributors http://www.question2answer.org/ File: qa-include/qa-app-upload.php Description: Application-level file upload functionality 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. More about this license: http://www.question2answer.org/license.php */ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser header('Location: ../'); exit; } function qa_get_max_upload_size() /* Return the maximum size of file that can be uploaded, based on database and PHP limits */ { if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } $mindb = 16777215; // from MEDIUMBLOB column type $minphp = trim(ini_get('upload_max_filesize')); switch (strtolower(substr($minphp, -1))) { case 'g': $minphp *= 1024; // fall-through case 'm': $minphp *= 1024; // fall-through case 'k': $minphp *= 1024; } return min($mindb, $minphp); } function qa_upload_file($localfilename, $sourcefilename, $maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null) /* Move an uploaded image or other file into blob storage. Pass the $localfilename where the file is currently stored (temporarily) and the $sourcefilename of the file on the user's computer (if using PHP's usual file upload mechanism, these are obtained from $_FILES[..]['tmp_name'] and $_FILES[..]['name'] fields respectively). To apply a maximum file size (in bytes) beyond the general one, use $maxfilesize, otherwise set it to null. Set $onlyimage to true if only image uploads (PNG, GIF, JPEG) are allowed. To apply a maximum width or height (in pixels) to uploaded images, set $imagemaxwidth and $imagemaxheight. The function returns an array which may contain the following elements: 'error' => a string containing an error, if one occurred 'format' => the format (file extension) of the blob created (all scaled images end up as 'jpeg') 'width' => if an image, the width in pixels of the blob created (after possible scaling) 'height' => if an image, the height in pixels of the blob created (after possible scaling) 'blobid' => the blobid that was created (if there was no error) 'bloburl' => the url that can be used to view/download the created blob (if there was no error) */ { if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } $result=array(); // Check per-user upload limits require_once QA_INCLUDE_DIR.'app/users.php'; require_once QA_INCLUDE_DIR.'app/limits.php'; switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS)) { case 'limit': $result['error']=qa_lang('main/upload_limit'); return $result; case false: qa_limits_increment(qa_get_logged_in_userid(), QA_LIMIT_UPLOADS); break; default: $result['error']=qa_lang('users/no_permission'); return $result; } // Check the uploaded file is not too large $filesize=filesize($localfilename); if (isset($maxfilesize)) $maxfilesize=min($maxfilesize, qa_get_max_upload_size()); else $maxfilesize=qa_get_max_upload_size(); if ( ($filesize<=0) || ($filesize>$maxfilesize) ) { // if file was too big for PHP, $filesize will be zero $result['error']=qa_lang_sub('main/max_upload_size_x', number_format($maxfilesize/1048576, 1).'MB'); return $result; } // Find out what type of source file was uploaded and if appropriate, check it's an image and get preliminary size measure $pathinfo=pathinfo($sourcefilename); $format=strtolower(@$pathinfo['extension']); $isimage=($format=='png') || ($format=='gif') || ($format=='jpeg') || ($format=='jpg'); // allowed image extensions if ($isimage) { $imagesize=@getimagesize($localfilename); if (is_array($imagesize)) { $result['width']=$imagesize[0]; $result['height']=$imagesize[1]; switch ($imagesize['2']) { // reassign format based on actual content, if we can case IMAGETYPE_GIF: $format='gif'; break; case IMAGETYPE_JPEG: $format='jpeg'; break; case IMAGETYPE_PNG: $format='png'; break; } } } $result['format']=$format; if ($onlyimage) if ( (!$isimage) || !is_array($imagesize) ) { $result['error']=qa_lang_sub('main/image_not_read', 'GIF, JPG, PNG'); return $result; } // Read in the raw file contents $content=file_get_contents($localfilename); // If appropriate, get more accurate image size and apply constraints to it require_once QA_INCLUDE_DIR.'util/image.php'; if ($isimage && qa_has_gd_image()) { $image=@imagecreatefromstring($content); if (is_resource($image)) { $result['width']=$width=imagesx($image); $result['height']=$height=imagesy($image); if (isset($imagemaxwidth) || isset($imagemaxheight)) if (qa_image_constrain( $width, $height, isset($imagemaxwidth) ? $imagemaxwidth : $width, isset($imagemaxheight) ? $imagemaxheight : $height )) { qa_gd_image_resize($image, $width, $height); if (is_resource($image)) { $content=qa_gd_image_jpeg($image); $result['format']=$format='jpeg'; $result['width']=$width; $result['height']=$height; } } if (is_resource($image)) // might have been lost imagedestroy($image); } } // Create the blob and return require_once QA_INCLUDE_DIR.'app/blobs.php'; $userid=qa_get_logged_in_userid(); $cookieid=isset($userid) ? qa_cookie_get() : qa_cookie_get_create(); $result['blobid']=qa_create_blob($content, $format, $sourcefilename, $userid, $cookieid, qa_remote_ip_address()); if (!isset($result['blobid'])) { $result['error']=qa_lang('main/general_error'); return $result; } $result['bloburl']=qa_get_blob_url($result['blobid'], true); return $result; } function qa_upload_file_one($maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null) /* In response to a file upload, move the first uploaded file into blob storage. Other parameters are as for qa_upload_file(...) */ { $file=reset($_FILES); return qa_upload_file($file['tmp_name'], $file['name'], $maxfilesize, $onlyimage, $imagemaxwidth, $imagemaxheight); } /* Omit PHP closing tag to help avoid accidental output */