/** * Fetch a resize image from an existing filedata * * @param array File information * * */ public function fetchResizedImageFromFiledata(&$record, $type) { $options = vB::getDatastore()->get_value('options'); $sizes = @unserialize($options['attachresizes']); $filename = 'temp.' . $record['extension']; if (!isset($sizes[$type]) or empty($sizes[$type])) { throw new vB_Exception_Api('thumbnail_nosupport'); } if ($options['attachfile']) { if ($options['attachfile'] == ATTACH_AS_FILES_NEW) { $path = $options['attachpath'] . '/' . implode('/', preg_split('//', $record['userid'], -1, PREG_SPLIT_NO_EMPTY)) . '/'; } else { $path = $options['attachpath'] . '/' . $record['userid'] . '/'; } $location = $path . $record['filedataid'] . '.attach'; } else { // Must save filedata to a temp file as the img operations require a file read $location = vB_Utilities::getTmpFileName($record['userid'], 'vbimage'); @file_put_contents($location, $record['filedata']); } $resized = $this->fetchThumbnail($filename, $location, $sizes[$type], $sizes[$type], $options['thumbquality']); $record['resize_dateline'] = $resized['filesize']; $record['resize_filesize'] = strlen($resized['filedata']); if ($options['attachfile']) { if ($options['attachfile'] == ATTACH_AS_FILES_NEW) { $path = $options['attachpath'] . '/' . implode('/', preg_split('//', $record['userid'], -1, PREG_SPLIT_NO_EMPTY)) . '/'; } else { $path = $options['attachpath'] . '/' . $record['userid'] . '/'; } @file_put_contents($path . $record['filedataid'] . '.' . $type, $resized['filedata']); } else { $record['resize_filedata'] = $resized['filedata']; } vB::getDbAssertor()->assertQuery('vBForum:replaceIntoFiledataResize', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'filedataid' => $record['filedataid'], 'resize_type' => $type, 'resize_filedata' => $options['attachfile'] ? '' : $record['resize_filedata'], 'resize_filesize' => $record['resize_filesize'], 'resize_dateline' => vB::getRequest()->getTimeNow(), 'resize_width' => $resized['width'], 'resize_height' => $resized['height'], 'reload' => 0)); if (!$options['attachfile']) { @unlink($location); } }
/** Upload an image based on the url * * @param int user ID * @param string remote url * @param bool save as attachment * * @return mixed array of data, includes filesize, dateline, htmltype, filename, extension, and filedataid **/ public function uploadUrl($userid, $url, $attachment = false, $uploadfrom = '') { //Leave for consistency with admincp if (!defined('ATTACH_AS_FILES_NEW')) { define('ATTACH_AS_FILES_NEW', 2); } //Did we get a valid url? if (empty($url)) { // throw the same exception to mitigate SSRF (VBV-13082) throw new vB_Exception_Api('upload_invalid_image'); } if (!preg_match('#^https?://#i', $url)) { // throw the same exception to mitigate SSRF (VBV-13082) throw new vB_Exception_Api('upload_invalid_image'); } // Retrieve the image $vurl = new vB_vURL(); $fileResult = $vurl->fetch_body($url, 0, false, true); if (empty($fileResult['body'])) { // throw the same exception to mitigate SSRF (VBV-13082) throw new vB_Exception_Api('upload_invalid_image'); } $pathinfo = pathinfo($url); if (empty($pathinfo)) { // throw the same exception to mitigate SSRF (VBV-13082) throw new vB_Exception_Api('upload_invalid_image'); } // if there's no extension here try get one from elsewhere $extension_map = $this->imageHandler->getExtensionMap(); if (empty($pathinfo['extension']) or !array_key_exists(strtolower($pathinfo['extension']), $extension_map)) { // try to get an extension from the content type header if (!empty($fileResult['headers']['content-type'])) { // should be something like image/jpeg $typeData = explode('/', $fileResult['headers']['content-type']); if (count($typeData) == 2 and array_key_exists(trim($typeData[1]), $extension_map)) { $extension = strtolower($extension_map[trim($typeData[1])]); } } $name = $pathinfo['basename'] . '.' . $extension; } else { $extension = $pathinfo['extension']; $name = $pathinfo['basename']; } $extension = strtolower($extension); $filename = vB_Utilities::getTmpFileName($userid, 'vbattach', ".{$extension}"); file_put_contents($filename, $fileResult['body']); $filesize = strlen($fileResult['body']); //Make a local copy $filearray = array('name' => $name, 'size' => $filesize, 'type' => 'image/' . $extension_map[$extension], 'tmp_name' => $filename); if (!empty($uploadfrom)) { $filearray['uploadFrom'] = $uploadfrom; } if ($attachment) { return $this->uploadAttachment($userid, $filearray); } $result = $this->saveUpload($userid, $filearray, $fileResult['body'], $filesize, $extension, true); if (file_exists($filearray['tmp_name'])) { @unlink($filearray['tmp_name']); } return $result; }
public function cropFileData($filedataid, $data = array()) { $usercontext = vB::getUserContext(); if (!$usercontext->fetchUserId() or !$usercontext->hasPermission('genericpermissions', 'canuseavatar') or !$usercontext->hasPermission('genericpermissions', 'canmodifyprofile')) { throw new vB_Exception_API('no_permission_use_avatar'); } //Did we get a valid url? if (empty($filedataid)) { throw new vB_Exception_API('upload_invalid_url'); } //add @ to suppress warnings caused by invalid url $filedata = vB_Api::instanceInternal('filedata')->fetchImageByFiledataid($filedataid); if (empty($filedata)) { throw new vB_Exception_API('upload_invalid_url'); } $imageHandler = vB_Image::instance(); $extension_map = $imageHandler->getExtensionMap(); if (!array_key_exists(strtolower($filedata['extension']), $extension_map)) { throw new vB_Exception_API('error_thumbnail_notcorrectimage'); } //Make a local copy $filename = vB_Utilities::getTmpFileName('', 'vbprofile', ".{$filedata['extension']}"); file_put_contents($filename, $filedata['filedata']); $crop = array(); if (!empty($data) and is_array($data) and array_key_exists('crop', $data)) { $crop = $data['crop']; } return vB_Library::instance('user')->uploadAvatar($filename, $crop); }
/** * new vURL method which stores items in a file if it can until needed * * @return mixed false on failure, true or array depending on response requested */ function exec2() { $this->tmpfile = vB_Utilities::getTmpFileName('', 'vbvurl'); if (empty($this->options[VURL_URL])) { trigger_error('Must set URL with set_option(VURL_URL, $url)', E_USER_ERROR); } if (!empty($this->options[VURL_USERAGENT])) { $this->options[VURL_HTTPHEADER][] = 'User-Agent: ' . $this->options[VURL_USERAGENT]; } if ($this->bitoptions & VURL_CLOSECONNECTION) { $this->options[VURL_HTTPHEADER][] = 'Connection: close'; } foreach (array_keys($this->transports) as $tname) { $transport =& $this->transports[$tname]; if (($result = $transport->exec()) === VURL_HANDLED and !$this->fetch_error()) { return $this->format_response(array('headers' => $transport->response_header, 'body' => $transport->response_text, 'body_file' => $this->tmpfile)); } if ($this->fetch_error()) { return false; } } @unlink($this->tmpfile); $this->set_error(VURL_ERROR_NOLIB); return false; }
protected function uploadImageStreamStringToFiledata($imageContent, $prefix = 'vb_') { // It doesn't seem like we have existing functions to just save the raw image stream as filedata. // The existing content_attach functions seem to all require some temporary file to exist somewhere. // So let's save the image in a temporary file, save it to the file system using existing functions, // then remove the file. $tempIconFileLocation = vB_Utilities::getTmpFileName('', $prefix); // removal happens below, look for the unlink() call file_put_contents($tempIconFileLocation, $imageContent); /* * Below depends on the GD library * http://www.php.net/manual/en/function.getimagesize.php * Index 0 and 1 contains respectively the width and the height of the image. * Index 2 is one of the IMAGETYPE_XXX constants indicating the type of the image. * Index 3 is a text string with the correct height="yyy" width="xxx" string that can be used directly in an IMG tag. * mime is the correspondant MIME type of the image. This information can be used to deliver images with the correct HTTP Content-type header: */ $imageSize = getimagesize($tempIconFileLocation); $extension = image_type_to_extension($imageSize[2], false); $fileArray = array(); $fileArray['tmp_name'] = $tempIconFileLocation; // apparently fetchThumbnail() requires that the NAME has a valid extension... This is just bogus because we totally made up this file, but whatever $fileArray['name'] = 'image_' . md5(microtime(true)) . "." . $extension; $userid = vB::getCurrentSession()->get('userid'); $result = vB_Library::instance('content_attach')->saveUpload($userid, $fileArray, $imageContent, filesize($tempIconFileLocation), $extension, true, true); // temp file deletion is not done automatically, so we must do it. if (!empty($tempIconFileLocation)) { @unlink($tempIconFileLocation); } if (!isset($result['filedataid'])) { /* * If we cannot upload an image, we should just continue importing the theme as * icons and preview image are optional. * I'm leaving an exception here in case we want to handle it better, or we want * to move this into an API class, so the caller should catch the exception and * handle it accordingly. */ throw new vB_Exception_Api('theme_icon_upload_error'); } /* * Note, this function returns an array to adhere to API standards just in case this * ends up being moved into an API class. If we do move it into an API class, we may * want to change the Exception above to be a vB_Exception_Api */ return array('filedataid' => $result['filedataid']); }
/** * See function definition in vB_Image */ public function getImageFromString($string, $moveabout = true) { $tmpname = vB_Utilities::getTmpFileName('', 'vbimagick'); if (!$tmpname) { throw new vB_Exception_Api('temp_file_create_error'); } // Command start for no background image $execute = ' -size 201x61 xc:white '; $fonts = $this->fetchRegimageFonts(); if ($moveabout) { $backgrounds = $this->fetchRegimageBackgrounds(); if (!empty($backgrounds)) { $index = mt_rand(0, count($backgrounds) - 1); $background = $backgrounds["{$index}"]; // replace Command start with background image $execute = " \"{$background}\" -resize 201x61! -swirl " . mt_rand(10, 100); // randomly rotate the background image 180 degrees $execute .= vB::getRequest()->getTimeNow() & 2 ? ' -rotate 180 ' : ''; } // Randomly move the letters up and down for ($x = 0; $x < strlen($string); $x++) { if (!empty($fonts)) { $index = mt_rand(0, count($fonts) - 1); if ($this->regimageoption['randomfont']) { $font = $fonts["{$index}"]; } else { if (!$font) { $font = $fonts["{$index}"]; } } } else { $font = 'Helvetica'; } if ($this->regimageoption['randomshape']) { // Stroke Width, 1 or 2 $strokewidth = mt_rand(1, 2); // Pick a random color $r = mt_rand(50, 200); $b = mt_rand(50, 200); $g = mt_rand(50, 200); // Pick a Shape $x1 = mt_rand(0, 200); $y1 = mt_rand(0, 60); $x2 = mt_rand(0, 200); $y2 = mt_rand(0, 60); $start = mt_rand(0, 360); $end = mt_rand(0, 360); switch (mt_rand(1, 5)) { case 1: $shape = "\"roundrectangle {$x1},{$y1} {$x2},{$y2} {$start},end\""; break; case 2: $shape = "\"arc {$x1},{$y1} {$x2},{$y2} 20,15\""; break; case 3: $shape = "\"ellipse {$x1},{$y1} {$x2},{$y2} {$start},{$end}\""; break; case 4: $shape = "\"line {$x1},{$y1} {$x2},{$y2}\""; break; case 5: $x3 = mt_rand(0, 200); $y3 = mt_rand(0, 60); $x4 = mt_rand(0, 200); $y4 = mt_rand(0, 60); $shape = "\"polygon {$x1},{$y1} {$x2},{$y2} {$x3},{$y3} {$x4},{$y4}\""; break; } // before or after $place = mt_rand(1, 2); $finalshape = " -flatten -stroke \"rgb({$r},{$b},{$g})\" -strokewidth {$strokewidth} -fill none -draw {$shape} -stroke none "; if ($place == 1) { $execute .= $finalshape; } } $slant = (($x <= 1 or $x == 5) and $this->regimageoption['randomslant']) ? true : false; $execute .= $this->annotate($string["{$x}"], $font, $slant, true); if ($this->regimageoption['randomshape'] and $place == 2) { $execute .= $finalshape; } } } else { if (!empty($fonts)) { $font = $fonts[0]; } else { $font = 'Helvetica'; } $execute .= $this->annotate("\"{$string}\"", $font, false, false); } // Swirl text, stroke inner border of 1 pixel and output as GIF $execute .= ' -flatten '; $execute .= ($moveabout and $this->regimageoption['randomslant']) ? ' -swirl 20 ' : ''; $execute .= " -stroke black -strokewidth 1 -fill none -draw \"rectangle 0,60 200,0\" -depth 8 PNG:\"{$tmpname}\""; if ($result = $this->fetchImExec('convert', $execute)) { $filedata = @file_get_contents($tmpname); $fileSize = 0; if ($tmpSize = @filesize($tmpname)) { $fileSize = $tmpSize; } else { $fileSize = strlen($filedata); } @unlink($tmpname); // return imageinfo return array('filedata' => $filedata, 'filetype' => 'png', 'filesize' => $fileSize, 'contentType' => 'image/png'); } else { @unlink($tmpname); return false; } }
$remotefile = false; if (is_file($avatar['avatarpath'])) { $imagepath = $avatar['avatarpath']; } else { $location = dirname(__FILE__) . '/../' . $avatar['avatarpath']; if (is_file($location)) { $imagepath = $location; } else { if ($avatar['avatarpath'][0] == '/') { // absolute web path -- needs to be translated into a full path and handled that way $avatar['avatarpath'] = create_full_url($avatar['avatarpath']); } } } if (substr($avatar['avatarpath'], 0, 7) == 'http://') { $imagepath = vB_Utilities::getTmpFileName($avatar['avatarid'], 'vbavatar'); if ($filenum = @fopen($imagepath, 'wb')) { require_once DIR . '/includes/class_vurl.php'; $vurl = new vB_vURL($vbulletin); $vurl->set_option(VURL_URL, $avatar['avatarpath']); $vurl->set_option(VURL_HEADER, true); $vurl->set_option(VURL_RETURNTRANSFER, true); if ($result = $vurl->exec()) { @fwrite($filenum, $result['body']); } unset($vurl); @fclose($filenum); $remotefile = true; } } if (!file_exists($imagepath)) {
/** * This function accepts a file via URL or from $_FILES, verifies it, and places it in a temporary location for processing * * @param mixed Valid options are: (a) a URL to a file to retrieve or (b) a pointer to a file in the $_FILES array */ function accept_upload(&$upload) { $this->error = ''; if (!is_array($upload) and strval($upload) != '') { $this->upload['extension'] = strtolower(file_extension($upload)); // Check extension here so we can save grabbing a large file that we aren't going to use if (!$this->is_valid_extension($this->upload['extension'])) { $this->set_error('upload_invalid_file'); return false; } // Admins can upload any size file if ($this->registry->userinfo['permissions']['adminpermissions'] & $this->registry->bf_ugp_adminpermissions['cancontrolpanel']) { $this->maxuploadsize = 0; } else { $this->maxuploadsize = $this->fetch_max_uploadsize($this->upload['extension']); if (!$this->maxuploadsize) { $newmem = 20971520; } } if (!preg_match('#^((http|ftp)s?):\\/\\/#i', $upload)) { $upload = 'http://' . $upload; } if (ini_get('allow_url_fopen') == 0 and !function_exists('curl_init')) { $this->set_error('upload_fopen_disabled'); return false; } else { if ($filesize = $this->fetch_remote_filesize($upload)) { if ($this->maxuploadsize and $filesize > $this->maxuploadsize) { $this->set_error('upload_remoteimage_toolarge'); return false; } else { if (function_exists('memory_get_usage') and $memory_limit = @ini_get('memory_limit') and $memory_limit != -1) { // Make sure we have enough memory to process this file $memorylimit = vb_number_format($memory_limit, 0, false, null, ''); $memoryusage = memory_get_usage(); $freemem = $memorylimit - $memoryusage; $newmemlimit = !empty($newmem) ? $freemem + $newmem : $freemem + $filesize; if (($current_memory_limit = vB_Utilities::ini_size_to_bytes(@ini_get('memory_limit'))) < $newmemlimit and $current_memory_limit > 0) { @ini_set('memory_limit', $newmemlimit); } } require_once DIR . '/includes/class_vurl.php'; $vurl = new vB_vURL($this->registry); $vurl->set_option(VURL_URL, $upload); $vurl->set_option(VURL_FOLLOWLOCATION, 1); $vurl->set_option(VURL_HEADER, true); $vurl->set_option(VURL_MAXSIZE, $this->maxuploadsize); $vurl->set_option(VURL_RETURNTRANSFER, true); if ($result = $vurl->exec2()) { } else { switch ($vurl->fetch_error()) { case VURL_ERROR_MAXSIZE: $this->set_error('upload_remoteimage_toolarge'); break; case VURL_ERROR_NOLIB: // this condition isn't reachable $this->set_error('upload_fopen_disabled'); break; case VURL_ERROR_SSL: case VURL_URL_URL: default: $this->set_error('retrieval_of_remote_file_failed'); } return false; } unset($vurl); } } else { $this->set_error('upload_invalid_url'); return false; } } // write file to temporary directory... $this->upload['location'] = vB_Utilities::getTmpFileName('', 'vbupload'); $attachment_write_failed = true; if (!empty($result['body'])) { $fp = $this->registry->userinfo['permissions']['adminpermissions'] & $this->registry->bf_ugp_adminpermissions['cancontrolpanel'] ? fopen($this->upload['location'], 'wb') : @fopen($this->upload['location'], 'wb'); if ($fp and $this->upload['location']) { @fwrite($fp, $result['body']); @fclose($fp); $attachment_write_failed = false; } } else { if (file_exists($result['body_file'])) { if (@rename($result['body_file'], $this->upload['location']) or copy($result['body_file'], $this->upload['location']) and unlink($result['body_file'])) { $mask = 0777 & ~umask(); @chmod($this->upload['location'], $mask); $attachment_write_failed = false; } } } if ($attachment_write_failed) { $this->set_error('upload_writefile_failed'); return false; } $this->upload['filesize'] = @filesize($this->upload['location']); $this->upload['filename'] = basename($upload); $this->upload['extension'] = strtolower(file_extension($this->upload['filename'])); $this->upload['thumbnail'] = ''; $this->upload['filestuff'] = ''; $this->upload['url'] = true; } else { $this->upload['filename'] = trim($upload['name']); $this->upload['filesize'] = intval($upload['size']); $this->upload['location'] = trim($upload['tmp_name']); $this->upload['extension'] = strtolower(file_extension($this->upload['filename'])); $this->upload['thumbnail'] = ''; $this->upload['filestuff'] = ''; if ($this->registry->userinfo['permissions']['adminpermissions'] & $this->registry->bf_ugp_adminpermissions['cancontrolpanel'] and $this->upload['error']) { // Encountered PHP upload error if (!($maxupload = @ini_get('upload_max_filesize'))) { $maxupload = 10485760; } $maxattachsize = vb_number_format($maxupload, 1, true); switch ($this->upload['error']) { case '1': // UPLOAD_ERR_INI_SIZE // UPLOAD_ERR_INI_SIZE case '2': // UPLOAD_ERR_FORM_SIZE $this->set_error('upload_file_exceeds_php_limit', $maxattachsize); break; case '3': // UPLOAD_ERR_PARTIAL $this->set_error('upload_file_partially_uploaded'); break; case '4': $this->set_error('upload_file_failed'); break; case '6': $this->set_error('missing_temporary_folder'); break; case '7': $this->set_error('upload_writefile_failed'); break; case '8': $this->set_error('upload_stopped_by_extension'); break; default: $this->set_error('upload_invalid_file'); } return false; } else { if ($this->upload['error'] or $this->upload['location'] == 'none' or $this->upload['location'] == '' or $this->upload['filename'] == '' or !$this->upload['filesize'] or !is_uploaded_file($this->upload['location'])) { if ($this->emptyfile or $this->upload['filename'] != '') { $this->set_error('upload_file_failed'); } return false; } } if ($this->registry->options['safeupload']) { $temppath = $this->registry->options['tmppath'] . '/' . $this->registry->session->fetch_sessionhash(); $moveresult = $this->registry->userinfo['permissions']['adminpermissions'] & $this->registry->bf_ugp_adminpermissions['cancontrolpanel'] ? move_uploaded_file($this->upload['location'], $temppath) : @move_uploaded_file($this->upload['location'], $temppath); if (!$moveresult) { $this->set_error('upload_unable_move'); return false; } $this->upload['location'] = $temppath; } } // Check if the filename is utf8 $this->upload['utf8_name'] = isset($upload['utf8_name']) and $upload['utf8_name']; $return_value = true; // Legacy Hook 'upload_accept' Removed // return $return_value; }
/** * * * */ function pre_save($doquery = true) { if ($this->presave_called !== null) { return $this->presave_called; } if (!$this->condition) { // Check if we need to insert or overwrite this image. if ($this->fetch_field('userid') and $this->assertor->getRow($this->table, array('userid' => $this->fetch_field('userid')))) { $this->condition['userid'] = $this->fetch_field('userid'); } } // Store in database $table = $this->fetchTableBase($this->table); if ($table == 'customavatar' and $this->fetch_field('filedata') and !$this->fetch_field('filedata_thumb') and !$this->options['usefileavatar']) { $filename = vB_Utilities::getTmpFileName($this->fetch_field('userid'), 'vbuserpic'); $filenum = @fopen($filename, 'wb'); @fwrite($filenum, $this->fetch_field('filedata')); @fclose($filenum); $imageinfo = $this->imageHandler->fetchImageInfo($filename); if (!$this->fetch_field('width') or !$this->fetch_field('height')) { if ($imageinfo) { $this->set('width', $imageinfo[0]); $this->set('height', $imageinfo[1]); } } $thumbnail = $this->fetch_thumbnail($filename, false, $imageinfo); $this->deleteFile($filename); if ($thumbnail['filedata']) { $this->set('width_thumb', $thumbnail['width']); $this->set('height_thumb', $thumbnail['height']); $this->set('filedata_thumb', $thumbnail['filedata']); unset($thumbnail); } else { $this->set('width_thumb', 0); $this->set('height_thumb', 0); $this->set('filedata_thumb', ''); } } $return_value = true; $this->presave_called = $return_value; return $return_value; }