From 8e68d650a1aeb8eb5a4e2c95cbfa5ba3d0dc4830 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sat, 3 Sep 2011 16:03:21 -0400 Subject: [PATCH 02/20] Cleaned up how the Image Replace html is made. --- ext/image/main.php | 8 ++++++++ ext/image/theme.php | 29 ++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/ext/image/main.php b/ext/image/main.php index 1908d6f5..c448d0e7 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -200,12 +200,20 @@ class ImageIO extends SimpleExtension { } public function onUserPageBuilding($event) { + global $user; + global $config; + $u_id = url_escape($event->display_user->id); $i_image_count = Image::count_images(array("user_id={$event->display_user->id}")); $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; $h_image_rate = sprintf("%.1f", ($i_image_count / $i_days_old)); $images_link = make_link("post/list/user_id=$u_id/1"); $event->add_stats("Images uploaded: $i_image_count, $h_image_rate per day"); + + /* In the future, could perhaps allow users to replace images that they own as well... */ + if ($user->is_admin() && $config->get_bool("upload_replace")) { + $event->add_part($this->theme->get_replace_html($event->image->id)); + } } public function onSetupBuilding($event) { diff --git a/ext/image/theme.php b/ext/image/theme.php index 516a045d..3004bd5d 100644 --- a/ext/image/theme.php +++ b/ext/image/theme.php @@ -1,41 +1,44 @@ get_bool("jquery_confirm")) { $html = " ".make_form(make_link("image_admin/delete"),'POST',false,'delete_image')." - + "; } else { $html = " ".make_form(make_link("image_admin/delete"))." - + "; } - - if($config->get_bool("upload_replace") && $user->is_admin()) { - $html .= " + } + + /** + * Display link to replace the image + * + * @param $image_id The image to replace + */ + public function get_deleter_html($image_id) { + + $html = " ".make_form(make_link("image_admin/replace"))." - + - - "; - } + "; return $html; } From 7ee0407ba89f8d05874044357446c9bf6af15c6f Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sat, 3 Sep 2011 16:42:12 -0400 Subject: [PATCH 03/20] Oops, forgot to rename. --- ext/image/theme.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/image/theme.php b/ext/image/theme.php index 3004bd5d..d5f867b6 100644 --- a/ext/image/theme.php +++ b/ext/image/theme.php @@ -32,7 +32,7 @@ class ImageIOTheme { * * @param $image_id The image to replace */ - public function get_deleter_html($image_id) { + public function get_resize_html($image_id) { $html = " ".make_form(make_link("image_admin/replace"))." From 3cfe182ad367da30969e865d46420da5e505a331 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sat, 3 Sep 2011 16:45:56 -0400 Subject: [PATCH 04/20] Typo, Renamed. --- ext/image/theme.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/image/theme.php b/ext/image/theme.php index d5f867b6..8306e0ff 100644 --- a/ext/image/theme.php +++ b/ext/image/theme.php @@ -25,6 +25,8 @@ class ImageIOTheme { "; } + + return $html; } /** @@ -32,7 +34,7 @@ class ImageIOTheme { * * @param $image_id The image to replace */ - public function get_resize_html($image_id) { + public function get_replace_html($image_id) { $html = " ".make_form(make_link("image_admin/replace"))." From e6e9aced1c4c69e6bac8d448aa3ff88ff917671b Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sat, 3 Sep 2011 16:48:33 -0400 Subject: [PATCH 05/20] This function doesn't need the global $user now. --- ext/image/main.php | 9 ++++----- ext/image/theme.php | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ext/image/main.php b/ext/image/main.php index c448d0e7..abbc7d6a 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -175,6 +175,10 @@ class ImageIO extends SimpleExtension { if($user->is_admin()) { $event->add_part($this->theme->get_deleter_html($event->image->id)); } + /* In the future, could perhaps allow users to replace images that they own as well... */ + if ($user->is_admin() && $config->get_bool("upload_replace")) { + $event->add_part($this->theme->get_replace_html($event->image->id)); + } } public function onImageAddition($event) { @@ -209,11 +213,6 @@ class ImageIO extends SimpleExtension { $h_image_rate = sprintf("%.1f", ($i_image_count / $i_days_old)); $images_link = make_link("post/list/user_id=$u_id/1"); $event->add_stats("Images uploaded: $i_image_count, $h_image_rate per day"); - - /* In the future, could perhaps allow users to replace images that they own as well... */ - if ($user->is_admin() && $config->get_bool("upload_replace")) { - $event->add_part($this->theme->get_replace_html($event->image->id)); - } } public function onSetupBuilding($event) { diff --git a/ext/image/theme.php b/ext/image/theme.php index 8306e0ff..648e8531 100644 --- a/ext/image/theme.php +++ b/ext/image/theme.php @@ -7,7 +7,6 @@ class ImageIOTheme { * @param $image_id The image to delete */ public function get_deleter_html($image_id) { - global $user; global $config; if($config->get_bool("jquery_confirm")) { From 9c8da62ba09f2bf10bbdebf27547e0592052d8f0 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sat, 3 Sep 2011 17:01:27 -0400 Subject: [PATCH 06/20] This function needs the global $config. --- ext/image/main.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/image/main.php b/ext/image/main.php index abbc7d6a..ba3f1b9b 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -172,6 +172,8 @@ class ImageIO extends SimpleExtension { public function onImageAdminBlockBuilding($event) { global $user; + global $config; + if($user->is_admin()) { $event->add_part($this->theme->get_deleter_html($event->image->id)); } From 100dd6438eeb715ab86d7845d4034854ec1ad1a6 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sat, 3 Sep 2011 19:34:46 -0400 Subject: [PATCH 07/20] Added more comments and changed others for better doxygen support. --- ext/image/main.php | 88 ++++++++++++++++++++++++++------------------- ext/upload/main.php | 21 +++++++---- 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/ext/image/main.php b/ext/image/main.php index ba3f1b9b..0dfeb775 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -1,21 +1,27 @@ + * Modified by: jgen * Description: Handle the image database * Visibility: admin */ -/* - * ImageAdditionEvent: - * $user -- the user adding the image - * $image -- the image being added - * - * An image is being added to the database + /** + * An image is being added to the database. */ class ImageAdditionEvent extends Event { var $user, $image; - + + /** + * Inserts a new image into the database with its associated + * information. Also calls TagSetEvent to set the tags for + * this new image. + * + * @sa TagSetEvent + * @param $user The user adding the image + * @param $image The new image to add. + */ public function ImageAdditionEvent(User $user, Image $image) { $this->image = $image; $this->user = $user; @@ -30,34 +36,41 @@ class ImageAdditionException extends SCoreException { } } -/* - * ImageDeletionEvent: - * $image -- the image being deleted - * - * An image is being deleted. Used by things like tags - * and comments handlers to clean out related rows in - * their tables +/** + * An image is being deleted. */ class ImageDeletionEvent extends Event { var $image; - + + /** + * Deletes an image. + * Used by things like tags and comments handlers to + * clean out related rows in their tables. + * + * @param $image The image being deleted + */ public function ImageDeletionEvent(Image $image) { $this->image = $image; } } -/* - * ImageReplaceEvent: - * $id -- the ID of the image to replace - * $image -- the image object of the new image to use - * - * This function replaces an image. Effectively it only - * replaces the image file contents and leaves the tags - * and such the same. +/** + * An image is being replaced. */ class ImageReplaceEvent extends Event { var $id, $image; - + + /** + * Replaces an image. + * Updates an existing ID in the database to use a new image + * file, leaving the tags and such unchanged. Also removes + * the old image file and thumbnail from the disk. + * + * @param $id + * The ID of the image to replace + * @param $image + * The image object of the new image to use + */ public function ImageReplaceEvent($id, Image $image) { $this->id = $id; $this->image = $image; @@ -72,15 +85,18 @@ class ImageReplaceException extends SCoreException { } } - -/* - * ThumbnailGenerationEvent: - * Request a thumb be made for an image +/** + * Request a thumbnail be made for an image object. */ class ThumbnailGenerationEvent extends Event { - var $hash; - var $type; - + var $hash, $type; + + /** + * Request a thumbnail be made for an image object + * + * @param $hash The unique hash of the image + * @param $type The type of the image + */ public function ThumbnailGenerationEvent($hash, $type) { $this->hash = $hash; $this->type = $type; @@ -95,8 +111,7 @@ class ThumbnailGenerationEvent extends Event { * $image -- the image who's link is being parsed */ class ParseLinkTemplateEvent extends Event { - var $link, $original; - var $image; + var $link, $original, $image; public function ParseLinkTemplateEvent($link, Image $image) { $this->link = $link; @@ -110,9 +125,8 @@ class ParseLinkTemplateEvent extends Event { } -/* - * A class to handle adding / getting / removing image - * files from the disk +/** + * A class to handle adding / getting / removing image files from the disk. */ class ImageIO extends SimpleExtension { public function onInitExt($event) { diff --git a/ext/upload/main.php b/ext/upload/main.php index 890e10f8..fd795fdf 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -5,17 +5,19 @@ * Description: Allows people to upload files to the website */ -/* - * DataUploadEvent: - * $user -- the user uploading the data - * $tmpname -- the temporary file used for upload - * $metadata -- info about the file, should contain at least "filename", "extension", "tags" and "source" - * - * Some data is being uploaded. Should be caught by a file handler. +/** + * Occurs when some data is being uploaded. */ class DataUploadEvent extends Event { var $user, $tmpname, $metadata, $hash, $type, $image_id = -1; + /** + * Some data is being uploaded. + * This should be caught by a file handler. + * @param $user The user uploading the data. + * @param $tmpname The temporary file used for upload. + * @param $metadata Info about the file, should contain at least "filename", "extension", "tags" and "source". + */ public function DataUploadEvent(User $user, $tmpname, $metadata) { assert(file_exists($tmpname)); @@ -34,6 +36,11 @@ class DataUploadEvent extends Event { class UploadException extends SCoreException {} +/** + * Main upload class. + * All files that are uploaded to the site are handled through this class. + * This also includes transloaded files as well. + */ class Upload implements Extension { var $theme; // event handling {{{ From 14bfa8b32376dda39555fe925a5f97b768e25af4 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sat, 3 Sep 2011 23:13:41 -0400 Subject: [PATCH 08/20] Working on Image Resize feature. --- ext/resize/main.php | 233 +++++++++++++++++++++++++++++++++++++++++++ ext/resize/theme.php | 56 +++++++++++ 2 files changed, 289 insertions(+) create mode 100644 ext/resize/main.php create mode 100644 ext/resize/theme.php diff --git a/ext/resize/main.php b/ext/resize/main.php new file mode 100644 index 00000000..0d2e1d50 --- /dev/null +++ b/ext/resize/main.php @@ -0,0 +1,233 @@ + + * Description: Allows admins to resize uploaded images. + * License: GPLv2 + * Version: 0.1 + * Notice: + * The image resize and resample code is based off of the "smart_resize_image" + * function copyright 2008 Maxim Chernyak, released under a MIT-style license. + * + */ + +/** + * This class is just a wrapper around SCoreException. + */ +class ImageResizeException extends SCoreException { + var $error; + + public function __construct($error) { + $this->error = $error; + } +} + +/** + * This class handles image resize requests. + */ +class ResizeImage extends SimpleExtension { + + public function onInitExt($event) { + global $config; + $config->set_default_bool('resize_enabled', true); + $config->set_default_int('resize_default_width', 0); + $config->set_default_int('resize_default_height', 0); + } + + public function onImageAdminBlockBuilding($event) { + global $user, $config; + if($user->is_admin() && $config->get_bool("resize_enabled")) { + /* Add a link to resize the image */ + $event->add_part($this->theme->get_resize_html($event->image->id)); + } + } + + public function onSetupBuilding($event) { + $sb = new SetupBlock("Image Resize"); + $sb->add_bool_option("resize_enabled", "Allow resizing images: "); + $sb->add_label("
Preset/Default Width: "); + $sb->add_int_option("resize_default_width"); + $sb->add_label(" px"); + $sb->add_label("
Preset/Default Height: "); + $sb->add_int_option("resize_default_height"); + $sb->add_label(" px"); + $sb->add_label("
(enter 0 for no default)"); + $event->panel->add_block($sb); + } + + public function onPageRequest($event) { + global $page, $user; + + if ( $event->page_matches("resize") && $user->is_admin() ) { + // Try to get the image ID + $image_id = int_escape($event->get_arg(0)); + if (empty($image_id)) { + $image_id = isset($_POST['image_id']) ? $_POST['image_id'] : null; + } + if (empty($image_id)) { + throw new ImageResizeException("Can not resize Image: No valid Image ID given."); + } + + $image = Image::by_id($image_id); + if(is_null($image)) { + $this->theme->display_error($page, "Image not found", "No image in the database has the ID #$image_id"); + } else { + + /* Check if options were given to resize an image. */ + if (isset($_POST['resize'])) { + + /* get options */ + + $width = $height = 0; + + if (isset($_POST['resize_width'])) { + $width = int_escape($_POST['resize_width']); + } + if (isset($_POST['resize_height'])) { + $width = int_escape($_POST['resize_height']); + } + + /* Attempt to resize the image */ + try { + $this->resize_image($image, $width, $height); + } catch (ImageResizeException $e) { + $this->theme->display_resize_error($page, "Error Resizing", $e->error); + } + } else { + /* Display options for resizing */ + $this->theme->display_resize_page($page, $image_id); + } + } + } + } + + + // Private functions + + /* + This function could be made much smaller by using the ImageReplaceEvent + ie: Pretend that we are replacing the image with a resized copy. + */ + private function resize_image($image, $width, $height) { + global $config; + global $user; + global $page; + global $database; + + if ( $height <= 0 && $width <= 0 ) { + throw new ImageResizeException("Invalid options for height and width."); + } + + $id = $image->id; + $hash = $image->hash; + if (is_null($hash)) { + throw new ImageResizeException("Image does not have a hash associated with it."); + } + + $image_filename = warehouse_path("images", $hash); + $info = getimagesize($image_filename); + + if (($image->width != $info[0] ) || ($image->height != $info[1])) { + throw new ImageResizeException("The image size does not match what is in the database! - Aborting Resize."); + } + + /* Check memory usage limits */ + $memory_use = (filesize($image_filename)*2) + ($width*$height*4) + (4*1024*1024); + $memory_limit = get_memory_limit(); + + if ($memory_use > $memory_limit) { + throw new ImageResizeException("The image is too large to resize given the memory limits. ($memory_use > $memory_limit)"); + } + + /* Calculate the new size of the image */ + if ( $height > 0 && $width > 0 ) { + $new_height = $height; + $new_width = $width; + } else { + // Scale the new image + if ($width == 0) $factor = $height/$image->height; + elseif ($height == 0) $factor = $width/$image->width; + else $factor = min( $width / $image->width, $height / $image->height ); + + $new_width = round( $image->width * $factor ); + $new_height = round( $image->height * $factor ); + } + + /* Attempt to load the image */ + switch ( $info[2] ) { + case IMAGETYPE_GIF: $image = imagecreatefromgif($image_filename); break; + case IMAGETYPE_JPEG: $image = imagecreatefromjpeg($image_filename); break; + case IMAGETYPE_PNG: $image = imagecreatefrompng($image_filename); break; + default: + throw new ImageResizeException("Unsupported image type."); + } + + /* Resize and resample the image */ + $image_resized = imagecreatetruecolor( $new_width, $new_height ); + + if ( ($info[2] == IMAGETYPE_GIF) || ($info[2] == IMAGETYPE_PNG) ) { + $transparency = imagecolortransparent($image); + + if ($transparency >= 0) { + $transparent_color = imagecolorsforindex($image, $trnprt_indx); + $transparency = imagecolorallocate($image_resized, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']); + imagefill($image_resized, 0, 0, $transparency); + imagecolortransparent($image_resized, $transparency); + } + elseif ($info[2] == IMAGETYPE_PNG) { + imagealphablending($image_resized, false); + $color = imagecolorallocatealpha($image_resized, 0, 0, 0, 127); + imagefill($image_resized, 0, 0, $color); + imagesavealpha($image_resized, true); + } + } + imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $new_width, $new_height, $image->width, $image->height); + + /* Delete original image and thumbnail */ + log_debug("image", "Removing image with hash ".$hash); + $image->remove_image_only(); + + /* Temp storage while we resize */ + $tmp_filename = tempnam("/tmp", 'shimmie_resize_'.time()); + if (empty($tmp_filename)) { + throw new ImageResizeException("Unable to save temporary image file."); + } + + /* Output to the same format as the original image */ + switch ( $info[2] ) { + case IMAGETYPE_GIF: imagegif($image_resized, $tmp_filename); break; + case IMAGETYPE_JPEG: imagejpeg($image_resized, $tmp_filename); break; + case IMAGETYPE_PNG: imagepng($image_resized, $tmp_filename); break; + default: + throw new ImageResizeException("Unsupported image type."); + } + + + /* Regenerate thumbnail */ + + + unlink($tmp_filename); + + + /* Update the database */ + $database->Execute( + "UPDATE images SET + filename = :filename, filesize = :filesize, hash = :hash, + ext = :ext, width = :width, height = :height, source = :source + WHERE + id = :id + ", + array( + "filename"=>$image_new->filename, "filesize"=>$image->filesize, "hash"=>$image->hash, + "ext"=>$image->ext, "width"=>$image->width, "height"=>$image->height, "source"=>$image->source, + "id"=>$id + ) + ); + + + + log_info("resize", "Resized Image #{$image->id}"); + + } +} +?> diff --git a/ext/resize/theme.php b/ext/resize/theme.php new file mode 100644 index 00000000..853274d1 --- /dev/null +++ b/ext/resize/theme.php @@ -0,0 +1,56 @@ + + + + "; + + return $html; + } + + public function display_resize_error(Page $page, $title, $message) { + $page->add_block(new Block($title, $message)); + } + + public function display_resize_page(Page $page, $image_id) { + global $config; + + $default_width = $config->get_int('resize_default_width'); + $default_height = $config->get_int('resize_default_height'); + + $image = Image::by_id($image_id); + $thumbnail = $this->build_thumb_html($image, null); + + $html = "

Resize Image ID ".$image_id."
".$thumbnail."

+

Please note: You will have to refresh the image page, or empty your browser cache.

+

Enter the new size for the image, or leave blank to scale the image automatically.


" + .make_form(make_link('resize/'.$image_id), 'POST', $multipart=True,'form_resize')." + + + + + +
New Width
New Height
+ + "; + + $page->set_title("Resize Image"); + $page->set_heading("Resize Image"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Resize Image", $html, "main", 20)); + + } +} +?> From ad850ad0d6dde56d4d6545757aedf88ccbb1d199 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 4 Sep 2011 10:30:20 -0400 Subject: [PATCH 09/20] Fixed a small typo. --- ext/image/main.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/image/main.php b/ext/image/main.php index 0dfeb775..67f2ccc7 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -426,7 +426,7 @@ class ImageIO extends SimpleExtension { id = :id ", array( - "filename"=>$image_new->filename, "filesize"=>$image->filesize, "hash"=>$image->hash, + "filename"=>$image->filename, "filesize"=>$image->filesize, "hash"=>$image->hash, "ext"=>$image->ext, "width"=>$image->width, "height"=>$image->height, "source"=>$image->source, "id"=>$id ) From d05344d5e34f4de6ede1f4fce2c6bb6796b07850 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 4 Sep 2011 11:17:14 -0400 Subject: [PATCH 10/20] Image resize is working now! (uses the GD library only for now) Moved resize into contrib folder. --- {ext => contrib}/resize/main.php | 84 ++++++++++++++++++------------- {ext => contrib}/resize/theme.php | 3 ++ core/imageboard.pack.php | 4 +- 3 files changed, 54 insertions(+), 37 deletions(-) rename {ext => contrib}/resize/main.php (71%) rename {ext => contrib}/resize/theme.php (94%) diff --git a/ext/resize/main.php b/contrib/resize/main.php similarity index 71% rename from ext/resize/main.php rename to contrib/resize/main.php index 0d2e1d50..972fc891 100644 --- a/ext/resize/main.php +++ b/contrib/resize/main.php @@ -1,14 +1,15 @@ - * Description: Allows admins to resize uploaded images. + * Description: Allows admins to resize images. * License: GPLv2 * Version: 0.1 * Notice: * The image resize and resample code is based off of the "smart_resize_image" * function copyright 2008 Maxim Chernyak, released under a MIT-style license. - * + * Documentation: + * This extension allows admins to resize images. */ /** @@ -74,7 +75,7 @@ class ResizeImage extends SimpleExtension { } else { /* Check if options were given to resize an image. */ - if (isset($_POST['resize'])) { + if (isset($_POST['resize_width']) || isset($_POST['resize_height'])) { /* get options */ @@ -84,12 +85,18 @@ class ResizeImage extends SimpleExtension { $width = int_escape($_POST['resize_width']); } if (isset($_POST['resize_height'])) { - $width = int_escape($_POST['resize_height']); + $height = int_escape($_POST['resize_height']); } /* Attempt to resize the image */ try { - $this->resize_image($image, $width, $height); + $this->resize_image($image_id, $width, $height); + + //$this->theme->display_resize_page($page, $image_id); + + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$image_id)); + } catch (ImageResizeException $e) { $this->theme->display_resize_error($page, "Error Resizing", $e->error); } @@ -108,26 +115,29 @@ class ResizeImage extends SimpleExtension { This function could be made much smaller by using the ImageReplaceEvent ie: Pretend that we are replacing the image with a resized copy. */ - private function resize_image($image, $width, $height) { + private function resize_image($image_id, $width, $height) { global $config; global $user; global $page; global $database; - if ( $height <= 0 && $width <= 0 ) { - throw new ImageResizeException("Invalid options for height and width."); + if ( ($height <= 0) && ($width <= 0) ) { + throw new ImageResizeException("Invalid options for height and width. ($width x $height)"); } - $id = $image->id; - $hash = $image->hash; + $image_obj = Image::by_id($image_id); + $hash = $image_obj->hash; if (is_null($hash)) { throw new ImageResizeException("Image does not have a hash associated with it."); } $image_filename = warehouse_path("images", $hash); $info = getimagesize($image_filename); + /* Get the image file type */ + $pathinfo = pathinfo($image_obj->filename); + $filetype = strtolower($pathinfo['extension']); - if (($image->width != $info[0] ) || ($image->height != $info[1])) { + if (($image_obj->width != $info[0] ) || ($image_obj->height != $info[1])) { throw new ImageResizeException("The image size does not match what is in the database! - Aborting Resize."); } @@ -145,12 +155,12 @@ class ResizeImage extends SimpleExtension { $new_width = $width; } else { // Scale the new image - if ($width == 0) $factor = $height/$image->height; - elseif ($height == 0) $factor = $width/$image->width; - else $factor = min( $width / $image->width, $height / $image->height ); + if ($width == 0) $factor = $height/$image_obj->height; + elseif ($height == 0) $factor = $width/$image_obj->width; + else $factor = min( $width / $image_obj->width, $height / $image_obj->height ); - $new_width = round( $image->width * $factor ); - $new_height = round( $image->height * $factor ); + $new_width = round( $image_obj->width * $factor ); + $new_height = round( $image_obj->height * $factor ); } /* Attempt to load the image */ @@ -181,14 +191,10 @@ class ResizeImage extends SimpleExtension { imagesavealpha($image_resized, true); } } - imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $new_width, $new_height, $image->width, $image->height); - - /* Delete original image and thumbnail */ - log_debug("image", "Removing image with hash ".$hash); - $image->remove_image_only(); + imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $new_width, $new_height, $image_obj->width, $image_obj->height); /* Temp storage while we resize */ - $tmp_filename = tempnam("/tmp", 'shimmie_resize_'.time()); + $tmp_filename = tempnam("/tmp", 'shimmie_resize'); if (empty($tmp_filename)) { throw new ImageResizeException("Unable to save temporary image file."); } @@ -202,32 +208,40 @@ class ResizeImage extends SimpleExtension { throw new ImageResizeException("Unsupported image type."); } + /* Move the new image into the main storage location */ + $new_hash = md5_file($tmp_filename); + $new_size = filesize($tmp_filename); + $target = warehouse_path("images", $new_hash); + if(!file_exists(dirname($target))) mkdir(dirname($target), 0755, true); + if(!@copy($tmp_filename, $target)) { + throw new ImageResizeException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ($target)"); + } + $new_filename = 'resized-'.$image_obj->filename; - /* Regenerate thumbnail */ - + /* Remove temporary file */ + @unlink($tmp_filename); - unlink($tmp_filename); + /* Delete original image and thumbnail */ + log_debug("image", "Removing image with hash ".$hash); + $image_obj->remove_image_only(); + /* Generate new thumbnail */ + send_event(new ThumbnailGenerationEvent($new_hash, $filetype)); /* Update the database */ $database->Execute( "UPDATE images SET - filename = :filename, filesize = :filesize, hash = :hash, - ext = :ext, width = :width, height = :height, source = :source + filename = :filename, filesize = :filesize, hash = :hash, width = :width, height = :height WHERE id = :id ", array( - "filename"=>$image_new->filename, "filesize"=>$image->filesize, "hash"=>$image->hash, - "ext"=>$image->ext, "width"=>$image->width, "height"=>$image->height, "source"=>$image->source, - "id"=>$id + "filename"=>$new_filename, "filesize"=>$new_size, "hash"=>$new_hash, + "width"=>$new_width, "height"=>$new_height, "id"=>$image_id ) ); - - - - log_info("resize", "Resized Image #{$image->id}"); + log_info("resize", "Resized Image #{$image_id} - New hash: {$new_hash}"); } } ?> diff --git a/ext/resize/theme.php b/contrib/resize/theme.php similarity index 94% rename from ext/resize/theme.php rename to contrib/resize/theme.php index 853274d1..0b73749e 100644 --- a/ext/resize/theme.php +++ b/contrib/resize/theme.php @@ -21,6 +21,9 @@ class ResizeImageTheme extends Themelet { } public function display_resize_error(Page $page, $title, $message) { + $page->set_title("Resize Image"); + $page->set_heading("Resize Image"); + $page->add_block(new NavBlock()); $page->add_block(new Block($title, $message)); } diff --git a/core/imageboard.pack.php b/core/imageboard.pack.php index e467e2db..9ce34abe 100644 --- a/core/imageboard.pack.php +++ b/core/imageboard.pack.php @@ -463,8 +463,8 @@ class Image { */ public function remove_image_only() { log_info("core-image", "Removed Image File ({$this->hash})"); - unlink($this->get_image_filename()); - unlink($this->get_thumb_filename()); + @unlink($this->get_image_filename()); + @unlink($this->get_thumb_filename()); } /** From be6e6e2933603b28570242c86d0bbb44c9eb3770 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 4 Sep 2011 11:41:25 -0400 Subject: [PATCH 11/20] Small change to reduce PHP notice. --- ext/upload/main.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/upload/main.php b/ext/upload/main.php index fd795fdf..688002dd 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -114,6 +114,8 @@ class Upload implements Extension { throw new UploadException("Can not upload more than one image for replacing."); } + $tags = ''; // Tags aren't changed when uploading. Set to null to stop PHP warnings. + if (count($_FILES)) { foreach($_FILES as $file) { $ok = $this->try_upload($file, $tags, $source, $image_id); From 8422e0050aed277e858e6d8747414845b051dc9d Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 4 Sep 2011 11:52:34 -0400 Subject: [PATCH 12/20] Another small change to reduce PHP notices. --- ext/upload/main.php | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/upload/main.php b/ext/upload/main.php index 688002dd..c9b3be48 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -114,6 +114,7 @@ class Upload implements Extension { throw new UploadException("Can not upload more than one image for replacing."); } + $source = isset($_POST['source']) ? $_POST['source'] : null; $tags = ''; // Tags aren't changed when uploading. Set to null to stop PHP warnings. if (count($_FILES)) { From bf035c247df33505915743ad3e4ee44a5e70a0f5 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 4 Sep 2011 13:46:12 -0400 Subject: [PATCH 13/20] Slight changes to how the Replace & Resize forms are displayed. --- contrib/resize/style.css | 5 +++++ contrib/resize/theme.php | 3 ++- ext/upload/theme.php | 10 ++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 contrib/resize/style.css diff --git a/contrib/resize/style.css b/contrib/resize/style.css new file mode 100644 index 00000000..ccfc01c2 --- /dev/null +++ b/contrib/resize/style.css @@ -0,0 +1,5 @@ +form#form_resize { + float: left; + margin: 0; + width: 60%; +} diff --git a/contrib/resize/theme.php b/contrib/resize/theme.php index 0b73749e..ee920b81 100644 --- a/contrib/resize/theme.php +++ b/contrib/resize/theme.php @@ -36,7 +36,8 @@ class ResizeImageTheme extends Themelet { $image = Image::by_id($image_id); $thumbnail = $this->build_thumb_html($image, null); - $html = "

Resize Image ID ".$image_id."
".$thumbnail."

+ $html = "
+

Resize Image ID ".$image_id."
".$thumbnail."

Please note: You will have to refresh the image page, or empty your browser cache.

Enter the new size for the image, or leave blank to scale the image automatically.


" .make_form(make_link('resize/'.$image_id), 'POST', $multipart=True,'form_resize')." diff --git a/ext/upload/theme.php b/ext/upload/theme.php index df0e5868..f26905c0 100644 --- a/ext/upload/theme.php +++ b/ext/upload/theme.php @@ -86,16 +86,16 @@ class UploadTheme extends Themelet { File + "; if($tl_enabled) { $upload_list .= " + URL + "; } - $upload_list .= " - - "; $max_size = $config->get_int('upload_size'); $max_kb = to_shorthand_int($max_size); @@ -103,7 +103,9 @@ class UploadTheme extends Themelet { $image = Image::by_id($image_id); $thumbnail = $this->build_thumb_html($image, null); - $html = "

Replacing Image ID ".$image_id."
Please note: You will have to refresh the image page, or empty your browser cache.

" + $html = " +
+

Replacing Image ID ".$image_id."
Please note: You will have to refresh the image page, or empty your browser cache.

" .$thumbnail."
" .make_form(make_link("upload/replace/".$image_id), "POST", $multipart=True)." From fca286913e8d00f7000894bad93e75ce20edb7cf Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 28 Aug 2011 00:31:30 -0400 Subject: [PATCH 14/20] Working on moving header() inside of the global $page data structure. --- contrib/browser_search/main.php | 2 +- contrib/regen_thumb/theme.php | 2 +- contrib/rss_comments/main.php | 2 +- contrib/rss_images/main.php | 4 ++-- contrib/site_description/main.php | 4 ++-- contrib/tagger/theme.php | 2 +- core/page.class.php | 20 ++++++++++---------- ext/view/theme.php | 10 +++++----- themes/danbooru/layout.class.php | 4 ++-- themes/default/layout.class.php | 4 ++-- themes/flat/layout.class.php | 4 ++-- themes/futaba/layout.class.php | 4 ++-- themes/lite/layout.class.php | 2 +- themes/old_default/layout.class.php | 4 ++-- themes/warm/layout.class.php | 2 +- 15 files changed, 35 insertions(+), 35 deletions(-) diff --git a/contrib/browser_search/main.php b/contrib/browser_search/main.php index fb0e5906..0b458a64 100755 --- a/contrib/browser_search/main.php +++ b/contrib/browser_search/main.php @@ -28,7 +28,7 @@ class BrowserSearch implements Extension { global $config; $search_title = $config->get_string('title'); $search_file_url = make_link('browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml'); - $page->add_header(""); + $page->add_html_header(""); } // The search.xml file that is generated on the fly diff --git a/contrib/regen_thumb/theme.php b/contrib/regen_thumb/theme.php index 2d8b7d68..6f5720a7 100644 --- a/contrib/regen_thumb/theme.php +++ b/contrib/regen_thumb/theme.php @@ -19,7 +19,7 @@ class RegenThumbTheme extends Themelet { public function display_results(Page $page, Image $image) { $page->set_title("Thumbnail Regenerated"); $page->set_heading("Thumbnail Regenerated"); - $page->add_header(""); + $page->add_html_header(""); $page->add_block(new NavBlock()); $page->add_block(new Block("Thumbnail", $this->build_thumb_html($image))); } diff --git a/contrib/rss_comments/main.php b/contrib/rss_comments/main.php index aa73d550..084ce836 100644 --- a/contrib/rss_comments/main.php +++ b/contrib/rss_comments/main.php @@ -11,7 +11,7 @@ class RSS_Comments extends SimpleExtension { global $config, $page; $title = $config->get_string('title'); - $page->add_header("add_html_header(""); } diff --git a/contrib/rss_images/main.php b/contrib/rss_images/main.php index 9c8c1f7c..101b0ac8 100644 --- a/contrib/rss_images/main.php +++ b/contrib/rss_images/main.php @@ -13,11 +13,11 @@ class RSS_Images extends SimpleExtension { if(count($event->search_terms) > 0) { $search = html_escape(implode(' ', $event->search_terms)); - $page->add_header("add_html_header(""); } else { - $page->add_header("add_html_header(""); } } diff --git a/contrib/site_description/main.php b/contrib/site_description/main.php index faccde49..43ed38b1 100644 --- a/contrib/site_description/main.php +++ b/contrib/site_description/main.php @@ -14,11 +14,11 @@ class SiteDescription extends SimpleExtension { global $config, $page; if(strlen($config->get_string("site_description")) > 0) { $description = $config->get_string("site_description"); - $page->add_header(""); + $page->add_html_header(""); } if(strlen($config->get_string("site_keywords")) > 0) { $keywords = $config->get_string("site_keywords"); - $page->add_header(""); + $page->add_html_header(""); } } diff --git a/contrib/tagger/theme.php b/contrib/tagger/theme.php index f1edc566..062998d9 100644 --- a/contrib/tagger/theme.php +++ b/contrib/tagger/theme.php @@ -11,7 +11,7 @@ class taggerTheme extends Themelet { // Initialization code $base_href = $config->get_string('base_href'); // TODO: AJAX test and fallback. - $page->add_header(""); + $page->add_html_header(""); $page->add_block(new Block(null, "","main",1000)); diff --git a/core/page.class.php b/core/page.class.php index dc7ebf29..3af68f16 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -108,7 +108,7 @@ class Page { var $heading = ""; var $subheading = ""; var $quicknav = ""; - var $headers = array(); + var $html_headers = array(); var $blocks = array(); /** @publicsection */ @@ -136,9 +136,9 @@ class Page { /** * Add a line to the HTML head section */ - public function add_header($line, $position=50) { - while(isset($this->headers[$position])) $position++; - $this->headers[$position] = $line; + public function add_html_header($line, $position=50) { + while(isset($this->html_headers[$position])) $position++; + $this->html_headers[$position] = $line; } /** @@ -165,7 +165,7 @@ class Page { case "page": header("Cache-control: no-cache"); usort($this->blocks, "blockcmp"); - $this->add_auto_headers(); + $this->add_auto_html_headers(); $layout = new Layout(); $layout->display_page($page); break; @@ -186,26 +186,26 @@ class Page { } } - protected function add_auto_headers() { + protected function add_auto_html_headers() { $data_href = get_base_href(); foreach(glob("lib/*.css") as $css) { - $this->add_header(""); + $this->add_html_header(""); } $css_files = glob("ext/*/style.css"); if($css_files) { foreach($css_files as $css_file) { - $this->add_header(""); + $this->add_html_header(""); } } foreach(glob("lib/*.js") as $js) { - $this->add_header(""); + $this->add_html_header(""); } $js_files = glob("ext/*/script.js"); if($js_files) { foreach($js_files as $js_file) { - $this->add_header(""); + $this->add_html_header(""); } } } diff --git a/ext/view/theme.php b/ext/view/theme.php index 993243b3..b9cb5cf8 100644 --- a/ext/view/theme.php +++ b/ext/view/theme.php @@ -10,11 +10,11 @@ class ViewImageTheme extends Themelet { $metatags = str_replace(" ", ", ", html_escape($image->get_tag_list())); $page->set_title("Image {$image->id}: ".html_escape($image->get_tag_list())); - $page->add_header(""); - $page->add_header(""); - $page->add_header(""); - $page->add_header("get_thumb_link())."\">"); - $page->add_header("id}"))."\">"); + $page->add_html_header(""); + $page->add_html_header(""); + $page->add_html_header(""); + $page->add_html_header("get_thumb_link())."\">"); + $page->add_html_header("id}"))."\">"); $page->set_heading(html_escape($image->get_tag_list())); $page->add_block(new Block("Navigation", $this->build_navigation($image), "left", 0)); $page->add_block(new Block(null, $this->build_info($image, $editor_parts), "main", 10)); diff --git a/themes/danbooru/layout.class.php b/themes/danbooru/layout.class.php index b49b52c2..5045adcc 100644 --- a/themes/danbooru/layout.class.php +++ b/themes/danbooru/layout.class.php @@ -53,8 +53,8 @@ class Layout { $header_html = ""; - ksort($page->headers); - foreach($page->headers as $line) { + ksort($page->html_headers); + foreach($page->html_headers as $line) { $header_html .= "\t\t$line\n"; } diff --git a/themes/default/layout.class.php b/themes/default/layout.class.php index 290d1a8c..3ee91b82 100644 --- a/themes/default/layout.class.php +++ b/themes/default/layout.class.php @@ -14,8 +14,8 @@ class Layout { $contact_link = $config->get_string('contact_link'); $header_html = ""; - ksort($page->headers); - foreach($page->headers as $line) { + ksort($page->html_headers); + foreach($page->html_headers as $line) { $header_html .= "\t\t$line\n"; } diff --git a/themes/flat/layout.class.php b/themes/flat/layout.class.php index d8fb4e0f..f0e9a95b 100644 --- a/themes/flat/layout.class.php +++ b/themes/flat/layout.class.php @@ -14,8 +14,8 @@ class Layout { $contact_link = $config->get_string('contact_link'); $header_html = ""; - ksort($page->headers); - foreach($page->headers as $line) { + ksort($page->html_headers); + foreach($page->html_headers as $line) { $header_html .= "\t\t$line\n"; } diff --git a/themes/futaba/layout.class.php b/themes/futaba/layout.class.php index ed1568fd..51f76716 100644 --- a/themes/futaba/layout.class.php +++ b/themes/futaba/layout.class.php @@ -9,8 +9,8 @@ class Layout { $contact_link = $config->get_string('contact_link'); $header_html = ""; - ksort($page->headers); - foreach($page->headers as $line) { + ksort($page->html_headers); + foreach($page->html_headers as $line) { $header_html .= "\t\t$line\n"; } diff --git a/themes/lite/layout.class.php b/themes/lite/layout.class.php index 5e9bed77..c7273ab3 100644 --- a/themes/lite/layout.class.php +++ b/themes/lite/layout.class.php @@ -20,7 +20,7 @@ class Layout { $contact_link = $config->get_string('contact_link'); $header_html = ""; - foreach($page->headers as $line) { + foreach($page->html_headers as $line) { $header_html .= "\t\t$line\n"; } diff --git a/themes/old_default/layout.class.php b/themes/old_default/layout.class.php index 43931d5e..cb4e6952 100644 --- a/themes/old_default/layout.class.php +++ b/themes/old_default/layout.class.php @@ -9,8 +9,8 @@ class Layout { $contact_link = $config->get_string('contact_link'); $header_html = ""; - ksort($page->headers); - foreach($page->headers as $line) { + ksort($page->html_headers); + foreach($page->html_headers as $line) { $header_html .= "\t\t$line\n"; } diff --git a/themes/warm/layout.class.php b/themes/warm/layout.class.php index 3bd85755..3d6c2cb7 100644 --- a/themes/warm/layout.class.php +++ b/themes/warm/layout.class.php @@ -14,7 +14,7 @@ class Layout { $contact_link = $config->get_string('contact_link'); $header_html = ""; - foreach($page->headers as $line) { + foreach($page->html_headers as $line) { $header_html .= "\t\t$line\n"; } From 19a3a5a6f9bc768d10c13fb42f6956006390e099 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Tue, 30 Aug 2011 13:14:03 -0400 Subject: [PATCH 15/20] Working on changed $page to support http headers as well as html headers. --- core/page.class.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/page.class.php b/core/page.class.php index 3af68f16..254f7619 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -140,7 +140,14 @@ class Page { while(isset($this->html_headers[$position])) $position++; $this->html_headers[$position] = $line; } - + + /** + * Add a http header to be sent to the client. + */ + public function add_header($line) { + die("Function is not impliemented yet."); + } + /** * Add a Block of data */ From bd31bcd79aba9ea3fc62f6266ceb23811c4a7acc Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Tue, 30 Aug 2011 16:24:10 -0400 Subject: [PATCH 16/20] The page class now supports both HTML headers and HTTP headers. From the comment: FIXME: should be $page->blah --- core/page.class.php | 18 ++++++++++++++---- ext/image/main.php | 8 ++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/core/page.class.php b/core/page.class.php index 254f7619..b1940cd3 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -109,6 +109,7 @@ class Page { var $subheading = ""; var $quicknav = ""; var $html_headers = array(); + var $http_headers = array(); var $blocks = array(); /** @publicsection */ @@ -144,8 +145,9 @@ class Page { /** * Add a http header to be sent to the client. */ - public function add_header($line) { - die("Function is not impliemented yet."); + public function add_http_header($line, $position=50) { + while(isset($this->http_headers[$position])) $position++; + $this->http_headers[$position] = $line; } /** @@ -164,9 +166,17 @@ class Page { */ public function display() { global $page; + + add_http_header("Content-type: {$this->type}", 1); + add_http_header("X-Powered-By: SCore-".SCORE_VERSION, 2); - header("Content-type: {$this->type}"); - header("X-Powered-By: SCore-".SCORE_VERSION); + if (!headers_sent()) { + foreach($this->http_headers as $head){ + header($head); + } + } else { + print "Error: Headers have already been sent to the client."; + } switch($this->mode) { case "page": diff --git a/ext/image/main.php b/ext/image/main.php index 67f2ccc7..aea0ff54 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -367,13 +367,13 @@ class ImageIO extends SimpleExtension { } $gmdate_mod = gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT'; - // FIXME: should be $page->blah if($if_modified_since == $gmdate_mod) { - header("HTTP/1.0 304 Not Modified"); + $page->add_http_header("HTTP/1.0 304 Not Modified",3); } else { - header("Last-Modified: $gmdate_mod"); - header("Expires: Fri, 2 Sep 2101 12:42:42 GMT"); // War was beginning + /* FIXME: The Expires date Needs to be admin-configurable */ + $page->add_http_header("Last-Modified: $gmdate_mod"); + $page->add_http_header("Expires: Fri, 2 Sep 2101 12:42:42 GMT"); // War was beginning } } else { From c30c898c4e7d0ebd3e2af25f05ba7f4e9565c6bc Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Tue, 30 Aug 2011 16:38:46 -0400 Subject: [PATCH 17/20] Changing files to use the $page->add_http_header() method instead. --- contrib/danbooru_api/main.php | 32 +++++++++++++-------------- ext/handle_404/main.php | 3 ++- ext/upload/main.php | 3 ++- themes/danbooru/themelet.class.php | 2 +- themes/default/themelet.class.php | 2 +- themes/flat/themelet.class.php | 2 +- themes/lite/themelet.class.php | 2 +- themes/old_default/themelet.class.php | 2 +- themes/warm/themelet.class.php | 2 +- 9 files changed, 26 insertions(+), 24 deletions(-) diff --git a/contrib/danbooru_api/main.php b/contrib/danbooru_api/main.php index 4d11d655..b925d860 100644 --- a/contrib/danbooru_api/main.php +++ b/contrib/danbooru_api/main.php @@ -159,8 +159,8 @@ class DanbooruApi implements Extension { $fp = fopen($url, "r"); if(!$fp) { - header("HTTP/1.0 409 Conflict"); - header("X-Danbooru-Errors: fopen read error"); + $page->add_http_header("HTTP/1.0 409 Conflict"); + $page->add_http_header("X-Danbooru-Errors: fopen read error"); } $data = ""; @@ -193,8 +193,8 @@ class DanbooruApi implements Extension $filename = basename($url); } else { // Nothing was specified at all - header("HTTP/1.0 409 Conflict"); - header("X-Danbooru-Errors: no input files"); + $page->add_http_header("HTTP/1.0 409 Conflict"); + $page->add_http_header("X-Danbooru-Errors: no input files"); return; } @@ -206,8 +206,8 @@ class DanbooruApi implements Extension { if(strtolower($_REQUEST['md5']) != $hash) { - header("HTTP/1.0 409 Conflict"); - header("X-Danbooru-Errors: md5 mismatch"); + $page->add_http_header("HTTP/1.0 409 Conflict"); + $page->add_http_header("X-Danbooru-Errors: md5 mismatch"); return; } } @@ -217,11 +217,11 @@ class DanbooruApi implements Extension // Does it exist already? $existing = Image::by_hash($hash); if(!is_null($existing)) { - header("HTTP/1.0 409 Conflict"); - header("X-Danbooru-Errors: duplicate"); + $page->add_http_header("HTTP/1.0 409 Conflict"); + $page->add_http_header("X-Danbooru-Errors: duplicate"); $existinglink = make_link("post/view/" . $existing->id); if($danboorup_kludge) $existinglink=make_http($existinglink); - header("X-Danbooru-Location: $existinglink"); + $page->add_http_header("X-Danbooru-Location: $existinglink"); return; // wut! } @@ -246,21 +246,21 @@ class DanbooruApi implements Extension // Did we POST or GET this call? if($_SERVER['REQUEST_METHOD'] == 'POST') { - header("X-Danbooru-Location: $newid"); + $page->add_http_header("X-Danbooru-Location: $newid"); } else - header("Location: $newid"); + $page->add_http_header("Location: $newid"); } catch(UploadException $ex) { // Did something screw up? - header("HTTP/1.0 409 Conflict"); - header("X-Danbooru-Errors: exception - " . $ex->getMessage()); + $page->add_http_header("HTTP/1.0 409 Conflict"); + $page->add_http_header("X-Danbooru-Errors: exception - " . $ex->getMessage()); return; } } else { - header("HTTP/1.0 409 Conflict"); - header("X-Danbooru-Errors: authentication error"); + $page->add_http_header("HTTP/1.0 409 Conflict"); + $page->add_http_header("X-Danbooru-Errors: authentication error"); return; } } @@ -387,7 +387,7 @@ class DanbooruApi implements Extension if(($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'show')) { $fixedlocation = make_link("post/view/" . $event->get_arg(3)); - header("Location: $fixedlocation"); + $page->add_http_header("Location: $fixedlocation"); } } diff --git a/ext/handle_404/main.php b/ext/handle_404/main.php index 3a9a2503..b7e80aa0 100644 --- a/ext/handle_404/main.php +++ b/ext/handle_404/main.php @@ -14,8 +14,9 @@ class Handle404 extends SimpleExtension { // hax. if($page->mode == "page" && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) { $h_pagename = html_escape(implode('/', $event->args)); - header("HTTP/1.0 404 Page Not Found"); log_debug("handle_404", "Hit 404: $h_pagename"); + + $page->add_http_header("HTTP/1.0 404 Page Not Found",5); $page->set_title("404"); $page->set_heading("404 - No Handler Found"); $page->add_block(new NavBlock()); diff --git a/ext/upload/main.php b/ext/upload/main.php index c9b3be48..167bce07 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -283,7 +283,8 @@ class Upload implements Extension { if($event->image_id == -1) { throw new UploadException("File type not recognised"); } - header("X-Shimmie-Image-ID: ".int_escape($event->image_id)); + //header("X-Shimmie-Image-ID: ".int_escape($event->image_id)); + $page->add_http_header("X-Shimmie-Image-ID: ".int_escape($event->image_id)); } catch(UploadException $ex) { $this->theme->display_upload_error($page, "Error with ".html_escape($file['name']), diff --git a/themes/danbooru/themelet.class.php b/themes/danbooru/themelet.class.php index 1c2d687c..2fa978a5 100644 --- a/themes/danbooru/themelet.class.php +++ b/themes/danbooru/themelet.class.php @@ -10,7 +10,7 @@ class Themelet { public function display_permission_denied(Page $page) { - header("HTTP/1.0 403 Permission Denied"); + $page->add_http_header("HTTP/1.0 403 Permission Denied"); $this->display_error($page, "Permission Denied", "You do not have permission to access this page"); } diff --git a/themes/default/themelet.class.php b/themes/default/themelet.class.php index de1f9b4e..159f8881 100644 --- a/themes/default/themelet.class.php +++ b/themes/default/themelet.class.php @@ -18,7 +18,7 @@ class Themelet { * A specific, common error message */ public function display_permission_denied(Page $page) { - header("HTTP/1.0 403 Permission Denied"); + $page->add_http_header("HTTP/1.0 403 Permission Denied"); $this->display_error($page, "Permission Denied", "You do not have permission to access this page"); } diff --git a/themes/flat/themelet.class.php b/themes/flat/themelet.class.php index 5cb25716..b79ccc73 100644 --- a/themes/flat/themelet.class.php +++ b/themes/flat/themelet.class.php @@ -18,7 +18,7 @@ class Themelet { * A specific, common error message */ public function display_permission_denied(Page $page) { - header("HTTP/1.0 403 Permission Denied"); + $page->add_http_header("HTTP/1.0 403 Permission Denied"); $this->display_error($page, "Permission Denied", "You do not have permission to access this page"); } diff --git a/themes/lite/themelet.class.php b/themes/lite/themelet.class.php index 59b403e2..8d57b147 100644 --- a/themes/lite/themelet.class.php +++ b/themes/lite/themelet.class.php @@ -18,7 +18,7 @@ class Themelet { * A specific, common error message */ public function display_permission_denied(Page $page) { - header("HTTP/1.0 403 Permission Denied"); + $page->add_http_header("HTTP/1.0 403 Permission Denied"); $this->display_error($page, "Permission Denied", "You do not have permission to access this page"); } diff --git a/themes/old_default/themelet.class.php b/themes/old_default/themelet.class.php index 09eb031e..41c5cf5e 100644 --- a/themes/old_default/themelet.class.php +++ b/themes/old_default/themelet.class.php @@ -16,7 +16,7 @@ class Themelet { * A specific, common error message */ public function display_permission_denied(Page $page) { - header("HTTP/1.0 403 Permission Denied"); + $page->add_http_header("HTTP/1.0 403 Permission Denied"); $this->display_error($page, "Permission Denied", "You do not have permission to access this page"); } diff --git a/themes/warm/themelet.class.php b/themes/warm/themelet.class.php index ddbad7a8..89f4dcf8 100644 --- a/themes/warm/themelet.class.php +++ b/themes/warm/themelet.class.php @@ -18,7 +18,7 @@ class Themelet { * A specific, common error message */ public function display_permission_denied(Page $page) { - header("HTTP/1.0 403 Permission Denied"); + $page->add_http_header("HTTP/1.0 403 Permission Denied"); $this->display_error($page, "Permission Denied", "You do not have permission to access this page"); } From c2ef8736b8fd0c410457fb27c38ae5adc7e2590d Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 4 Sep 2011 14:19:06 -0400 Subject: [PATCH 18/20] Fixed a typo. --- core/page.class.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/page.class.php b/core/page.class.php index b1940cd3..c2af3868 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -167,13 +167,11 @@ class Page { public function display() { global $page; - add_http_header("Content-type: {$this->type}", 1); - add_http_header("X-Powered-By: SCore-".SCORE_VERSION, 2); + $this->add_http_header("Content-type: {$this->type}", 1); + $this->add_http_header("X-Powered-By: SCore-".SCORE_VERSION, 2); if (!headers_sent()) { - foreach($this->http_headers as $head){ - header($head); - } + foreach($this->http_headers as $head)( header($head); ) } else { print "Error: Headers have already been sent to the client."; } From 1c8ba8dc26511af7982ed516f28aa4fff04ce9e8 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 4 Sep 2011 14:24:14 -0400 Subject: [PATCH 19/20] Wrong brackets. --- core/page.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/page.class.php b/core/page.class.php index c2af3868..d3879853 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -171,7 +171,7 @@ class Page { $this->add_http_header("X-Powered-By: SCore-".SCORE_VERSION, 2); if (!headers_sent()) { - foreach($this->http_headers as $head)( header($head); ) + foreach($this->http_headers as $head){ header($head); } } else { print "Error: Headers have already been sent to the client."; } From 808e477f34802769658e13868af5af4482ed1ba1 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Mon, 5 Sep 2011 14:47:30 -0400 Subject: [PATCH 20/20] Admins can configure the browser Image Expiration now. Also renamed the config option for jQuery image delete. --- ext/image/main.php | 24 ++++++++++++++++++++---- ext/image/theme.php | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ext/image/main.php b/ext/image/main.php index aea0ff54..a42c7916 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -138,11 +138,12 @@ class ImageIO extends SimpleExtension { $config->set_default_string('thumb_convert_path', 'convert.exe'); $config->set_default_bool('image_show_meta', false); - $config->set_default_bool('jquery_confirm', true); + $config->set_default_bool('image_jquery_confirm', true); $config->set_default_string('image_ilink', ''); $config->set_default_string('image_tlink', ''); $config->set_default_string('image_tip', '$tags // $size // $filesize'); $config->set_default_string('upload_collision_handler', 'error'); + $config->set_default_int('image_expires', (60*60*24*365) ); // defaults to one year } public function onPageRequest($event) { @@ -242,7 +243,17 @@ class ImageIO extends SimpleExtension { if(!in_array("OS", $_SERVER) || $_SERVER["OS"] != 'Windows_NT') { $sb->add_bool_option("image_show_meta", "
Show metadata: "); } - $sb->add_bool_option("jquery_confirm", "
Confirm Delete with jQuery: "); + $sb->add_bool_option("image_jquery_confirm", "
Confirm Delete with jQuery: "); + + $expires = array(); + $expires['1 Minute'] = 60; + $expires['1 Hour'] = 3600; + $expires['1 Day'] = 86400; + $expires['1 Month (31 days)'] = 2678400; //(60*60*24*31) + $expires['1 Year'] = 31536000; // 365 days (60*60*24*365) + $expires['Never'] = 3153600000; // 100 years.. + $sb->add_choice_option("image_expires", $expires, "
Image Expiration: "); + $event->panel->add_block($sb); $thumbers = array(); @@ -371,9 +382,14 @@ class ImageIO extends SimpleExtension { $page->add_http_header("HTTP/1.0 304 Not Modified",3); } else { - /* FIXME: The Expires date Needs to be admin-configurable */ $page->add_http_header("Last-Modified: $gmdate_mod"); - $page->add_http_header("Expires: Fri, 2 Sep 2101 12:42:42 GMT"); // War was beginning + + if ( $config->get_int("image_expires") ) { + $expires = date(DATE_RFC1123, time() + $config->get_int("image_expires")); + } else { + $expires = 'Fri, 2 Sep 2101 12:42:42 GMT'; // War was beginning + } + $page->add_http_header('Expires: '.$expires); } } else { diff --git a/ext/image/theme.php b/ext/image/theme.php index 648e8531..8d0537a1 100644 --- a/ext/image/theme.php +++ b/ext/image/theme.php @@ -9,7 +9,7 @@ class ImageIOTheme { public function get_deleter_html($image_id) { global $config; - if($config->get_bool("jquery_confirm")) { + if($config->get_bool("image_jquery_confirm")) { $html = " ".make_form(make_link("image_admin/delete"),'POST',false,'delete_image')."