/** * @param Image $image * @return string */ private function build_information(Image $image) { $h_owner = html_escape($image->get_owner()->name); $h_ownerlink = "<a href='" . make_link("user/{$h_owner}") . "'>{$h_owner}</a>"; $h_ip = html_escape($image->owner_ip); $h_date = autodate($image->posted); $h_filesize = to_shorthand_int($image->filesize); global $user; if ($user->can("view_ip")) { $h_ownerlink .= " ({$h_ip})"; } $html = "\n\t\tID: {$image->id}\n\t\t<br>Uploader: {$h_ownerlink}\n\t\t<br>Date: {$h_date}\n\t\t<br>Size: {$h_filesize} ({$image->width}x{$image->height})\n\t\t"; if (!is_null($image->source)) { $h_source = html_escape($image->source); if (substr($image->source, 0, 7) != "http://" && substr($image->source, 0, 8) != "https://") { $h_source = "http://" . $h_source; } $html .= "<br>Source: <a href='{$h_source}'>link</a>"; } if (ext_is_live("Ratings")) { if ($image->rating == null || $image->rating == "u") { $image->rating = "u"; } if (ext_is_live("Ratings")) { $h_rating = Ratings::rating_to_human($image->rating); $html .= "<br>Rating: {$h_rating}"; } } return $html; }
public function display_comment_list($images, $page_number, $total_pages, $can_post) { global $config, $page, $user; $page->disable_left(); // parts for the whole page $prev = $page_number - 1; $next = $page_number + 1; $h_prev = $page_number <= 1 ? "Prev" : "<a href='" . make_link("comment/list/{$prev}") . "'>Prev</a>"; $h_index = "<a href='" . make_link() . "'>Index</a>"; $h_next = $page_number >= $total_pages ? "Next" : "<a href='" . make_link("comment/list/{$next}") . "'>Next</a>"; $nav = "{$h_prev} | {$h_index} | {$h_next}"; $page->set_title("Comments"); $page->set_heading("Comments"); $page->add_block(new Block("Navigation", $nav, "left")); $this->display_paginator($page, "comment/list", null, $page_number, $total_pages); // parts for each image $position = 10; $comment_captcha = $config->get_bool('comment_captcha'); $comment_limit = $config->get_int("comment_list_count", 10); foreach ($images as $pair) { $image = $pair[0]; $comments = $pair[1]; $thumb_html = $this->build_thumb_html($image); $s = " "; $un = $image->get_owner()->name; $t = ""; foreach ($image->get_tag_array() as $tag) { $u_tag = url_escape($tag); $t .= "<a href='" . make_link("post/list/{$u_tag}/1") . "'>" . html_escape($tag) . "</a> "; } $p = autodate($image->posted); $r = ext_is_live("Ratings") ? "<b>Rating</b> " . Ratings::rating_to_human($image->rating) : ""; $comment_html = "<b>Date</b> {$p} {$s} <b>User</b> {$un} {$s} {$r}<br><b>Tags</b> {$t}<p> "; $comment_count = count($comments); if ($comment_limit > 0 && $comment_count > $comment_limit) { //$hidden = $comment_count - $comment_limit; $comment_html .= "<p>showing {$comment_limit} of {$comment_count} comments</p>"; $comments = array_slice($comments, -$comment_limit); } foreach ($comments as $comment) { $comment_html .= $this->comment_to_html($comment); } if ($can_post) { if (!$user->is_anonymous()) { $comment_html .= $this->build_postbox($image->id); } else { if (!$comment_captcha) { $comment_html .= $this->build_postbox($image->id); } else { $comment_html .= "<a href='" . make_link("post/view/" . $image->id) . "'>Add Comment</a>"; } } } $html = "\n\t\t\t\t<table><tr>\n\t\t\t\t\t<td style='width: 220px;'>{$thumb_html}</td>\n\t\t\t\t\t<td style='text-align: left;'>{$comment_html}</td>\n\t\t\t\t</tr></table>\n\t\t\t"; $page->add_block(new Block(" ", $html, "main", $position++)); } }
public function setUp() { $class = str_replace("Test", "", get_class($this)); if (!method_exists($class, "is_live") || !ext_is_live($class)) { $this->markTestSkipped("{$class} not supported with this database"); } // things to do after bootstrap and before request // log in as anon $this->log_out(); }
private function count_main($blocks) { $n = 0; foreach ($blocks as $block) { if ($block->section == "main") { $n++; } // more hax. } if (ext_is_live("Chatbox")) { $n--; // even more hax. } return $n; }
public function onPostListBuilding(PostListBuildingEvent $event) { global $config, $database, $page, $user; $fid = $config->get_int("featured_id"); if ($fid > 0) { $image = $database->cache->get("featured_image_object:{$fid}"); if ($image === false) { $image = Image::by_id($fid); if ($image) { // make sure the object is fully populated before saving $image->get_tag_array(); } $database->cache->set("featured_image_object:{$fid}", $image, 600); } if (!is_null($image)) { if (ext_is_live("Ratings")) { if (strpos(Ratings::get_user_privs($user), $image->rating) === FALSE) { return; } } $this->theme->display_featured($page, $image); } } }
/** * Retrieve all the images in a pool, given a pool ID. * * @param PageRequestEvent $event * @param int $poolID */ private function get_posts($event, $poolID) { global $config, $user, $database; $pageNumber = int_escape($event->get_arg(2)); if (is_null($pageNumber) || !is_numeric($pageNumber)) { $pageNumber = 0; } else { if ($pageNumber <= 0) { $pageNumber = 0; } else { $pageNumber--; } } $poolID = int_escape($poolID); $pool = $this->get_pool($poolID); $imagesPerPage = $config->get_int("poolsImagesPerPage"); // WE CHECK IF THE EXTENSION RATING IS INSTALLED, WHICH VERSION AND IF IT // WORKS TO SHOW/HIDE SAFE, QUESTIONABLE, EXPLICIT AND UNRATED IMAGES FROM USER if (ext_is_live("Ratings")) { $rating = Ratings::privs_to_sql(Ratings::get_user_privs($user)); } if (isset($rating) && !empty($rating)) { $result = $database->get_all("\n\t\t\t\t\tSELECT p.image_id\n\t\t\t\t\tFROM pool_images AS p\n\t\t\t\t\tINNER JOIN images AS i ON i.id = p.image_id\n\t\t\t\t\tWHERE p.pool_id = :pid AND i.rating IN ({$rating})\n\t\t\t\t\tORDER BY p.image_order ASC\n\t\t\t\t\tLIMIT :l OFFSET :o", array("pid" => $poolID, "l" => $imagesPerPage, "o" => $pageNumber * $imagesPerPage)); $totalPages = ceil($database->get_one("\n\t\t\t\t\tSELECT COUNT(*) \n\t\t\t\t\tFROM pool_images AS p\n\t\t\t\t\tINNER JOIN images AS i ON i.id = p.image_id\n\t\t\t\t\tWHERE pool_id=:pid AND i.rating IN ({$rating})", array("pid" => $poolID)) / $imagesPerPage); } else { $result = $database->get_all("\n\t\t\t\t\tSELECT image_id\n\t\t\t\t\tFROM pool_images\n\t\t\t\t\tWHERE pool_id=:pid\n\t\t\t\t\tORDER BY image_order ASC\n\t\t\t\t\tLIMIT :l OFFSET :o", array("pid" => $poolID, "l" => $imagesPerPage, "o" => $pageNumber * $imagesPerPage)); $totalPages = ceil($database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid" => $poolID)) / $imagesPerPage); } $images = array(); foreach ($result as $singleResult) { $images[] = Image::by_id($singleResult["image_id"]); } $this->theme->view_pool($pool, $images, $pageNumber + 1, $totalPages); }
/** * @param int $current_page */ private function build_page($current_page) { global $database, $user; $where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; $total_pages = $database->cache->get("comment_pages"); if (empty($total_pages)) { $total_pages = (int) ($database->get_one("\n\t\t\t\tSELECT COUNT(c1)\n\t\t\t\tFROM (SELECT COUNT(image_id) AS c1 FROM comments {$where} GROUP BY image_id) AS s1\n\t\t\t") / 10); $database->cache->set("comment_pages", $total_pages, 600); } $total_pages = max($total_pages, 1); $current_page = clamp($current_page, 1, $total_pages); $threads_per_page = 10; $start = $threads_per_page * ($current_page - 1); $result = $database->Execute("\n\t\t\tSELECT image_id,MAX(posted) AS latest\n\t\t\tFROM comments\n\t\t\t{$where}\n\t\t\tGROUP BY image_id\n\t\t\tORDER BY latest DESC\n\t\t\tLIMIT :limit OFFSET :offset\n\t\t", array("limit" => $threads_per_page, "offset" => $start)); $user_ratings = ext_is_live("Ratings") ? Ratings::get_user_privs($user) : ""; $images = array(); while ($row = $result->fetch()) { $image = Image::by_id($row["image_id"]); if (ext_is_live("Ratings") && !is_null($image) && strpos($user_ratings, $image->rating) === FALSE) { $image = null; // this is "clever", I may live to regret it } if (!is_null($image)) { $comments = $this->get_comments($image->id); $images[] = array($image, $comments); } } $this->theme->display_comment_list($images, $current_page, $total_pages, $user->can("create_comment")); }
/** * @param Image $image * @return null * @throws ImageAdditionException */ private function add_image(Image $image) { global $user, $database, $config; /* * Validate things */ if (strlen(trim($image->source)) == 0) { $image->source = null; } /* * Check for an existing image */ $existing = Image::by_hash($image->hash); if (!is_null($existing)) { $handler = $config->get_string("upload_collision_handler"); if ($handler == "merge" || isset($_GET['update'])) { $merged = array_merge($image->get_tag_array(), $existing->get_tag_array()); send_event(new TagSetEvent($existing, $merged)); if (isset($_GET['rating']) && isset($_GET['update']) && ext_is_live("Ratings")) { send_event(new RatingSetEvent($existing, $_GET['rating'])); } if (isset($_GET['source']) && isset($_GET['update'])) { send_event(new SourceSetEvent($existing, $_GET['source'])); } return null; } else { $error = "Image <a href='" . make_link("post/view/{$existing->id}") . "'>{$existing->id}</a> " . "already has hash {$image->hash}:<p>" . $this->theme->build_thumb_html($existing); throw new ImageAdditionException($error); } } // actually insert the info $database->Execute("INSERT INTO images(\n\t\t\t\t\towner_id, owner_ip, filename, filesize,\n\t\t\t\t\thash, ext, width, height, posted, source\n\t\t\t\t)\n\t\t\t\tVALUES (\n\t\t\t\t\t:owner_id, :owner_ip, :filename, :filesize,\n\t\t\t\t\t:hash, :ext, :width, :height, now(), :source\n\t\t\t\t)", array("owner_id" => $user->id, "owner_ip" => $_SERVER['REMOTE_ADDR'], "filename" => substr($image->filename, 0, 60), "filesize" => $image->filesize, "hash" => $image->hash, "ext" => strtolower($image->ext), "width" => $image->width, "height" => $image->height, "source" => $image->source)); $image->id = $database->get_last_insert_id('images_id_seq'); log_info("image", "Uploaded Image #{$image->id} ({$image->hash})"); # at this point in time, the image's tags haven't really been set, # and so, having $image->tag_array set to something is a lie (but # a useful one, as we want to know what the tags are /supposed/ to # be). Here we correct the lie, by first nullifying the wrong tags # then using the standard mechanism to set them properly. $tags_to_set = $image->get_tag_array(); $image->tag_array = array(); send_event(new TagSetEvent($image, $tags_to_set)); if ($image->source) { log_info("core-image", "Source for Image #{$image->id} set to: {$image->source}"); } }
/** * Handle an transload. * * @param string $url * @param mixed $tags * @param string $source * @param string $replace * @return bool Returns TRUE on transload successful. */ private function try_transload($url, $tags, $source, $replace = '') { global $page, $config, $user; $ok = true; // Checks if user is admin > check if you want locked. if ($user->can("edit_image_lock") && !empty($_GET['locked'])) { $locked = bool_escape($_GET['locked']); } // Checks if url contains rating, also checks if the rating extension is enabled. if ($config->get_string("transload_engine", "none") != "none" && ext_is_live("Ratings") && !empty($_GET['rating'])) { // Rating event will validate that this is s/q/e/u $rating = strtolower($_GET['rating']); $rating = $rating[0]; } else { $rating = ""; } $tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload"); // transload() returns Array or Bool, depending on the transload_engine. $headers = transload($url, $tmp_filename); $s_filename = is_array($headers) ? findHeader($headers, 'Content-Disposition') : null; $h_filename = $s_filename ? preg_replace('/^.*filename="([^ ]+)"/i', '$1', $s_filename) : null; $filename = $h_filename ?: basename($url); if (!$headers) { $this->theme->display_upload_error($page, "Error with " . html_escape($filename), "Error reading from " . html_escape($url)); return false; } if (filesize($tmp_filename) == 0) { $this->theme->display_upload_error($page, "Error with " . html_escape($filename), "No data found -- perhaps the site has hotlink protection?"); $ok = false; } else { $pathinfo = pathinfo($url); $metadata = array(); $metadata['filename'] = $filename; $metadata['tags'] = $tags; $metadata['source'] = $url == $source && !$config->get_bool('upload_tlsource') ? "" : $source; $ext = false; if (is_array($headers)) { $ext = getExtension(findHeader($headers, 'Content-Type')); } if ($ext === false) { $ext = $pathinfo['extension']; } $metadata['extension'] = $ext; /* check for locked > adds to metadata if it has */ if (!empty($locked)) { $metadata['locked'] = $locked ? "on" : ""; } /* check for rating > adds to metadata if it has */ if (!empty($rating)) { $metadata['rating'] = $rating; } /* check if we have been given an image ID to replace */ if (!empty($replace)) { $metadata['replace'] = $replace; } $event = new DataUploadEvent($tmp_filename, $metadata); try { send_event($event); } catch (UploadException $ex) { $this->theme->display_upload_error($page, "Error with " . html_escape($url), $ex->getMessage()); $ok = false; } } unlink($tmp_filename); return $ok; }
/** * @param Image $image * @return string */ private function build_tag_map(Image $image) { global $database, $config; $html = ""; $cloud = ""; $precloud = ""; $postcloud = ""; $sort_method = $config->get_string("tageditcloud_sort"); $tags_min = $config->get_int("tageditcloud_minusage"); $used_first = $config->get_bool("tageditcloud_usedfirst"); $max_count = $config->get_int("tageditcloud_maxcount"); $def_count = $config->get_int("tageditcloud_defcount"); $ignore_tags = Tag::explode($config->get_string("tageditcloud_ignoretags")); if (ext_is_live("TagCategories")) { $categories = $database->get_all("SELECT category, color FROM image_tag_categories"); $cat_color = array(); foreach ($categories as $row) { $cat_color[$row['category']] = $row['color']; } } switch ($sort_method) { case 'a': case 'p': default: $order_by = $sort_method == 'a' ? "tag" : "count DESC"; $tag_data = $database->get_all("\n\t\t\t\t\tSELECT tag, FLOOR(LN(LN(count - :tag_min1 + 1)+1)*150)/200 AS scaled, count\n\t\t\t\t\tFROM tags\n\t\t\t\t\tWHERE count >= :tag_min2\n\t\t\t\t\tORDER BY {$order_by}\n\t\t\t\t\tLIMIT :limit", array("tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count)); break; case 'r': $relevant_tags = array_diff($image->get_tag_array(), $ignore_tags); if (count($relevant_tags) == 0) { return null; } $relevant_tags = implode(",", array_map(array($database, "escape"), $relevant_tags)); $tag_data = $database->get_all("\n\t\t\t\t\tSELECT t2.tag AS tag, COUNT(image_id) AS count, FLOOR(LN(LN(COUNT(image_id) - :tag_min1 + 1)+1)*150)/200 AS scaled\n\t\t\t\t\tFROM image_tags it1\n\t\t\t\t\tJOIN image_tags it2 USING(image_id)\n\t\t\t\t\tJOIN tags t1 ON it1.tag_id = t1.id\n\t\t\t\t\tJOIN tags t2 ON it2.tag_id = t2.id\n\t\t\t\t\tWHERE t1.count >= :tag_min2 AND t1.tag IN({$relevant_tags})\n\t\t\t\t\tGROUP BY t2.tag\n\t\t\t\t\tORDER BY count DESC\n\t\t\t\t\tLIMIT :limit", array("tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count)); break; } $counter = 1; foreach ($tag_data as $row) { $full_tag = $row['tag']; if (ext_is_live("TagCategories")) { $tc = explode(':', $row['tag']); if (isset($tc[1]) && isset($cat_color[$tc[0]])) { $h_tag = html_escape($tc[1]); $color = '; color:' . $cat_color[$tc[0]]; } else { $h_tag = html_escape($row['tag']); $color = ''; } } else { $h_tag = html_escape($row['tag']); $color = ''; } $size = sprintf("%.2f", max($row['scaled'], 0.5)); $js = htmlspecialchars('tageditcloud_toggle_tag(this,' . json_encode($full_tag) . ')', ENT_QUOTES); //Ugly, but it works if (array_search($row['tag'], $image->get_tag_array()) !== FALSE) { if ($used_first) { $precloud .= " <span onclick='{$js}' class='tag-selected' style='font-size: {$size}em{$color}' title='{$row['count']}'>{$h_tag}</span> \n"; continue; } else { $entry = " <span onclick='{$js}' class='tag-selected' style='font-size: {$size}em{$color}' title='{$row['count']}'>{$h_tag}</span> \n"; } } else { $entry = " <span onclick='{$js}' style='font-size: {$size}em{$color}' title='{$row['count']}'>{$h_tag}</span> \n"; } if ($counter++ <= $def_count) { $cloud .= $entry; } else { $postcloud .= $entry; } } if ($precloud != '') { $html .= "<div id='tagcloud_set'>{$precloud}</div>"; } if ($postcloud != '') { $postcloud = "<div id='tagcloud_extra' style='display: none;'>{$postcloud}</div>"; } $html .= "<div id='tagcloud_unset'>{$cloud}{$postcloud}</div>"; if ($sort_method != 'a' && $counter > $def_count) { $rem = $counter - $def_count; $html .= "</div><br>[<span onclick='tageditcloud_toggle_extra(this);' style='color: #0000EF; font-weight:bold;'>show {$rem} more tags</span>]"; } return "<div id='tageditcloud' class='tageditcloud'>{$html}</div>"; // FIXME: stupidasallhell }