diff --git a/include/Photo.php b/include/Photo.php index e734fed89a..f1e2989d51 100644 --- a/include/Photo.php +++ b/include/Photo.php @@ -1,91 +1,97 @@ 'jpg', - 'image/png' => 'png', - 'image/gif' => 'gif' - ); - } else { - $t = array(); - $t['image/jpeg'] ='jpg'; - if (imagetypes() & IMG_PNG) $t['image/png'] = 'png'; - } + /** + * @brief supported mimetypes and corresponding file extensions + */ + static function supportedTypes() { + if (class_exists('Imagick')) { - return $t; - } - - public function __construct($data, $type=null) { - $this->imagick = class_exists('Imagick'); - $this->types = $this->supportedTypes(); - if (!array_key_exists($type,$this->types)){ - $type='image/jpeg'; - } - $this->type = $type; - - if($this->is_imagick() && $this->load_data($data)) { - return true; + // Imagick::queryFormats won't help us a lot there... + // At least, not yet, other parts of friendica uses this array + $t = array( + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + 'image/gif' => 'gif' + ); } else { - // Failed to load with Imagick, fallback - $this->imagick = false; + $t = array(); + $t['image/jpeg'] ='jpg'; + if (imagetypes() & IMG_PNG) { + $t['image/png'] = 'png'; + } } - return $this->load_data($data); - } - public function __destruct() { - if($this->image) { - if($this->is_imagick()) { - $this->image->clear(); - $this->image->destroy(); - return; - } - imagedestroy($this->image); + return $t; } - } - public function is_imagick() { - return $this->imagick; - } + public function __construct($data, $type=null) { + $this->imagick = class_exists('Imagick'); + $this->types = $this->supportedTypes(); + if (!array_key_exists($type,$this->types)){ + $type='image/jpeg'; + } + $this->type = $type; - /** - * Maps Mime types to Imagick formats - */ - public function get_FormatsMap() { - $m = array( - 'image/jpeg' => 'JPG', - 'image/png' => 'PNG', - 'image/gif' => 'GIF' - ); - return $m; - } + if ($this->is_imagick() && $this->load_data($data)) { + return true; + } else { + // Failed to load with Imagick, fallback + $this->imagick = false; + } + return $this->load_data($data); + } - private function load_data($data) { - if($this->is_imagick()) { - $this->image = new Imagick(); - try { + public function __destruct() { + if ($this->image) { + if ($this->is_imagick()) { + $this->image->clear(); + $this->image->destroy(); + return; + } + imagedestroy($this->image); + } + } + + public function is_imagick() { + return $this->imagick; + } + + /** + * @brief Maps Mime types to Imagick formats + */ + public function get_FormatsMap() { + $m = array( + 'image/jpeg' => 'JPG', + 'image/png' => 'PNG', + 'image/gif' => 'GIF' + ); + return $m; + } + + private function load_data($data) { + if ($this->is_imagick()) { + $this->image = new Imagick(); + try { $this->image->readImageBlob($data); } catch (Exception $e) { @@ -93,41 +99,43 @@ class Photo { return false; } - /** - * Setup the image to the format it will be saved to - */ - $map = $this->get_FormatsMap(); - $format = $map[$type]; - $this->image->setFormat($format); + /* + * Setup the image to the format it will be saved to + */ + $map = $this->get_FormatsMap(); + $format = $map[$type]; + $this->image->setFormat($format); - // Always coalesce, if it is not a multi-frame image it won't hurt anyway - $this->image = $this->image->coalesceImages(); + // Always coalesce, if it is not a multi-frame image it won't hurt anyway + $this->image = $this->image->coalesceImages(); - /** - * setup the compression here, so we'll do it only once - */ - switch($this->getType()){ - case "image/png": - $quality = get_config('system','png_quality'); - if((! $quality) || ($quality > 9)) - $quality = PNG_QUALITY; - /** - * From http://www.imagemagick.org/script/command-line-options.php#quality: - * - * 'For the MNG and PNG image formats, the quality value sets - * the zlib compression level (quality / 10) and filter-type (quality % 10). - * The default PNG "quality" is 75, which means compression level 7 with adaptive PNG filtering, - * unless the image has a color map, in which case it means compression level 7 with no PNG filtering' - */ - $quality = $quality * 10; - $this->image->setCompressionQuality($quality); - break; - case "image/jpeg": - $quality = get_config('system','jpeg_quality'); - if((! $quality) || ($quality > 100)) - $quality = JPEG_QUALITY; - $this->image->setCompressionQuality($quality); - } + /* + * setup the compression here, so we'll do it only once + */ + switch($this->getType()){ + case "image/png": + $quality = get_config('system','png_quality'); + if ((! $quality) || ($quality > 9)) { + $quality = PNG_QUALITY; + } + /* + * From http://www.imagemagick.org/script/command-line-options.php#quality: + * + * 'For the MNG and PNG image formats, the quality value sets + * the zlib compression level (quality / 10) and filter-type (quality % 10). + * The default PNG "quality" is 75, which means compression level 7 with adaptive PNG filtering, + * unless the image has a color map, in which case it means compression level 7 with no PNG filtering' + */ + $quality = $quality * 10; + $this->image->setCompressionQuality($quality); + break; + case "image/jpeg": + $quality = get_config('system','jpeg_quality'); + if ((! $quality) || ($quality > 100)) { + $quality = JPEG_QUALITY; + } + $this->image->setCompressionQuality($quality); + } // The 'width' and 'height' properties are only used by non-Imagick routines. $this->width = $this->image->getImageWidth(); @@ -139,7 +147,7 @@ class Photo { $this->valid = false; $this->image = @imagecreatefromstring($data); - if($this->image !== FALSE) { + if ($this->image !== false) { $this->width = imagesx($this->image); $this->height = imagesy($this->image); $this->valid = true; @@ -148,123 +156,125 @@ class Photo { return true; } - + return false; } - public function is_valid() { - if($this->is_imagick()) - return ($this->image !== FALSE); - return $this->valid; - } - - public function getWidth() { - if(!$this->is_valid()) - return FALSE; - - if($this->is_imagick()) - return $this->image->getImageWidth(); - return $this->width; - } - - public function getHeight() { - if(!$this->is_valid()) - return FALSE; - - if($this->is_imagick()) - return $this->image->getImageHeight(); - return $this->height; - } - - public function getImage() { - if(!$this->is_valid()) - return FALSE; - - if($this->is_imagick()) { - /* Clean it */ - $this->image = $this->image->deconstructImages(); - return $this->image; + public function is_valid() { + if ($this->is_imagick()) { + return ($this->image !== false); + } + return $this->valid; } - return $this->image; - } - public function getType() { - if(!$this->is_valid()) - return FALSE; + public function getWidth() { + if (!$this->is_valid()) { + return false; + } - return $this->type; - } + if ($this->is_imagick()) { + return $this->image->getImageWidth(); + } + return $this->width; + } - public function getExt() { - if(!$this->is_valid()) - return FALSE; + public function getHeight() { + if (!$this->is_valid()) { + return false; + } - return $this->types[$this->getType()]; - } + if ($this->is_imagick()) { + return $this->image->getImageHeight(); + } + return $this->height; + } - public function scaleImage($max) { - if(!$this->is_valid()) - return FALSE; + public function getImage() { + if (!$this->is_valid()) { + return false; + } - $width = $this->getWidth(); - $height = $this->getHeight(); + if ($this->is_imagick()) { + /* Clean it */ + $this->image = $this->image->deconstructImages(); + return $this->image; + } + return $this->image; + } - $dest_width = $dest_height = 0; + public function getType() { + if (!$this->is_valid()) { + return false; + } - if((! $width)|| (! $height)) - return FALSE; + return $this->type; + } - if($width > $max && $height > $max) { + public function getExt() { + if (!$this->is_valid()) { + return false; + } + + return $this->types[$this->getType()]; + } + + public function scaleImage($max) { + if (!$this->is_valid()) { + return false; + } + + $width = $this->getWidth(); + $height = $this->getHeight(); + + $dest_width = $dest_height = 0; + + if ((! $width)|| (! $height)) { + return false; + } + + if ($width > $max && $height > $max) { // very tall image (greater than 16:9) // constrain the width - let the height float. - if((($height * 9) / 16) > $width) { + if ((($height * 9) / 16) > $width) { $dest_width = $max; - $dest_height = intval(( $height * $max ) / $width); + $dest_height = intval(( $height * $max ) / $width); + } elseif ($width > $height) { + // else constrain both dimensions + $dest_width = $max; + $dest_height = intval(( $height * $max ) / $width); + } else { + $dest_width = intval(( $width * $max ) / $height); + $dest_height = $max; } - - // else constrain both dimensions - - elseif($width > $height) { - $dest_width = $max; - $dest_height = intval(( $height * $max ) / $width); - } - else { - $dest_width = intval(( $width * $max ) / $height); - $dest_height = $max; - } - } - else { - if( $width > $max ) { - $dest_width = $max; - $dest_height = intval(( $height * $max ) / $width); - } - else { - if( $height > $max ) { + } else { + if ( $width > $max ) { + $dest_width = $max; + $dest_height = intval(( $height * $max ) / $width); + } else { + if ( $height > $max ) { // very tall image (greater than 16:9) // but width is OK - don't do anything - if((($height * 9) / 16) > $width) { + if ((($height * 9) / 16) > $width) { $dest_width = $width; - $dest_height = $height; - } - else { - $dest_width = intval(( $width * $max ) / $height); - $dest_height = $max; + $dest_height = $height; + } else { + $dest_width = intval(( $width * $max ) / $height); + $dest_height = $max; } + } else { + $dest_width = $width; + $dest_height = $height; + } + } } - else { - $dest_width = $width; - $dest_height = $height; - } - } - } - if($this->is_imagick()) { - /** + if ($this->is_imagick()) { + /* * If it is not animated, there will be only one iteration here, * so don't bother checking */ @@ -283,234 +293,253 @@ class Photo { $this->height = $this->image->getImageHeight(); return; - } - - - $dest = imagecreatetruecolor( $dest_width, $dest_height ); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); - if($this->image) - imagedestroy($this->image); - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - public function rotate($degrees) { - if(!$this->is_valid()) - return FALSE; - - if($this->is_imagick()) { - $this->image->setFirstIterator(); - do { - $this->image->rotateImage(new ImagickPixel(), -$degrees); // ImageMagick rotates in the opposite direction of imagerotate() - } while ($this->image->nextImage()); - return; - } - - $this->image = imagerotate($this->image,$degrees,0); - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - public function flip($horiz = true, $vert = false) { - if(!$this->is_valid()) - return FALSE; - - if($this->is_imagick()) { - $this->image->setFirstIterator(); - do { - if($horiz) $this->image->flipImage(); - if($vert) $this->image->flopImage(); - } while ($this->image->nextImage()); - return; - } - - $w = imagesx($this->image); - $h = imagesy($this->image); - $flipped = imagecreate($w, $h); - if($horiz) { - for ($x = 0; $x < $w; $x++) { - imagecopy($flipped, $this->image, $x, 0, $w - $x - 1, 0, 1, $h); - } - } - if($vert) { - for ($y = 0; $y < $h; $y++) { - imagecopy($flipped, $this->image, 0, $y, 0, $h - $y - 1, $w, 1); - } - } - $this->image = $flipped; - } - - public function orient($filename) { - if ($this->is_imagick()) { - // based off comment on http://php.net/manual/en/imagick.getimageorientation.php - $orientation = $this->image->getImageOrientation(); - switch ($orientation) { - case imagick::ORIENTATION_BOTTOMRIGHT: - $this->image->rotateimage("#000", 180); - break; - case imagick::ORIENTATION_RIGHTTOP: - $this->image->rotateimage("#000", 90); - break; - case imagick::ORIENTATION_LEFTBOTTOM: - $this->image->rotateimage("#000", -90); - break; } - $this->image->setImageOrientation(imagick::ORIENTATION_TOPLEFT); - return TRUE; - } - // based off comment on http://php.net/manual/en/function.imagerotate.php - if(!$this->is_valid()) - return FALSE; - - if( (! function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg') ) - return; - - $exif = @exif_read_data($filename,null,true); - if(! $exif) - return; - - $ort = $exif['IFD0']['Orientation']; - - switch($ort) - { - case 1: // nothing - break; - - case 2: // horizontal flip - $this->flip(); - break; - - case 3: // 180 rotate left - $this->rotate(180); - break; - - case 4: // vertical flip - $this->flip(false, true); - break; - - case 5: // vertical flip + 90 rotate right - $this->flip(false, true); - $this->rotate(-90); - break; - - case 6: // 90 rotate right - $this->rotate(-90); - break; - - case 7: // horizontal flip + 90 rotate right - $this->flip(); - $this->rotate(-90); - break; - - case 8: // 90 rotate left - $this->rotate(90); - break; - } - - // logger('exif: ' . print_r($exif,true)); - return $exif; - - } - - - - public function scaleImageUp($min) { - if(!$this->is_valid()) - return FALSE; - - - $width = $this->getWidth(); - $height = $this->getHeight(); - - $dest_width = $dest_height = 0; - - if((! $width)|| (! $height)) - return FALSE; - - if($width < $min && $height < $min) { - if($width > $height) { - $dest_width = $min; - $dest_height = intval(( $height * $min ) / $width); - } - else { - $dest_width = intval(( $width * $min ) / $height); - $dest_height = $min; - } - } - else { - if( $width < $min ) { - $dest_width = $min; - $dest_height = intval(( $height * $min ) / $width); - } - else { - if( $height < $min ) { - $dest_width = intval(( $width * $min ) / $height); - $dest_height = $min; + $dest = imagecreatetruecolor( $dest_width, $dest_height ); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha } - else { - $dest_width = $width; - $dest_height = $height; + imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); + if ($this->image) { + imagedestroy($this->image); } - } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); } - if($this->is_imagick()) - return $this->scaleImage($dest_width,$dest_height); + public function rotate($degrees) { + if (!$this->is_valid()) { + return false; + } - $dest = imagecreatetruecolor( $dest_width, $dest_height ); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); - if($this->image) - imagedestroy($this->image); - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } + if ($this->is_imagick()) { + $this->image->setFirstIterator(); + do { + $this->image->rotateImage(new ImagickPixel(), -$degrees); // ImageMagick rotates in the opposite direction of imagerotate() + } while ($this->image->nextImage()); + return; + } - - - public function scaleImageSquare($dim) { - if(!$this->is_valid()) - return FALSE; - - if($this->is_imagick()) { - $this->image->setFirstIterator(); - do { - $this->image->scaleImage($dim, $dim); - } while ($this->image->nextImage()); - return; + $this->image = imagerotate($this->image,$degrees,0); + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); } - $dest = imagecreatetruecolor( $dim, $dim ); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dim, $dim, $this->width, $this->height); - if($this->image) - imagedestroy($this->image); - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } + public function flip($horiz = true, $vert = false) { + if (!$this->is_valid()) { + return false; + } + + if ($this->is_imagick()) { + $this->image->setFirstIterator(); + do { + if ($horiz) { + $this->image->flipImage(); + } + if ($vert) { + $this->image->flopImage(); + } + } while ($this->image->nextImage()); + return; + } + + $w = imagesx($this->image); + $h = imagesy($this->image); + $flipped = imagecreate($w, $h); + if ($horiz) { + for ($x = 0; $x < $w; $x++) { + imagecopy($flipped, $this->image, $x, 0, $w - $x - 1, 0, 1, $h); + } + } + if ($vert) { + for ($y = 0; $y < $h; $y++) { + imagecopy($flipped, $this->image, 0, $y, 0, $h - $y - 1, $w, 1); + } + } + $this->image = $flipped; + } + + public function orient($filename) { + if ($this->is_imagick()) { + // based off comment on http://php.net/manual/en/imagick.getimageorientation.php + $orientation = $this->image->getImageOrientation(); + switch ($orientation) { + case imagick::ORIENTATION_BOTTOMRIGHT: + $this->image->rotateimage("#000", 180); + break; + case imagick::ORIENTATION_RIGHTTOP: + $this->image->rotateimage("#000", 90); + break; + case imagick::ORIENTATION_LEFTBOTTOM: + $this->image->rotateimage("#000", -90); + break; + } + + $this->image->setImageOrientation(imagick::ORIENTATION_TOPLEFT); + return true; + } + // based off comment on http://php.net/manual/en/function.imagerotate.php + + if (!$this->is_valid()) { + return false; + } + + if ( (! function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg') ) { + return; + } + + $exif = @exif_read_data($filename,null,true); + if (! $exif) { + return; + } + + $ort = $exif['IFD0']['Orientation']; + + switch($ort) + { + case 1: // nothing + break; + + case 2: // horizontal flip + $this->flip(); + break; + + case 3: // 180 rotate left + $this->rotate(180); + break; + + case 4: // vertical flip + $this->flip(false, true); + break; + + case 5: // vertical flip + 90 rotate right + $this->flip(false, true); + $this->rotate(-90); + break; + + case 6: // 90 rotate right + $this->rotate(-90); + break; + + case 7: // horizontal flip + 90 rotate right + $this->flip(); + $this->rotate(-90); + break; + + case 8: // 90 rotate left + $this->rotate(90); + break; + } + + // logger('exif: ' . print_r($exif,true)); + return $exif; + + } - public function cropImage($max,$x,$y,$w,$h) { - if(!$this->is_valid()) - return FALSE; - if($this->is_imagick()) { + public function scaleImageUp($min) { + if (!$this->is_valid()) { + return false; + } + + + $width = $this->getWidth(); + $height = $this->getHeight(); + + $dest_width = $dest_height = 0; + + if ((! $width)|| (! $height)) { + return false; + } + + if ($width < $min && $height < $min) { + if ($width > $height) { + $dest_width = $min; + $dest_height = intval(( $height * $min ) / $width); + } else { + $dest_width = intval(( $width * $min ) / $height); + $dest_height = $min; + } + } else { + if ( $width < $min ) { + $dest_width = $min; + $dest_height = intval(( $height * $min ) / $width); + } else { + if ( $height < $min ) { + $dest_width = intval(( $width * $min ) / $height); + $dest_height = $min; + } else { + $dest_width = $width; + $dest_height = $height; + } + } + } + + if ($this->is_imagick()) { + return $this->scaleImage($dest_width,$dest_height); + } + + $dest = imagecreatetruecolor( $dest_width, $dest_height ); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + } + imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); + if ($this->image) { + imagedestroy($this->image); + } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + + + public function scaleImageSquare($dim) { + if (!$this->is_valid()) { + return false; + } + + if ($this->is_imagick()) { + $this->image->setFirstIterator(); + do { + $this->image->scaleImage($dim, $dim); + } while ($this->image->nextImage()); + return; + } + + $dest = imagecreatetruecolor( $dim, $dim ); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + } + imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dim, $dim, $this->width, $this->height); + if ($this->image) { + imagedestroy($this->image); + } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + + public function cropImage($max,$x,$y,$w,$h) { + if (!$this->is_valid()) { + return false; + } + + if ($this->is_imagick()) { $this->image->setFirstIterator(); do { $this->image->cropImage($w, $h, $x, $y); - /** + /* * We need to remove the canva, * or the image is not resized to the crop: * http://php.net/manual/en/imagick.cropimage.php#97232 @@ -520,165 +549,172 @@ class Photo { return $this->scaleImage($max); } - $dest = imagecreatetruecolor( $max, $max ); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); - if($this->image) - imagedestroy($this->image); - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - public function saveImage($path) { - if(!$this->is_valid()) - return FALSE; - - $string = $this->imageString(); - - $a = get_app(); - - $stamp1 = microtime(true); - file_put_contents($path, $string); - $a->save_timestamp($stamp1, "file"); - } - - public function imageString() { - if(!$this->is_valid()) - return FALSE; - - if($this->is_imagick()) { - /* Clean it */ - $this->image = $this->image->deconstructImages(); - $string = $this->image->getImagesBlob(); - return $string; + $dest = imagecreatetruecolor( $max, $max ); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + } + imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); + if ($this->image) { + imagedestroy($this->image); + } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); } - $quality = FALSE; + public function saveImage($path) { + if (!$this->is_valid()) { + return false; + } - ob_start(); + $string = $this->imageString(); - // Enable interlacing - imageinterlace($this->image, true); + $a = get_app(); - switch($this->getType()){ - case "image/png": - $quality = get_config('system','png_quality'); - if((! $quality) || ($quality > 9)) - $quality = PNG_QUALITY; - imagepng($this->image,NULL, $quality); - break; - case "image/jpeg": - $quality = get_config('system','jpeg_quality'); - if((! $quality) || ($quality > 100)) - $quality = JPEG_QUALITY; - imagejpeg($this->image,NULL,$quality); + $stamp1 = microtime(true); + file_put_contents($path, $string); + $a->save_timestamp($stamp1, "file"); } - $string = ob_get_contents(); - ob_end_clean(); - return $string; - } + public function imageString() { + if (!$this->is_valid()) { + return false; + } + + if ($this->is_imagick()) { + /* Clean it */ + $this->image = $this->image->deconstructImages(); + $string = $this->image->getImagesBlob(); + return $string; + } + + $quality = FALSE; + + ob_start(); + + // Enable interlacing + imageinterlace($this->image, true); + + switch($this->getType()){ + case "image/png": + $quality = get_config('system','png_quality'); + if ((! $quality) || ($quality > 9)) { + $quality = PNG_QUALITY; + } + imagepng($this->image,NULL, $quality); + break; + case "image/jpeg": + $quality = get_config('system','jpeg_quality'); + if ((! $quality) || ($quality > 100)) { + $quality = JPEG_QUALITY; + } + imagejpeg($this->image,NULL,$quality); + } + $string = ob_get_contents(); + ob_end_clean(); + + return $string; + } - public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '') { + public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '') { - $r = q("select `guid` from photo where `resource-id` = '%s' and `guid` != '' limit 1", - dbesc($rid) - ); - if(count($r)) - $guid = $r[0]['guid']; - else - $guid = get_guid(); + $r = q("SELECT `guid` FROM `photo` WHERE `resource-id` = '%s' AND `guid` != '' LIMIT 1", + dbesc($rid) + ); + if (dbm::is_result($r)) { + $guid = $r[0]['guid']; + } else { + $guid = get_guid(); + } - $x = q("select id from photo where `resource-id` = '%s' and uid = %d and `contact-id` = %d and `scale` = %d limit 1", - dbesc($rid), - intval($uid), - intval($cid), - intval($scale) - ); - if(count($x)) { - $r = q("UPDATE `photo` - set `uid` = %d, - `contact-id` = %d, - `guid` = '%s', - `resource-id` = '%s', - `created` = '%s', - `edited` = '%s', - `filename` = '%s', - `type` = '%s', - `album` = '%s', - `height` = %d, - `width` = %d, + $x = q("SELECT `id` FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d AND `contact-id` = %d AND `scale` = %d LIMIT 1", + dbesc($rid), + intval($uid), + intval($cid), + intval($scale) + ); + if (dbm::is_result($x)) { + $r = q("UPDATE `photo` + SET `uid` = %d, + `contact-id` = %d, + `guid` = '%s', + `resource-id` = '%s', + `created` = '%s', + `edited` = '%s', + `filename` = '%s', + `type` = '%s', + `album` = '%s', + `height` = %d, + `width` = %d, `datasize` = %d, - `data` = '%s', - `scale` = %d, - `profile` = %d, - `allow_cid` = '%s', - `allow_gid` = '%s', - `deny_cid` = '%s', - `deny_gid` = '%s' - where id = %d", + `data` = '%s', + `scale` = %d, + `profile` = %d, + `allow_cid` = '%s', + `allow_gid` = '%s', + `deny_cid` = '%s', + `deny_gid` = '%s' + WHERE `id` = %d", - intval($uid), - intval($cid), - dbesc($guid), - dbesc($rid), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc(basename($filename)), - dbesc($this->getType()), - dbesc($album), - intval($this->getHeight()), - intval($this->getWidth()), + intval($uid), + intval($cid), + dbesc($guid), + dbesc($rid), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(basename($filename)), + dbesc($this->getType()), + dbesc($album), + intval($this->getHeight()), + intval($this->getWidth()), dbesc(strlen($this->imageString())), - dbesc($this->imageString()), - intval($scale), - intval($profile), - dbesc($allow_cid), - dbesc($allow_gid), - dbesc($deny_cid), - dbesc($deny_gid), - intval($x[0]['id']) - ); - } - else { - $r = q("INSERT INTO `photo` - ( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `datasize`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` ) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s' )", - intval($uid), - intval($cid), - dbesc($guid), - dbesc($rid), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc(basename($filename)), - dbesc($this->getType()), - dbesc($album), - intval($this->getHeight()), - intval($this->getWidth()), + dbesc($this->imageString()), + intval($scale), + intval($profile), + dbesc($allow_cid), + dbesc($allow_gid), + dbesc($deny_cid), + dbesc($deny_gid), + intval($x[0]['id']) + ); + } else { + $r = q("INSERT INTO `photo` + ( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `datasize`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` ) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s' )", + intval($uid), + intval($cid), + dbesc($guid), + dbesc($rid), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(basename($filename)), + dbesc($this->getType()), + dbesc($album), + intval($this->getHeight()), + intval($this->getWidth()), dbesc(strlen($this->imageString())), - dbesc($this->imageString()), - intval($scale), - intval($profile), - dbesc($allow_cid), - dbesc($allow_gid), - dbesc($deny_cid), - dbesc($deny_gid) - ); - } + dbesc($this->imageString()), + intval($scale), + intval($profile), + dbesc($allow_cid), + dbesc($allow_gid), + dbesc($deny_cid), + dbesc($deny_gid) + ); + } - // Update the cached values - if ($album != 'Contact Photos') { - photo_albums($uid, true); - } + // Update the cached values + if ($album != 'Contact Photos') { + photo_albums($uid, true); + } - return $r; - } -}} + return $r; + } +} /** @@ -688,41 +724,43 @@ class Photo { * @arg $fromcurl boolean Check Content-Type header from curl request */ function guess_image_type($filename, $fromcurl=false) { - logger('Photo: guess_image_type: '.$filename . ($fromcurl?' from curl headers':''), LOGGER_DEBUG); - $type = null; - if ($fromcurl) { - $a = get_app(); - $headers=array(); - $h = explode("\n",$a->get_curl_headers()); - foreach ($h as $l) { - list($k,$v) = array_map("trim", explode(":", trim($l), 2)); - $headers[$k] = $v; + logger('Photo: guess_image_type: '.$filename . ($fromcurl?' from curl headers':''), LOGGER_DEBUG); + $type = null; + if ($fromcurl) { + $a = get_app(); + $headers=array(); + $h = explode("\n",$a->get_curl_headers()); + foreach ($h as $l) { + list($k,$v) = array_map("trim", explode(":", trim($l), 2)); + $headers[$k] = $v; + } + if (array_key_exists('Content-Type', $headers)) + $type = $headers['Content-Type']; } - if (array_key_exists('Content-Type', $headers)) - $type = $headers['Content-Type']; - } - if (is_null($type)){ - // Guessing from extension? Isn't that... dangerous? - if(class_exists('Imagick') && file_exists($filename) && is_readable($filename)) { - /** - * Well, this not much better, - * but at least it comes from the data inside the image, - * we won't be tricked by a manipulated extension - */ - $image = new Imagick($filename); - $type = $image->getImageMimeType(); - $image->setInterlaceScheme(Imagick::INTERLACE_PLANE); - } else { - $ext = pathinfo($filename, PATHINFO_EXTENSION); - $types = Photo::supportedTypes(); - $type = "image/jpeg"; - foreach ($types as $m=>$e){ - if ($ext==$e) $type = $m; - } + if (is_null($type)){ + // Guessing from extension? Isn't that... dangerous? + if (class_exists('Imagick') && file_exists($filename) && is_readable($filename)) { + /** + * Well, this not much better, + * but at least it comes from the data inside the image, + * we won't be tricked by a manipulated extension + */ + $image = new Imagick($filename); + $type = $image->getImageMimeType(); + $image->setInterlaceScheme(Imagick::INTERLACE_PLANE); + } else { + $ext = pathinfo($filename, PATHINFO_EXTENSION); + $types = Photo::supportedTypes(); + $type = "image/jpeg"; + foreach ($types as $m=>$e){ + if ($ext==$e) { + $type = $m; + } + } + } } - } - logger('Photo: guess_image_type: type='.$type, LOGGER_DEBUG); - return $type; + logger('Photo: guess_image_type: type='.$type, LOGGER_DEBUG); + return $type; } @@ -739,10 +777,11 @@ function guess_image_type($filename, $fromcurl=false) { function update_contact_avatar($avatar,$uid,$cid, $force = false) { $r = q("SELECT `avatar`, `photo`, `thumb`, `micro` FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid)); - if (!$r) + if (!dbm::is_result($r)) { return false; - else + } else { $data = array($r[0]["photo"], $r[0]["thumb"], $r[0]["micro"]); + } if (($r[0]["avatar"] != $avatar) OR $force) { $photos = import_profile_photo($avatar,$uid,$cid, true); @@ -762,59 +801,63 @@ function import_profile_photo($photo,$uid,$cid, $quit_on_error = false) { $a = get_app(); - $r = q("select `resource-id` from photo where `uid` = %d and `contact-id` = %d and `scale` = 4 and `album` = 'Contact Photos' limit 1", + $r = q("SELECT `resource-id` FROM `photo` WHERE `uid` = %d AND `contact-id` = %d AND `scale` = 4 AND `album` = 'Contact Photos' LIMIT 1", intval($uid), intval($cid) ); - if(count($r) && strlen($r[0]['resource-id'])) { + if (dbm::is_result($r) && strlen($r[0]['resource-id'])) { $hash = $r[0]['resource-id']; } else { $hash = photo_new_resource(); - } + } $photo_failure = false; $filename = basename($photo); $img_str = fetch_url($photo,true); - if ($quit_on_error AND ($img_str == "")) + if ($quit_on_error AND ($img_str == "")) { return false; + } $type = guess_image_type($photo,true); $img = new Photo($img_str, $type); - if($img->is_valid()) { + if ($img->is_valid()) { $img->scaleImageSquare(175); $r = $img->store($uid, $cid, $hash, $filename, 'Contact Photos', 4 ); - if($r === false) + if ($r === false) $photo_failure = true; $img->scaleImage(80); $r = $img->store($uid, $cid, $hash, $filename, 'Contact Photos', 5 ); - if($r === false) + if ($r === false) $photo_failure = true; $img->scaleImage(48); $r = $img->store($uid, $cid, $hash, $filename, 'Contact Photos', 6 ); - if($r === false) + if ($r === false) { $photo_failure = true; + } $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.' . $img->getExt(); $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.' . $img->getExt(); $micro = $a->get_baseurl() . '/photo/' . $hash . '-6.' . $img->getExt(); - } else + } else { $photo_failure = true; + } - if($photo_failure AND $quit_on_error) + if ($photo_failure AND $quit_on_error) { return false; + } - if($photo_failure) { + if ($photo_failure) { $photo = $a->get_baseurl() . '/images/person-175.jpg'; $thumb = $a->get_baseurl() . '/images/person-80.jpg'; $micro = $a->get_baseurl() . '/images/person-48.jpg'; @@ -829,17 +872,13 @@ function get_photo_info($url) { $data = Cache::get($url); - // Unserialise to be able to check in the next step if the cached data is alright. - if (!is_null($data)) - $data = unserialize($data); - if (is_null($data) OR !$data) { $img_str = fetch_url($url, true, $redirects, 4); $filesize = strlen($img_str); - if (function_exists("getimagesizefromstring")) + if (function_exists("getimagesizefromstring")) { $data = getimagesizefromstring($img_str); - else { + } else { $tempfile = tempnam(get_temppath(), "cache"); $a = get_app(); @@ -851,10 +890,11 @@ function get_photo_info($url) { unlink($tempfile); } - if ($data) + if ($data) { $data["size"] = $filesize; + } - Cache::set($url, serialize($data)); + Cache::set($url, $data); } return $data; @@ -864,36 +904,37 @@ function scale_image($width, $height, $max) { $dest_width = $dest_height = 0; - if((!$width) || (!$height)) - return FALSE; + if ((!$width) || (!$height)) { + return false; + } - if($width > $max && $height > $max) { + if ($width > $max && $height > $max) { // very tall image (greater than 16:9) // constrain the width - let the height float. - if((($height * 9) / 16) > $width) { + if ((($height * 9) / 16) > $width) { $dest_width = $max; $dest_height = intval(( $height * $max ) / $width); - } elseif($width > $height) { + } elseif ($width > $height) { // else constrain both dimensions $dest_width = $max; $dest_height = intval(( $height * $max ) / $width); - } else { + } else { $dest_width = intval(( $width * $max ) / $height); $dest_height = $max; } } else { - if( $width > $max ) { + if ( $width > $max ) { $dest_width = $max; $dest_height = intval(( $height * $max ) / $width); - } else { - if( $height > $max ) { + } else { + if ( $height > $max ) { // very tall image (greater than 16:9) // but width is OK - don't do anything - if((($height * 9) / 16) > $width) { + if ((($height * 9) / 16) > $width) { $dest_width = $width; $dest_height = $height; } else { @@ -911,10 +952,10 @@ function scale_image($width, $height, $max) { function store_photo($a, $uid, $imagedata = "", $url = "") { $r = q("SELECT `user`.`nickname`, `user`.`page-flags`, `contact`.`id` FROM `user` INNER JOIN `contact` on `user`.`uid` = `contact`.`uid` - WHERE `user`.`uid` = %d AND `user`.`blocked` = 0 and `contact`.`self` = 1 LIMIT 1", + WHERE `user`.`uid` = %d AND `user`.`blocked` = 0 AND `contact`.`self` = 1 LIMIT 1", intval($uid)); - if(!count($r)) { + if (!dbm::is_result($r)) { logger("Can't detect user data for uid ".$uid, LOGGER_DEBUG); return(array()); } @@ -938,22 +979,22 @@ function store_photo($a, $uid, $imagedata = "", $url = "") { $maximagesize = get_config('system','maximagesize'); - if(($maximagesize) && (strlen($imagedata) > $maximagesize)) { + if (($maximagesize) && (strlen($imagedata) > $maximagesize)) { logger("Image exceeds size limit of ".$maximagesize, LOGGER_DEBUG); return(array()); - } + } /* - $r = q("select sum(octet_length(data)) as total from photo where uid = %d and scale = 0 and album != 'Contact Photos' ", - intval($uid) - ); + $r = q("select sum(octet_length(data)) as total from photo where uid = %d and scale = 0 and album != 'Contact Photos' ", + intval($uid) + ); - $limit = service_class_fetch($uid,'photo_upload_limit'); + $limit = service_class_fetch($uid,'photo_upload_limit'); - if(($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) { + if (($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) { logger("Image exceeds personal limit of uid ".$uid, LOGGER_DEBUG); return(array()); - } + } */ $tempfile = tempnam(get_temppath(), "cache"); @@ -972,7 +1013,7 @@ function store_photo($a, $uid, $imagedata = "", $url = "") { $ph = new Photo($imagedata, $data["mime"]); - if(!$ph->is_valid()) { + if (!$ph->is_valid()) { unlink($tempfile); logger("Picture is no valid picture", LOGGER_DEBUG); return(array()); @@ -982,10 +1023,12 @@ function store_photo($a, $uid, $imagedata = "", $url = "") { unlink($tempfile); $max_length = get_config('system','max_image_length'); - if(! $max_length) + if (! $max_length) { $max_length = MAX_IMAGE_LENGTH; - if($max_length > 0) + } + if ($max_length > 0) { $ph->scaleImage($max_length); + } $width = $ph->getWidth(); $height = $ph->getHeight(); @@ -1001,7 +1044,7 @@ function store_photo($a, $uid, $imagedata = "", $url = "") { $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 0, 0, $defperm); - if(!$r) { + if (!$r) { logger("Picture couldn't be stored", LOGGER_DEBUG); return(array()); } @@ -1009,43 +1052,49 @@ function store_photo($a, $uid, $imagedata = "", $url = "") { $image = array("page" => $a->get_baseurl().'/photos/'.$page_owner_nick.'/image/'.$hash, "full" => $a->get_baseurl()."/photo/{$hash}-0.".$ph->getExt()); - if($width > 800 || $height > 800) + if ($width > 800 || $height > 800) { $image["large"] = $a->get_baseurl()."/photo/{$hash}-0.".$ph->getExt(); + } - if($width > 640 || $height > 640) { + if ($width > 640 || $height > 640) { $ph->scaleImage(640); $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 1, 0, $defperm); - if($r) + if ($r) { $image["medium"] = $a->get_baseurl()."/photo/{$hash}-1.".$ph->getExt(); + } } - if($width > 320 || $height > 320) { + if ($width > 320 || $height > 320) { $ph->scaleImage(320); $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 2, 0, $defperm); - if($r) + if ($r) { $image["small"] = $a->get_baseurl()."/photo/{$hash}-2.".$ph->getExt(); + } } - if($width > 160 AND $height > 160) { + if ($width > 160 AND $height > 160) { $x = 0; $y = 0; $min = $ph->getWidth(); - if ($min > 160) + if ($min > 160) { $x = ($min - 160) / 2; + } if ($ph->getHeight() < $min) { $min = $ph->getHeight(); - if ($min > 160) + if ($min > 160) { $y = ($min - 160) / 2; + } } $min = 160; $ph->cropImage(160, $x, $y, $min, $min); $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 3, 0, $defperm); - if($r) + if ($r) { $image["thumb"] = $a->get_baseurl()."/photo/{$hash}-3.".$ph->getExt(); + } } // Set the full image as preview image. This will be overwritten, if the picture is larger than 640. @@ -1059,39 +1108,9 @@ function store_photo($a, $uid, $imagedata = "", $url = "") { //if (isset($image["small"])) // $image["preview"] = $image["small"]; - if (isset($image["medium"])) + if (isset($image["medium"])) { $image["preview"] = $image["medium"]; + } return($image); } - -/** - * @brief Fetch the photo albums that are available for a viewer - * - * The query in this function is cost intensive, so it is cached. - * - * @param int $uid User id of the photos - * @param bool $update Update the cache - * - * @return array Returns array of the photo albums - */ -function photo_albums($uid, $update = false) { - $sql_extra = permissions_sql($uid); - - $key = "photo_albums:".$uid.":".local_user().":".remote_user(); - $albums = Cache::get($key); - if (is_null($albums) OR $update) { - /// @todo This query needs to be renewed. It is really slow - // At this time we just store the data in the cache - $albums = qu("SELECT COUNT(DISTINCT `resource-id`) AS `total`, `album` - FROM `photo` USE INDEX (`uid_album_created`) - WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' $sql_extra - GROUP BY `album` ORDER BY `created` DESC", - intval($uid), - dbesc('Contact Photos'), - dbesc(t('Contact Photos')) - ); - Cache::set($key, $albums, CACHE_DAY); - } - return $albums; -} diff --git a/include/Probe.php b/include/Probe.php index d266a384e6..aa9f7d21df 100644 --- a/include/Probe.php +++ b/include/Probe.php @@ -217,7 +217,6 @@ class Probe { if ($cache) { $result = Cache::get("probe_url:".$network.":".$uri); if (!is_null($result)) { - $result = unserialize($result); return $result; } } @@ -257,7 +256,7 @@ class Probe { // Only store into the cache if the value seems to be valid if (!in_array($data['network'], array(NETWORK_PHANTOM, NETWORK_MAIL))) { - Cache::set("probe_url:".$network.":".$uri,serialize($data), CACHE_DAY); + Cache::set("probe_url:".$network.":".$uri, $data, CACHE_DAY); /// @todo temporary fix - we need a real contact update function that updates only changing fields /// The biggest problem is the avatar picture that could have a reduced image size. diff --git a/include/cache.php b/include/cache.php index 45938dddf8..b8016ac457 100644 --- a/include/cache.php +++ b/include/cache.php @@ -99,8 +99,8 @@ class Cache { dbesc($key) ); - if (count($r)) { - return $r[0]['v']; + if (dbm::is_result($r)) { + return unserialize($r[0]['v']); } return null; @@ -108,7 +108,9 @@ class Cache { /** * @brief Put data in the cache according to the key - * + * + * The input $value can have multiple formats. + * * @param string $key The key to the cached data * @param mixed $valie The value that is about to be stored * @param integer $duration The cache lifespan @@ -126,7 +128,7 @@ class Cache { /// @todo store the cache data in the same way like the config data q("REPLACE INTO `cache` (`k`,`v`,`expire_mode`,`updated`) VALUES ('%s','%s',%d,'%s')", dbesc($key), - dbesc($value), + dbesc(serialize($value)), intval($duration), dbesc(datetime_convert())); } diff --git a/include/cron.php b/include/cron.php index c03745a442..2c27e9f992 100644 --- a/include/cron.php +++ b/include/cron.php @@ -11,6 +11,7 @@ if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) { } require_once("boot.php"); +require_once("include/photos.php"); function cron_run(&$argv, &$argc){ @@ -162,8 +163,9 @@ function cron_run(&$argv, &$argc){ */ function cron_update_photo_albums() { $r = q("SELECT `uid` FROM `user` WHERE NOT `account_expired` AND NOT `account_removed`"); - if (!dbm::is_result($r)) + if (!dbm::is_result($r)) { return; + } foreach ($r AS $user) { photo_albums($user['uid'], true); diff --git a/include/gprobe.php b/include/gprobe.php index 91b9b16e33..2785475341 100644 --- a/include/gprobe.php +++ b/include/gprobe.php @@ -12,11 +12,11 @@ function gprobe_run(&$argv, &$argc){ } if(is_null($db)) { - @include(".htconfig.php"); - require_once("include/dba.php"); - $db = new dba($db_host, $db_user, $db_pass, $db_data); - unset($db_host, $db_user, $db_pass, $db_data); - }; + @include(".htconfig.php"); + require_once("include/dba.php"); + $db = new dba($db_host, $db_user, $db_pass, $db_data); + unset($db_host, $db_user, $db_pass, $db_data); + }; require_once('include/session.php'); require_once('include/datetime.php'); @@ -39,14 +39,13 @@ function gprobe_run(&$argv, &$argc){ logger("gprobe start for ".normalise_link($url), LOGGER_DEBUG); - if (!count($r)) { + if (!dbm::is_result($r)) { // Is it a DDoS attempt? $urlparts = parse_url($url); $result = Cache::get("gprobe:".$urlparts["host"]); if (!is_null($result)) { - $result = unserialize($result); if (in_array($result["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) { logger("DDoS attempt detected for ".$urlparts["host"]." by ".$_SERVER["REMOTE_ADDR"].". server data: ".print_r($_SERVER, true), LOGGER_DEBUG); return; @@ -56,7 +55,7 @@ function gprobe_run(&$argv, &$argc){ $arr = probe_url($url); if (is_null($result)) - Cache::set("gprobe:".$urlparts["host"],serialize($arr)); + Cache::set("gprobe:".$urlparts["host"], $arr); if (!in_array($arr["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) update_gcontact($arr); @@ -65,7 +64,7 @@ function gprobe_run(&$argv, &$argc){ dbesc(normalise_link($url)) ); } - if(count($r)) { + if(dbm::is_result($r)) { // Check for accessibility and do a poco discovery if (poco_last_updated($r[0]['url'], true) AND ($r[0]["network"] == NETWORK_DFRN)) poco_load(0,0,$r[0]['id'], str_replace('/profile/','/poco/',$r[0]['url'])); @@ -76,6 +75,6 @@ function gprobe_run(&$argv, &$argc){ } if (array_search(__file__,get_included_files())===0){ - gprobe_run($_SERVER["argv"],$_SERVER["argc"]); - killme(); + gprobe_run($_SERVER["argv"],$_SERVER["argc"]); + killme(); } diff --git a/include/oembed.php b/include/oembed.php index 898d900f43..be6c298e8d 100755 --- a/include/oembed.php +++ b/include/oembed.php @@ -6,7 +6,15 @@ function oembed_replacecb($matches){ return $s; } - +/** + * @brief Get data from an URL to embed its content. + * + * @param string $embedurl The URL from which the data should be fetched. + * @param bool $no_rich_type If set to true rich type content won't be fetched. + * + * @return bool|object Returns object with embed content or false if no embedable + * content exists + */ function oembed_fetch_url($embedurl, $no_rich_type = false){ $embedurl = trim($embedurl, "'"); $embedurl = trim($embedurl, '"'); @@ -16,11 +24,11 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){ $r = q("SELECT * FROM `oembed` WHERE `url` = '%s'", dbesc(normalise_link($embedurl))); - if ($r) + if (dbm::is_result($r)) { $txt = $r[0]["content"]; - else + } else { $txt = Cache::get($a->videowidth . $embedurl); - + } // These media files should now be caught in bbcode.php // left here as a fallback in case this is called from another source @@ -28,27 +36,27 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){ $ext = pathinfo(strtolower($embedurl),PATHINFO_EXTENSION); - if(is_null($txt)){ + if (is_null($txt)) { $txt = ""; if (!in_array($ext, $noexts)){ // try oembed autodiscovery $redirects = 0; - $html_text = fetch_url($embedurl, false, $redirects, 15, "text/*"); /**/ - if($html_text){ + $html_text = fetch_url($embedurl, false, $redirects, 15, "text/*"); + if ($html_text) { $dom = @DOMDocument::loadHTML($html_text); - if ($dom){ + if ($dom) { $xpath = new DOMXPath($dom); $attr = "oembed"; $xattr = oe_build_xpath("class","oembed"); $entries = $xpath->query("//link[@type='application/json+oembed']"); - foreach($entries as $e){ + foreach ($entries as $e) { $href = $e->getAttributeNode("href")->nodeValue; $txt = fetch_url($href . '&maxwidth=' . $a->videowidth); break; } $entries = $xpath->query("//link[@type='text/json+oembed']"); - foreach($entries as $e){ + foreach ($entries as $e) { $href = $e->getAttributeNode("href")->nodeValue; $txt = fetch_url($href . '&maxwidth=' . $a->videowidth); break; @@ -57,7 +65,7 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){ } } - if ($txt==false || $txt==""){ + if ($txt==false || $txt=="") { $embedly = get_config("system", "embedly"); if ($embedly != "") { // try embedly service @@ -70,30 +78,33 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){ $txt=trim($txt); - if ($txt[0]!="{") + if ($txt[0]!="{") { $txt='{"type":"error"}'; - else { //save in cache + } else { //save in cache $j = json_decode($txt); - if ($j->type != "error") + if ($j->type != "error") { q("INSERT INTO `oembed` (`url`, `content`, `created`) VALUES ('%s', '%s', '%s') ON DUPLICATE KEY UPDATE `content` = '%s', `created` = '%s'", dbesc(normalise_link($embedurl)), dbesc($txt), dbesc(datetime_convert()), dbesc($txt), dbesc(datetime_convert())); + } - Cache::set($a->videowidth.$embedurl,$txt, CACHE_DAY); + Cache::set($a->videowidth.$embedurl, $txt, CACHE_DAY); } } $j = json_decode($txt); - if (!is_object($j)) + if (!is_object($j)) { return false; + } // Always embed the SSL version - if (isset($j->html)) + if (isset($j->html)) { $j->html = str_replace(array("http://www.youtube.com/", "http://player.vimeo.com/"), array("https://www.youtube.com/", "https://player.vimeo.com/"), $j->html); + } $j->embedurl = $embedurl; @@ -109,16 +120,18 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){ //$j->height = $data["images"][0]["height"]; } - if (isset($data["title"])) - $j->title = $data["title"]; + if (isset($data["title"])) { + $j->title = $data["title"]; + } - if (isset($data["text"])) - $j->description = $data["text"]; + if (isset($data["text"])) { + $j->description = $data["text"]; + } if (is_array($data["images"])) { - $j->thumbnail_url = $data["images"][0]["src"]; - $j->thumbnail_width = $data["images"][0]["width"]; - $j->thumbnail_height = $data["images"][0]["height"]; + $j->thumbnail_url = $data["images"][0]["src"]; + $j->thumbnail_width = $data["images"][0]["width"]; + $j->thumbnail_height = $data["images"][0]["height"]; } } diff --git a/include/photos.php b/include/photos.php index 93a565b511..2beb23ffaf 100644 --- a/include/photos.php +++ b/include/photos.php @@ -25,3 +25,34 @@ function gps2Num($coordPart) { return floatval($parts[0]) / floatval($parts[1]); } + +/** + * @brief Fetch the photo albums that are available for a viewer + * + * The query in this function is cost intensive, so it is cached. + * + * @param int $uid User id of the photos + * @param bool $update Update the cache + * + * @return array Returns array of the photo albums + */ +function photo_albums($uid, $update = false) { + $sql_extra = permissions_sql($uid); + + $key = "photo_albums:".$uid.":".local_user().":".remote_user(); + $albums = Cache::get($key); + if (is_null($albums) OR $update) { + /// @todo This query needs to be renewed. It is really slow + // At this time we just store the data in the cache + $albums = qu("SELECT COUNT(DISTINCT `resource-id`) AS `total`, `album` + FROM `photo` USE INDEX (`uid_album_created`) + WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' $sql_extra + GROUP BY `album` ORDER BY `created` DESC", + intval($uid), + dbesc('Contact Photos'), + dbesc(t('Contact Photos')) + ); + Cache::set($key, $albums, CACHE_DAY); + } + return $albums; +} diff --git a/mod/photos.php b/mod/photos.php index edaba5a902..1730a9b60c 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -21,8 +21,6 @@ function photos_init(&$a) { nav_set_selected('home'); - $o = ''; - if ($a->argc > 1) { $nick = $a->argv[1]; $user = qu("SELECT * FROM `user` WHERE `nickname` = '%s' AND `blocked` = 0 LIMIT 1",