private function get_body() { // returns just the contents of the body global $database; global $config; $base_href = $config->get_string('base_href'); $data_href = get_base_href(); $sitename = $config->get_string('title'); $contact_link = $config->get_string('contact_link'); $counter_dir = $config->get_string('home_counter', 'default'); $total = Image::count_images(); $strtotal = "{$total}"; $num_comma = number_format($total); $counter_text = ""; for ($n = 0; $n < strlen($strtotal); $n++) { $cur = $strtotal[$n]; $counter_text .= " <img alt='{$cur}' src='{$data_href}/ext/home/counters/{$counter_dir}/{$cur}.gif' /> "; } // get the homelinks and process them $main_links = $config->get_string('home_links'); $main_links = str_replace('$base', $base_href, $main_links); $main_links = preg_replace('#\\[(.*?)\\|(.*?)\\]#', "<a href='\\1'>\\2</a>", $main_links); $main_links = str_replace('//', "/", $main_links); $main_text = $config->get_string('home_text'); return $this->theme->build_body($sitename, $main_links, $main_text, $contact_link, $num_comma, $counter_text); }
private function get_body() { // returns just the contents of the body global $config; $base_href = get_base_href(); $sitename = $config->get_string('title'); $contact_link = $config->get_string('contact_link'); $counter_dir = $config->get_string('home_counter', 'default'); $total = Image::count_images(); $strtotal = "{$total}"; $num_comma = number_format($total); $counter_text = ""; $length = strlen($strtotal); for ($n = 0; $n < $length; $n++) { $cur = $strtotal[$n]; $counter_text .= " <img alt='{$cur}' src='{$base_href}/ext/home/counters/{$counter_dir}/{$cur}.gif' /> "; } // get the homelinks and process them if (strlen($config->get_string('home_links', '')) > 0) { $main_links = $config->get_string('home_links'); } else { $main_links = '[url=site://post/list]Posts[/url] [url=site://comment/list]Comments[/url] [url=site://tags]Tags[/url]'; if (class_exists("Pools")) { $main_links .= ' [url=site://pool]Pools[/url]'; } if (class_exists("Wiki")) { $main_links .= ' [url=site://wiki]Wiki[/url]'; } $main_links .= ' [url=site://ext_doc]Documentation[/url]'; } $main_links = format_text($main_links); $main_text = $config->get_string('home_text'); return $this->theme->build_body($sitename, $main_links, $main_text, $contact_link, $num_comma, $counter_text); }
public function onUserPageBuilding($event) { $i_favorites_count = Image::count_images(array("favorited_by={$event->display_user->name}")); $i_days_old = (time() - strtotime($event->display_user->join_date)) / 86400 + 1; $h_favorites_rate = sprintf("%.1f", $i_favorites_count / $i_days_old); $favorites_link = make_link("post/list/favorited_by={$event->display_user->name}/1"); $event->add_stats("<a href='{$favorites_link}'>Images favorited</a>: {$i_favorites_count}, {$h_favorites_rate} per day"); }
/** * Count the number of pages for a given search * * @param string[] $tags * @return float */ public static function count_pages($tags = array()) { assert('is_array($tags)'); global $config; return ceil(Image::count_images($tags) / $config->get_int('index_images')); }
/** * Count the number of pages for a given search */ public static function count_pages($tags = array()) { assert(is_array($tags)); global $config, $database; $images_per_page = $config->get_int('index_width') * $config->get_int('index_height'); return ceil(Image::count_images($tags) / $images_per_page); }
public function onUserPageBuilding(UserPageBuildingEvent $event) { $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("<a href='{$images_link}'>Images uploaded</a>: {$i_image_count}, {$h_image_rate} per day"); }
public function onPageRequest(PageRequestEvent $event) { global $database, $page, $user; if ($event->page_matches("api/shimmie")) { $page->set_mode("data"); $page->set_type("text/plain"); if (!$event->page_matches("api/shimmie/get_tags") && !$event->page_matches("api/shimmie/get_image") && !$event->page_matches("api/shimmie/find_images") && !$event->page_matches("api/shimmie/get_user")) { $page->set_mode("redirect"); $page->set_redirect(make_link("ext_doc/shimmie_api")); } if ($event->page_matches("api/shimmie/get_tags")) { $arg = $event->get_arg(0); if (!empty($arg)) { $all = $database->get_all("SELECT tag FROM tags WHERE tag LIKE ?", array($arg . "%")); } elseif (isset($_GET['tag'])) { $all = $database->get_all("SELECT tag FROM tags WHERE tag LIKE ?", array($_GET['tag'] . "%")); } else { $all = $database->get_all("SELECT tag FROM tags"); } $res = array(); foreach ($all as $row) { $res[] = $row["tag"]; } $page->set_data(json_encode($res)); } if ($event->page_matches("api/shimmie/get_image")) { $arg = $event->get_arg(0); if (!empty($arg)) { $image = Image::by_id(int_escape($event->get_arg(0))); } elseif (isset($_GET['id'])) { $image = Image::by_id(int_escape($_GET['id'])); } // FIXME: handle null image $image->get_tag_array(); // tag data isn't loaded into the object until necessary $safe_image = new _SafeImage($image); $page->set_data(json_encode($safe_image)); } if ($event->page_matches("api/shimmie/find_images")) { $search_terms = $event->get_search_terms(); $page_number = $event->get_page_number(); $page_size = $event->get_page_size(); $images = Image::find_images(($page_number - 1) * $page_size, $page_size, $search_terms); $safe_images = array(); foreach ($images as $image) { $image->get_tag_array(); $safe_images[] = new _SafeImage($image); } $page->set_data(json_encode($safe_images)); } if ($event->page_matches("api/shimmie/get_user")) { $query = $user->id; $type = "id"; if ($event->count_args() == 1) { $query = $event->get_arg(0); } elseif (isset($_GET['id'])) { $query = $_GET['id']; } elseif (isset($_GET['name'])) { $query = $_GET['name']; $type = "name"; } $all = $database->get_row("SELECT id,name,joindate,class FROM users WHERE " . $type . "=?", array($query)); if (!empty($all)) { //FIXME?: For some weird reason, get_all seems to return twice. Unsetting second value to make things look nice.. // - it returns data as eg array(0=>1234, 'id'=>1234, 1=>'bob', 'name'=>bob, ...); for ($i = 0; $i < 4; $i++) { unset($all[$i]); } $all['uploadcount'] = Image::count_images(array("user_id=" . $all['id'])); $all['commentcount'] = $database->get_one("SELECT COUNT(*) AS count FROM comments WHERE owner_id=:owner_id", array("owner_id" => $all['id'])); if (isset($_GET['recent'])) { $recent = $database->get_all("SELECT * FROM images WHERE owner_id=? ORDER BY id DESC LIMIT 0, 5", array($all['id'])); $i = 0; foreach ($recent as $all['recentposts'][$i]) { unset($all['recentposts'][$i]['owner_id']); //We already know the owners id.. unset($all['recentposts'][$i]['owner_ip']); for ($x = 0; $x < 14; $x++) { unset($all['recentposts'][$i][$x]); } if (empty($all['recentposts'][$i]['author'])) { unset($all['recentposts'][$i]['author']); } if ($all['recentposts'][$i]['notes'] > 0) { $all['recentposts'][$i]['has_notes'] = "Y"; } else { $all['recentposts'][$i]['has_notes'] = "N"; } unset($all['recentposts'][$i]['notes']); $i += 1; } } } $page->set_data(json_encode($all)); } } }
private function api_danbooru(PageRequestEvent $event) { global $page; global $config; global $database; global $user; $page->set_mode("data"); $page->set_type("application/xml"); //debug //$page->set_type("text/plain"); $results = array(); $danboorup_kludge = 1; // danboorup for firefox makes broken links out of location: /path /* add_post() Adds a post to the database. Parameters * login: login * password: password * file: file as a multipart form * source: source url * title: title **IGNORED** * tags: list of tags as a string, delimited by whitespace * md5: MD5 hash of upload in hexadecimal format * rating: rating of the post. can be explicit, questionable, or safe. **IGNORED** Notes * The only necessary parameter is tags and either file or source. * If you want to sign your post, you need a way to authenticate your account, either by supplying login and password, or by supplying a cookie. * If an account is not supplied or if it doesnt authenticate, he post will be added anonymously. * If the md5 parameter is supplied and does not match the hash of whats on the server, the post is rejected. Response The response depends on the method used: Post * X-Danbooru-Location set to the URL for newly uploaded post. Get * Redirected to the newly uploaded post. */ if ($event->get_arg(1) == 'add_post' || $event->get_arg(1) == 'post' && $event->get_arg(2) == 'create.xml') { // No XML data is returned from this function $page->set_type("text/plain"); // Check first if a login was supplied, if it wasn't check if the user is logged in via cookie // If all that fails, it's an anonymous upload $this->authenticate_user(); // Now we check if a file was uploaded or a url was provided to transload // Much of this code is borrowed from /ext/upload if ($user->can("create_image")) { if (isset($_FILES['file'])) { // A file was POST'd in $file = $_FILES['file']['tmp_name']; $filename = $_FILES['file']['name']; // If both a file is posted and a source provided, I'm assuming source is the source of the file if (isset($_REQUEST['source']) && !empty($_REQUEST['source'])) { $source = $_REQUEST['source']; } else { $source = null; } } elseif (isset($_FILES['post'])) { $file = $_FILES['post']['tmp_name']['file']; $filename = $_FILES['post']['name']['file']; if (isset($_REQUEST['post']['source']) && !empty($_REQUEST['post']['source'])) { $source = $_REQUEST['post']['source']; } else { $source = null; } } elseif (isset($_REQUEST['source']) || isset($_REQUEST['post']['source'])) { // A url was provided $url = isset($_REQUEST['source']) ? $_REQUEST['source'] : $_REQUEST['post']['source']; $source = $url; $tmp_filename = tempnam("/tmp", "shimmie_transload"); // Are we using fopen wrappers or curl? if ($config->get_string("transload_engine") == "fopen") { $fp = fopen($url, "r"); if (!$fp) { $page->add_http_header("HTTP/1.0 409 Conflict"); $page->add_http_header("X-Danbooru-Errors: fopen read error"); } $data = ""; $length = 0; while (!feof($fp) && $length <= $config->get_int('upload_size')) { $data .= fread($fp, 8192); $length = strlen($data); } fclose($fp); $fp = fopen($tmp_filename, "w"); fwrite($fp, $data); fclose($fp); } if ($config->get_string("transload_engine") == "curl") { $ch = curl_init($url); $fp = fopen($tmp_filename, "w"); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec($ch); curl_close($ch); fclose($fp); } $file = $tmp_filename; $filename = basename($url); } else { // Nothing was specified at all $page->add_http_header("HTTP/1.0 409 Conflict"); $page->add_http_header("X-Danbooru-Errors: no input files"); return; } // Get tags out of url $posttags = Tag::explode(isset($_REQUEST['tags']) ? $_REQUEST['tags'] : $_REQUEST['post']['tags']); $hash = md5_file($file); // Was an md5 supplied? Does it match the file hash? if (isset($_REQUEST['md5'])) { if (strtolower($_REQUEST['md5']) != $hash) { $page->add_http_header("HTTP/1.0 409 Conflict"); $page->add_http_header("X-Danbooru-Errors: md5 mismatch"); return; } } // Upload size checking is now performed in the upload extension // It is also currently broken due to some confusion over file variable ($tmp_filename?) // Does it exist already? $existing = Image::by_hash($hash); if (!is_null($existing)) { $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); } $page->add_http_header("X-Danbooru-Location: {$existinglink}"); return; // wut! } // Fire off an event which should process the new file and add it to the db $fileinfo = pathinfo($filename); $metadata = array(); $metadata['filename'] = $fileinfo['basename']; $metadata['extension'] = $fileinfo['extension']; $metadata['tags'] = $posttags; $metadata['source'] = $source; //log_debug("danbooru_api","========== NEW($filename) ========="); //log_debug("danbooru_api", "upload($filename): fileinfo(".var_export($fileinfo,TRUE)."), metadata(".var_export($metadata,TRUE).")..."); try { $nevent = new DataUploadEvent($file, $metadata); //log_debug("danbooru_api", "send_event(".var_export($nevent,TRUE).")"); send_event($nevent); // If it went ok, grab the id for the newly uploaded image and pass it in the header $newimg = Image::by_hash($hash); // FIXME: Unsupported file doesn't throw an error? $newid = make_link("post/view/" . $newimg->id); if ($danboorup_kludge) { $newid = make_http($newid); } // Did we POST or GET this call? if ($_SERVER['REQUEST_METHOD'] == 'POST') { $page->add_http_header("X-Danbooru-Location: {$newid}"); } else { $page->add_http_header("Location: {$newid}"); } } catch (UploadException $ex) { // Did something screw up? $page->add_http_header("HTTP/1.0 409 Conflict"); $page->add_http_header("X-Danbooru-Errors: exception - " . $ex->getMessage()); return; } } else { $page->add_http_header("HTTP/1.0 409 Conflict"); $page->add_http_header("X-Danbooru-Errors: authentication error"); return; } } /* find_posts() Find all posts that match the search criteria. Posts will be ordered by id descending. Parameters * md5: md5 hash to search for (comma delimited) * id: id to search for (comma delimited) * tags: what tags to search for * limit: limit * page: page number * after_id: limit results to posts added after this id */ if ($event->get_arg(1) == 'find_posts' || $event->get_arg(1) == 'post' && $event->get_arg(2) == 'index.xml') { $this->authenticate_user(); $start = 0; if (isset($_GET['md5'])) { $md5list = explode(",", $_GET['md5']); foreach ($md5list as $md5) { $results[] = Image::by_hash($md5); } $count = count($results); } elseif (isset($_GET['id'])) { $idlist = explode(",", $_GET['id']); foreach ($idlist as $id) { $results[] = Image::by_id($id); } $count = count($results); } else { $limit = isset($_GET['limit']) ? int_escape($_GET['limit']) : 100; // Calculate start offset. if (isset($_GET['page'])) { // Danbooru API uses 'page' >= 1 $start = (int_escape($_GET['page']) - 1) * $limit; } else { if (isset($_GET['pid'])) { // Gelbooru API uses 'pid' >= 0 $start = int_escape($_GET['pid']) * $limit; } else { $start = 0; } } $tags = isset($_GET['tags']) ? Tag::explode($_GET['tags']) : array(); $count = Image::count_images($tags); $results = Image::find_images(max($start, 0), min($limit, 100), $tags); } // Now we have the array $results filled with Image objects // Let's display them $xml = "<posts count=\"{$count}\" offset=\"{$start}\">\n"; foreach ($results as $img) { // Sanity check to see if $img is really an image object // If it isn't (e.g. someone requested an invalid md5 or id), break out of the this if (!is_object($img)) { continue; } $taglist = $img->get_tag_list(); $owner = $img->get_owner(); $previewsize = get_thumbnail_size($img->width, $img->height); $xml .= xml_tag("post", array("id" => $img->id, "md5" => $img->hash, "file_name" => $img->filename, "file_url" => $img->get_image_link(), "height" => $img->height, "width" => $img->width, "preview_url" => $img->get_thumb_link(), "preview_height" => $previewsize[1], "preview_width" => $previewsize[0], "rating" => "u", "date" => $img->posted, "is_warehoused" => false, "tags" => $taglist, "source" => $img->source, "score" => 0, "author" => $owner->name)); } $xml .= "</posts>"; $page->set_data($xml); } /* find_tags() Find all tags that match the search criteria. Parameters * id: A comma delimited list of tag id numbers. * name: A comma delimited list of tag names. * tags: any typical tag query. See Tag#parse_query for details. * after_id: limit results to tags with an id number after after_id. Useful if you only want to refresh */ if ($event->get_arg(1) == 'find_tags') { if (isset($_GET['id'])) { $idlist = explode(",", $_GET['id']); foreach ($idlist as $id) { $sqlresult = $database->execute("SELECT id,tag,count FROM tags WHERE id = ?", array($id)); if (!$sqlresult->EOF) { $results[] = array($sqlresult->fields['count'], $sqlresult->fields['tag'], $sqlresult->fields['id']); } } } elseif (isset($_GET['name'])) { $namelist = explode(",", $_GET['name']); foreach ($namelist as $name) { $sqlresult = $database->execute("SELECT id,tag,count FROM tags WHERE tag = ?", array($name)); if (!$sqlresult->EOF) { $results[] = array($sqlresult->fields['count'], $sqlresult->fields['tag'], $sqlresult->fields['id']); } } } else { $start = isset($_GET['after_id']) ? int_escape($_GET['offset']) : 0; $sqlresult = $database->execute("SELECT id,tag,count FROM tags WHERE count > 0 AND id >= ? ORDER BY id DESC", array($start)); while (!$sqlresult->EOF) { $results[] = array($sqlresult->fields['count'], $sqlresult->fields['tag'], $sqlresult->fields['id']); $sqlresult->MoveNext(); } } // Tag results collected, build XML output $xml = "<tags>\n"; foreach ($results as $tag) { $xml .= "<tag type=\"0\" count=\"{$tag['0']}\" name=\"" . $this->xmlspecialchars($tag[1]) . "\" id=\"{$tag['2']}\"/>\n"; } $xml .= "</tags>"; $page->set_data($xml); } // Hackery for danbooruup 0.3.2 providing the wrong view url. This simply redirects to the proper // Shimmie view page // Example: danbooruup says the url is http://shimmie/api/danbooru/post/show/123 // This redirects that to http://shimmie/post/view/123 if ($event->get_arg(1) == 'post' && $event->get_arg(2) == 'show') { $fixedlocation = make_link("post/view/" . $event->get_arg(3)); $page->set_mode("redirect"); $page->set_redirect($fixedlocation); } }
/** * @param $type * @param $query * @return array */ private function api_get_user($type, $query) { global $database; $all = $database->get_row("SELECT id, name, joindate, class FROM users WHERE {$type}=?", array($query)); if (!empty($all)) { //FIXME?: For some weird reason, get_all seems to return twice. Unsetting second value to make things look nice.. // - it returns data as eg array(0=>1234, 'id'=>1234, 1=>'bob', 'name'=>bob, ...); for ($i = 0; $i < 4; $i++) { unset($all[$i]); } $all['uploadcount'] = Image::count_images(array("user_id=" . $all['id'])); $all['commentcount'] = $database->get_one("SELECT COUNT(*) AS count FROM comments WHERE owner_id=:owner_id", array("owner_id" => $all['id'])); if (isset($_GET['recent'])) { $recent = $database->get_all("SELECT * FROM images WHERE owner_id=? ORDER BY id DESC LIMIT 0, 5", array($all['id'])); $i = 0; foreach ($recent as $all['recentposts'][$i]) { unset($all['recentposts'][$i]['owner_id']); //We already know the owners id.. unset($all['recentposts'][$i]['owner_ip']); for ($x = 0; $x < 14; $x++) { unset($all['recentposts'][$i][$x]); } if (empty($all['recentposts'][$i]['author'])) { unset($all['recentposts'][$i]['author']); } if ($all['recentposts'][$i]['notes'] > 0) { $all['recentposts'][$i]['has_notes'] = "Y"; } else { $all['recentposts'][$i]['has_notes'] = "N"; } unset($all['recentposts'][$i]['notes']); $i += 1; } } } return $all; }
/** * find_posts() * Find all posts that match the search criteria. Posts will be ordered by id descending. * * Parameters: * - md5: md5 hash to search for (comma delimited) * - id: id to search for (comma delimited) * - tags: what tags to search for * - limit: limit * - page: page number * - after_id: limit results to posts added after this id * * @return string * @throws SCoreException */ private function api_find_posts() { $results = array(); $this->authenticate_user(); $start = 0; if (isset($_GET['md5'])) { $md5list = explode(",", $_GET['md5']); foreach ($md5list as $md5) { $results[] = Image::by_hash($md5); } $count = count($results); } elseif (isset($_GET['id'])) { $idlist = explode(",", $_GET['id']); foreach ($idlist as $id) { $results[] = Image::by_id($id); } $count = count($results); } else { $limit = isset($_GET['limit']) ? int_escape($_GET['limit']) : 100; // Calculate start offset. if (isset($_GET['page'])) { // Danbooru API uses 'page' >= 1 $start = (int_escape($_GET['page']) - 1) * $limit; } else { if (isset($_GET['pid'])) { // Gelbooru API uses 'pid' >= 0 $start = int_escape($_GET['pid']) * $limit; } else { $start = 0; } } $tags = isset($_GET['tags']) ? Tag::explode($_GET['tags']) : array(); $count = Image::count_images($tags); $results = Image::find_images(max($start, 0), min($limit, 100), $tags); } // Now we have the array $results filled with Image objects // Let's display them $xml = "<posts count=\"{$count}\" offset=\"{$start}\">\n"; foreach ($results as $img) { // Sanity check to see if $img is really an image object // If it isn't (e.g. someone requested an invalid md5 or id), break out of the this if (!is_object($img)) { continue; } $taglist = $img->get_tag_list(); $owner = $img->get_owner(); $previewsize = get_thumbnail_size($img->width, $img->height); $xml .= xml_tag("post", array("id" => $img->id, "md5" => $img->hash, "file_name" => $img->filename, "file_url" => $img->get_image_link(), "height" => $img->height, "width" => $img->width, "preview_url" => $img->get_thumb_link(), "preview_height" => $previewsize[1], "preview_width" => $previewsize[0], "rating" => "u", "date" => $img->posted, "is_warehoused" => false, "tags" => $taglist, "source" => $img->source, "score" => 0, "author" => $owner->name)); } $xml .= "</posts>"; return $xml; }