Merge pull request #367 from DakuTree/patch

Metatag tweaks + Fix for issue 359 & 362.
This commit is contained in:
Shish 2014-01-25 06:58:35 -08:00
commit d7ce075a43
14 changed files with 243 additions and 93 deletions

View file

@ -26,6 +26,7 @@
$tag_n = 0; // temp hack $tag_n = 0; // temp hack
$_flexihash = null; $_flexihash = null;
$_fh_last_opts = null; $_fh_last_opts = null;
$order_sql = null; // this feels ugly
require_once "lib/flexihash.php"; require_once "lib/flexihash.php";
@ -114,7 +115,7 @@ class Image {
assert(is_numeric($start)); assert(is_numeric($start));
assert(is_numeric($limit)); assert(is_numeric($limit));
assert(is_array($tags)); assert(is_array($tags));
global $database, $user; global $database, $user, $config, $order_sql;
$images = array(); $images = array();
@ -128,13 +129,15 @@ class Image {
} }
$querylet = Image::build_search_querylet($tags); $querylet = Image::build_search_querylet($tags);
$querylet->append(new Querylet("ORDER BY images.id DESC LIMIT :limit OFFSET :offset", array("limit"=>$limit, "offset"=>$start))); $querylet->append(new Querylet(" ORDER BY images.".($order_sql ?: $config->get_string("index_order"))));
$querylet->append(new Querylet(" LIMIT :limit OFFSET :offset", array("limit"=>$limit, "offset"=>$start)));
#var_dump($querylet->sql); var_dump($querylet->variables); #var_dump($querylet->sql); var_dump($querylet->variables);
$result = $database->execute($querylet->sql, $querylet->variables); $result = $database->execute($querylet->sql, $querylet->variables);
while($row = $result->fetch()) { while($row = $result->fetch()) {
$images[] = new Image($row); $images[] = new Image($row);
} }
$order_sql = null;
return $images; return $images;
} }
@ -476,11 +479,11 @@ class Image {
$this->delete_tags_from_image(); $this->delete_tags_from_image();
// insert each new tags // insert each new tags
foreach($tags as $tag) { foreach($tags as $tag) {
if(preg_match("/^source=(.*)$/i", $tag, $matches)) { if(preg_match("/^source[=|:](.*)$/i", $tag, $matches)) {
$this->set_source($matches[1]); $this->set_source($matches[1]);
continue; continue;
} }
if(preg_match("/^pool=(.*)$/i", $tag, $matches)) { if(preg_match("/^pool[=|:](.*)$/i", $tag, $matches)) {
if(class_exists("Pools")) { if(class_exists("Pools")) {
$pls = new Pools(); $pls = new Pools();
$pls->add_post_from_tag($matches[1], $this->id); $pls->add_post_from_tag($matches[1], $this->id);
@ -663,6 +666,8 @@ class Image {
} }
} }
$terms = Tag::resolve_aliases($terms);
// parse the words that are searched for into // parse the words that are searched for into
// various types of querylet // various types of querylet
foreach($terms as $term) { foreach($terms as $term) {
@ -675,8 +680,6 @@ class Image {
continue; continue;
} }
$term = Tag::resolve_alias($term);
$stpe = new SearchTermParseEvent($term, $terms); $stpe = new SearchTermParseEvent($term, $terms);
send_event($stpe); send_event($stpe);
if($stpe->is_querylet_set()) { if($stpe->is_querylet_set()) {
@ -824,6 +827,8 @@ class Image {
} }
} }
$terms = Tag::resolve_aliases($terms);
reset($terms); // rewind to first element in array. reset($terms); // rewind to first element in array.
// turn each term into a specific type of querylet // turn each term into a specific type of querylet
@ -833,8 +838,6 @@ class Image {
$negative = true; $negative = true;
$term = substr($term, 1); $term = substr($term, 1);
} }
$term = Tag::resolve_alias($term);
$stpe = new SearchTermParseEvent($term, $terms); $stpe = new SearchTermParseEvent($term, $terms);
send_event($stpe); send_event($stpe);
@ -1082,11 +1085,22 @@ class Tag {
assert(is_array($tags)); assert(is_array($tags));
$new = array(); $new = array();
foreach($tags as $tag) {
$new_set = explode(' ', Tag::resolve_alias($tag)); $i = 0;
foreach($new_set as $new_one) { $tag_count = count($tags);
$new[] = $new_one; while($i<$tag_count) {
$aliases = explode(' ', Tag::resolve_alias($tags[$i]));
foreach($aliases as $alias){
if(!in_array($alias, $new)){
if($tags[$i] == $alias){
$new[] = $alias;
}elseif(!in_array($alias, $tags)){
$tags[] = $alias;
$tag_count++;
}
}
} }
$i++;
} }
$new = array_iunique($new); // remove any duplicate tags $new = array_iunique($new); // remove any duplicate tags

View file

@ -509,14 +509,15 @@ function captcha_check() {
* @param string &$file File path * @param string &$file File path
* @return string * @return string
*/ */
function getMimeType($file, $ext="") { function getMimeType($file, $ext="", $list=false) {
// Static extension lookup // Static extension lookup
$ext = strtolower($ext); $ext = strtolower($ext);
static $exts = array( static $exts = array(
'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png',
'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon',
'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf', 'swf' => 'application/x-shockwave-flash', 'video/x-flv' => 'flv',
'svg' => 'image/svg+xml', 'pdf' => 'application/pdf',
'zip' => 'application/zip', 'gz' => 'application/x-gzip', 'zip' => 'application/zip', 'gz' => 'application/x-gzip',
'tar' => 'application/x-tar', 'bz' => 'application/x-bzip', 'tar' => 'application/x-tar', 'bz' => 'application/x-bzip',
'bz2' => 'application/x-bzip2', 'txt' => 'text/plain', 'bz2' => 'application/x-bzip2', 'txt' => 'text/plain',
@ -529,6 +530,8 @@ function getMimeType($file, $ext="") {
'mp4' => 'video/mp4', 'ogv' => 'video/ogg', 'webm' => 'video/webm' 'mp4' => 'video/mp4', 'ogv' => 'video/ogg', 'webm' => 'video/webm'
); );
if ($list == true){ return $exts; }
if (isset($exts[$ext])) { return $exts[$ext]; } if (isset($exts[$ext])) { return $exts[$ext]; }
$type = false; $type = false;
@ -556,6 +559,17 @@ function getMimeType($file, $ext="") {
return 'application/octet-stream'; return 'application/octet-stream';
} }
function getExtension ($mime_type){
if(empty($mime_type)){
return false;
}
$extensions = getMimeType(null, null, true);
$ext = array_search($mime_type, $extensions);
return ($ext ?: false);
}
/** /**
* @private * @private
*/ */
@ -801,17 +815,24 @@ function transload($url, $mfile) {
$ch = curl_init($url); $ch = curl_init($url);
$fp = fopen($mfile, "w"); $fp = fopen($mfile, "w");
curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_USERAGENT, "Shimmie-".VERSION); curl_setopt($ch, CURLOPT_USERAGENT, "Shimmie-".VERSION);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_exec($ch); $response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = http_parse_headers(implode("\n", preg_split('/\R/', rtrim(substr($response, 0, $header_size)))));
$body = substr($response, $header_size);
curl_close($ch); curl_close($ch);
fwrite($fp, $body);
fclose($fp); fclose($fp);
return true; return $headers;
} }
if($config->get_string("transload_engine") === "wget") { if($config->get_string("transload_engine") === "wget") {
@ -839,12 +860,36 @@ function transload($url, $mfile) {
fwrite($fp, $data); fwrite($fp, $data);
fclose($fp); fclose($fp);
return true; $headers = http_parse_headers(implode("\n", $http_response_header));
return $headers;
} }
return false; return false;
} }
if (!function_exists('http_parse_headers')) { #http://www.php.net/manual/en/function.http-parse-headers.php#112917
function http_parse_headers ($raw_headers){
$headers = array(); // $headers = [];
foreach (explode("\n", $raw_headers) as $i => $h) {
$h = explode(':', $h, 2);
if (isset($h[1])){
if(!isset($headers[$h[0]])){
$headers[$h[0]] = trim($h[1]);
}else if(is_array($headers[$h[0]])){
$tmp = array_merge($headers[$h[0]],array(trim($h[1])));
$headers[$h[0]] = $tmp;
}else{
$tmp = array_merge(array($headers[$h[0]]),array(trim($h[1])));
$headers[$h[0]] = $tmp;
}
}
}
return $headers;
}
}
$_included = array(); $_included = array();
/** /**

View file

@ -45,7 +45,7 @@ class Artists extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/^author=(.*)$/", $event->term, $matches)) { if(preg_match("/^author[=|:](.*)$/", $event->term, $matches)) {
$char = $matches[1]; $char = $matches[1];
$event->add_querylet(new Querylet("Author = :author_char", array("author_char"=>$char))); $event->add_querylet(new Querylet("Author = :author_char", array("author_char"=>$char)));
} }

View file

@ -262,12 +262,12 @@ class CommentList extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/comments(<|>|<=|>=|=)(\d+)/", $event->term, $matches)) { if(preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = ltrim($matches[1], ":") ?: "=";
$comments = $matches[2]; $comments = $matches[2];
$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)")); $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)"));
} }
else if(preg_match("/commented_by=(.*)/i", $event->term, $matches)) { else if(preg_match("/^commented_by[=|:](.*)$/i", $event->term, $matches)) {
global $database; global $database;
$user = User::by_name($matches[1]); $user = User::by_name($matches[1]);
if(!is_null($user)) { if(!is_null($user)) {
@ -279,7 +279,7 @@ class CommentList extends Extension {
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)"));
} }
else if(preg_match("/commented_by_userid=([0-9]+)/i", $event->term, $matches)) { else if(preg_match("/^commented_by_userno[=|:]([0-9]+)$/i", $event->term, $matches)) {
$user_id = int_escape($matches[1]); $user_id = int_escape($matches[1]);
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = $user_id)"));
} }

View file

@ -54,14 +54,6 @@ class DanbooruApi extends Extension {
} }
} }
public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array();
if(preg_match("/^md5:([0-9a-fA-F]*)$/i", $event->term, $matches)) {
$hash = strtolower($matches[1]);
$event->add_querylet(new Querylet("images.hash = '$hash'")); // :-O
}
}
// Danbooru API // Danbooru API
private function api_danbooru(PageRequestEvent $event) private function api_danbooru(PageRequestEvent $event)
{ {

View file

@ -117,12 +117,12 @@ class Favorites extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/favorites(<|>|<=|>=|=)(\d+)/", $event->term, $matches)) { if(preg_match("/^favorites([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = ltrim($matches[1], ":") ?: "=";
$favorites = $matches[2]; $favorites = $matches[2];
$event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE favorites $cmp $favorites)")); $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE favorites $cmp $favorites)"));
} }
else if(preg_match("/favorited_by=(.*)/i", $event->term, $matches)) { else if(preg_match("/^favorited_by[=|:](.*)$/i", $event->term, $matches)) {
global $database; global $database;
$user = User::by_name($matches[1]); $user = User::by_name($matches[1]);
if(!is_null($user)) { if(!is_null($user)) {
@ -134,7 +134,7 @@ class Favorites extends Extension {
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)"));
} }
else if(preg_match("/favorited_by_userno=([0-9]+)/i", $event->term, $matches)) { else if(preg_match("/^favorited_by_userno[=|:](\d+)$/i", $event->term, $matches)) {
$user_id = int_escape($matches[1]); $user_id = int_escape($matches[1]);
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = $user_id)"));
} }

View file

@ -21,6 +21,16 @@
* <li>size&gt;=500x500 -- no small images * <li>size&gt;=500x500 -- no small images
* <li>size&lt;1000x1000 -- no large images * <li>size&lt;1000x1000 -- no large images
* </ul> * </ul>
* <li>width (=, &lt;, &gt;, &lt;=, &gt;=) width, eg
* <ul>
* <li>width=1024 -- find images with 1024 width
* <li>width>2000 -- find images bigger than 2000 width
* </ul>
* <li>height (=, &lt;, &gt;, &lt;=, &gt;=) height, eg
* <ul>
* <li>height=768 -- find images with 768 height
* <li>height>1000 -- find images bigger than 1000 height
* </ul>
* <li>ratio (=, &lt;, &gt;, &lt;=, &gt;=) width : height, eg * <li>ratio (=, &lt;, &gt;, &lt;=, &gt;=) width : height, eg
* <ul> * <ul>
* <li>ratio=4:3, ratio=16:9 -- standard wallpaper * <li>ratio=4:3, ratio=16:9 -- standard wallpaper
@ -38,41 +48,67 @@
* <li>id<20 -- search only the first few images * <li>id<20 -- search only the first few images
* <li>id>=500 -- search later images * <li>id>=500 -- search later images
* </ul> * </ul>
* <li>user=Username, eg * <li>user=Username & poster=Username, eg
* <ul> * <ul>
* <li>user=Shish -- find all of Shish's posts * <li>user=Shish -- find all of Shish's posts
* <li>poster=Shish -- same as above
* </ul> * </ul>
* <li>hash=md5sum, eg * <li>user_id=userID & poster_id=userID, eg
* <ul>
* <li>user_id=2 -- find all posts by user id 2
* <li>poster_id=2 -- same as above
* </ul>
* <li>hash=md5sum & md5=md5sum, eg
* <ul> * <ul>
* <li>hash=bf5b59173f16b6937a4021713dbfaa72 -- find the "Taiga want up!" image * <li>hash=bf5b59173f16b6937a4021713dbfaa72 -- find the "Taiga want up!" image
* <li>md5=bf5b59173f16b6937a4021713dbfaa72 -- same as above
* </ul> * </ul>
* <li>filetype=type, eg * <li>filetype=type & ext=type, eg
* <ul> * <ul>
* <li>filetype=png -- find all PNG images * <li>filetype=png -- find all PNG images
* <li>ext=png -- same as above
* </ul> * </ul>
* <li>filename=blah, eg * <li>filename=blah & name=blah, eg
* <ul> * <ul>
* <li>filename=kitten -- find all images with "kitten" in the original filename * <li>filename=kitten -- find all images with "kitten" in the original filename
* <li>name=kitten -- same as above
* </ul> * </ul>
* <li>posted (=, &lt;, &gt;, &lt;=, &gt;=) date, eg * <li>posted (=, &lt;, &gt;, &lt;=, &gt;=) date, eg
* <ul> * <ul>
* <li>posted&gt;=2009-12-25 posted&lt;=2010-01-01 -- find images posted between christmas and new year * <li>posted&gt;=2009-12-25 posted&lt;=2010-01-01 -- find images posted between christmas and new year
* </ul> * </ul>
* <li>tags (=, &lt;, &gt;, &lt;=, &gt;=) count, eg
* <ul>
* <li>tags=1 -- search for images with only 1 tag
* <li>tags>=10 -- search for images with 10 or more tags
* <li>tags<25 -- search for images with less than 25 tags
* </ul>
* <li>source=(URL, any, none) eg
* <ul>
* <li>source=http://example.com -- find all images with "http://example.com" in the source
* <li>source=any -- find all images with a source
* <li>source=none -- find all images without a source
* </ul>
* <li>order=(id, width, height, filesize, filename)_(ASC, DESC), eg
* <ul>
* <li>order=width -- find all images sorted from highest > lowest width
* <li>order=filesize_asc -- find all images sorted from lowest > highest filesize
* </ul>
* </ul> * </ul>
* <p>Search items can be combined to search for images which match both, * <p>Search items can be combined to search for images which match both,
* or you can stick "-" in front of an item to search for things that don't * or you can stick "-" in front of an item to search for things that don't
* match it. * match it.
* <p>Metatags can be followed by ":" rather than "=" if you prefer.
* <br />I.E: "posted:2014-01-01", "id:>=500" etc.
* <p>Some search methods provided by extensions: * <p>Some search methods provided by extensions:
* <ul> * <ul>
* <li>Danbooru API
* <ul>
* <li>md5:[hash] -- same as "hash=", but the API calls it by a different name
* </ul>
* <li>Numeric Score * <li>Numeric Score
* <ul> * <ul>
* <li>score (=, &lt;, &gt;, &lt;=, &gt;=) number -- seach by score * <li>score (=, &lt;, &gt;, &lt;=, &gt;=) number -- seach by score
* <li>upvoted_by=Username -- search for a user's likes * <li>upvoted_by=Username -- search for a user's likes
* <li>downvoted_by=Username -- search for a user's dislikes * <li>downvoted_by=Username -- search for a user's dislikes
* <li>upvoted_by_id=UserID -- search for a user's likes by user ID
* <li>downvoted_by_id=UserID -- search for a user's dislikes by user ID
* </ul> * </ul>
* <li>Image Rating * <li>Image Rating
* <ul> * <ul>
@ -81,11 +117,29 @@
* <li>Favorites * <li>Favorites
* <ul> * <ul>
* <li>favorites (=, &lt;, &gt;, &lt;=, &gt;=) number -- search for images favourited a certain number of times * <li>favorites (=, &lt;, &gt;, &lt;=, &gt;=) number -- search for images favourited a certain number of times
* <li>favourited_by=Username -- search for a user's choices * <li>favourited_by=Username -- search for a user's choices by username
* <li>favorited_by_userno=UserID -- search for a user's choice by userID
* </ul> * </ul>
* <li>Notes * <li>Notes
* <ul> * <ul>
* <li>notes (=, &lt;, &gt;, &lt;=, &gt;=) number -- search by the number of notes an image has * <li>notes (=, &lt;, &gt;, &lt;=, &gt;=) number -- search by the number of notes an image has
* <li>notes_by=Username -- search for images containing notes created by username
* <li>notes_by_userno=UserID -- search for images containing notes created by userID
* </ul>
* <li>Artists
* <ul>
* <li>author=ArtistName -- search for images by artist
* </ul>
* <li>Image Comments
* <ul>
* <li>comments (=, &lt;, &gt;, &lt;=, &gt;=) number -- search for images by number of comments
* <li>commented_by=Username -- search for images containing user's comments by username
* <li>commented_by_userno=UserID -- search for images containing user's comments by userID
* </ul>
* <li>Pools
* <ul>
* <li>pool=(PoolID, any, none) -- search for images in a pool by PoolID.
* <li>pool_by_name=PoolName -- search for images in a pool by PoolName. underscores are replaced with spaces
* </ul> * </ul>
* </ul> * </ul>
*/ */
@ -141,6 +195,7 @@ class Index extends Extension {
global $config; global $config;
$config->set_default_int("index_images", 24); $config->set_default_int("index_images", 24);
$config->set_default_bool("index_tips", true); $config->set_default_bool("index_tips", true);
$config->set_default_string("index_order", "id DESC");
} }
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
@ -240,48 +295,70 @@ class Index extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
// check for tags first as tag based searches are more common. // check for tags first as tag based searches are more common.
if(preg_match("/tags(<|>|<=|>=|=)(\d+)/", $event->term, $matches)) { if(preg_match("/^tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = ltrim($matches[1], ":") ?: "=";
$tags = $matches[2]; $tags = $matches[2];
$event->add_querylet(new Querylet('images.id IN (SELECT DISTINCT image_id FROM image_tags GROUP BY image_id HAVING count(image_id) '.$cmp.' '.$tags.')')); $event->add_querylet(new Querylet('images.id IN (SELECT DISTINCT image_id FROM image_tags GROUP BY image_id HAVING count(image_id) '.$cmp.' '.$tags.')'));
} }
else if(preg_match("/^ratio(<|>|<=|>=|=)(\d+):(\d+)$/", $event->term, $matches)) { else if(preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = preg_replace('/^:/', '=', $matches[1]);
$args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])); $args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3]));
$event->add_querylet(new Querylet("width / height $cmp :width{$this->stpen} / :height{$this->stpen}", $args)); $event->add_querylet(new Querylet("width / height $cmp :width{$this->stpen} / :height{$this->stpen}", $args));
} }
else if(preg_match("/^(filesize|id)(<|>|<=|>=|=)(\d+[kmg]?b?)$/i", $event->term, $matches)) { else if(preg_match("/^(filesize|id)([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+[kmg]?b?)$/i", $event->term, $matches)) {
$col = $matches[1]; $col = $matches[1];
$cmp = $matches[2]; $cmp = ltrim($matches[2], ":") ?: "=";
$val = parse_shorthand_int($matches[3]); $val = parse_shorthand_int($matches[3]);
$event->add_querylet(new Querylet("images.$col $cmp :val{$this->stpen}", array("val{$this->stpen}"=>$val))); $event->add_querylet(new Querylet("images.$col $cmp :val{$this->stpen}", array("val{$this->stpen}"=>$val)));
} }
else if(preg_match("/^(hash|md5)=([0-9a-fA-F]*)$/i", $event->term, $matches)) { else if(preg_match("/^(hash|md5)[=|:]([0-9a-fA-F]*)$/i", $event->term, $matches)) {
$hash = strtolower($matches[2]); $hash = strtolower($matches[2]);
$event->add_querylet(new Querylet('images.hash = :hash', array("hash" => $hash))); $event->add_querylet(new Querylet('images.hash = :hash', array("hash" => $hash)));
} }
else if(preg_match("/^(filetype|ext)=([a-zA-Z0-9]*)$/i", $event->term, $matches)) { else if(preg_match("/^(filetype|ext)[=|:]([a-zA-Z0-9]*)$/i", $event->term, $matches)) {
$ext = strtolower($matches[2]); $ext = strtolower($matches[2]);
$event->add_querylet(new Querylet('images.ext = :ext', array("ext" => $ext))); $event->add_querylet(new Querylet('images.ext = :ext', array("ext" => $ext)));
} }
else if(preg_match("/^(filename|name)=([a-zA-Z0-9]*)$/i", $event->term, $matches)) { else if(preg_match("/^(filename|name)[=|:]([a-zA-Z0-9]*)$/i", $event->term, $matches)) {
$filename = strtolower($matches[2]); $filename = strtolower($matches[2]);
$event->add_querylet(new Querylet("images.filename LIKE :filename{$this->stpen}", array("filename{$this->stpen}"=>"%$filename%"))); $event->add_querylet(new Querylet("images.filename LIKE :filename{$this->stpen}", array("filename{$this->stpen}"=>"%$filename%")));
} }
else if(preg_match("/^(source)=([a-zA-Z0-9]*)$/i", $event->term, $matches)) { else if(preg_match("/^(source)[=|:](.*)$/i", $event->term, $matches)) {
$filename = strtolower($matches[2]); $source = strtolower($matches[2]);
$event->add_querylet(new Querylet('images.source LIKE :src', array("src"=>"%$filename%")));
if(preg_match("/^(any|none)$/", $source)){
$not = ($source == "any" ? "NOT" : "");
$event->add_querylet(new Querylet("images.source IS $not NULL"));
}else{
$event->add_querylet(new Querylet('images.source LIKE :src', array("src"=>"%$source%")));
}
} }
else if(preg_match("/^posted(<|>|<=|>=|=)([0-9-]*)$/", $event->term, $matches)) { else if(preg_match("/^posted([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9-]*)$/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = ltrim($matches[1], ":") ?: "=";
$val = $matches[2]; $val = $matches[2];
$event->add_querylet(new Querylet("images.posted $cmp :posted{$this->stpen}", array("posted{$this->stpen}"=>$val))); $event->add_querylet(new Querylet("images.posted $cmp :posted{$this->stpen}", array("posted{$this->stpen}"=>$val)));
} }
else if(preg_match("/^size(<|>|<=|>=|=)(\d+)x(\d+)$/", $event->term, $matches)) { else if(preg_match("/^size([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)x(\d+)$/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = ltrim($matches[1], ":") ?: "=";
$args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])); $args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3]));
$event->add_querylet(new Querylet("width $cmp :width{$this->stpen} AND height $cmp :height{$this->stpen}", $args)); $event->add_querylet(new Querylet("width $cmp :width{$this->stpen} AND height $cmp :height{$this->stpen}", $args));
} }
else if(preg_match("/^width([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "=";
$event->add_querylet(new Querylet("width $cmp :width{$this->stpen}", array("width{$this->stpen}"=>int_escape($matches[2]))));
}
else if(preg_match("/^height([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "=";
$event->add_querylet(new Querylet("height $cmp :height{$this->stpen}",array("height{$this->stpen}"=>int_escape($matches[2]))));
}
else if(preg_match("/^order[=|:](id|width|height|filesize|filename)[_]?(desc|asc)?$/i", $event->term, $matches)){
global $order_sql;
$ord = strtolower($matches[1]);
$default_order_for_column = preg_match("/^(id|filename)$/", $matches[1]) ? "ASC" : "DESC";
$sort = isset($matches[2]) ? strtoupper($matches[2]) : $default_order_for_column;
$order_sql = "$ord $sort";
$event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag
}
$this->stpen++; $this->stpen++;
} }

View file

@ -210,16 +210,16 @@ class Notes extends Extension {
*/ */
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/note=(.*)/i", $event->term, $matches)) { if(preg_match("/^note[=|:](.*)$/i", $event->term, $matches)) {
$notes = int_escape($matches[1]); $notes = int_escape($matches[1]);
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE note = $notes)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE note = $notes)"));
} }
else if(preg_match("/notes(<|>|<=|>=|=)(\d+)/", $event->term, $matches)) { else if(preg_match("/^notes([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)%/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = ltrim($matches[1], ":") ?: "=";
$notes = $matches[2]; $notes = $matches[2];
$event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE notes $cmp $notes)")); $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE notes $cmp $notes)"));
} }
else if(preg_match("/notes_by=(.*)/i", $event->term, $matches)) { else if(preg_match("/^notes_by[=|:](.*)$/i", $event->term, $matches)) {
global $database; global $database;
$user = User::by_name($matches[1]); $user = User::by_name($matches[1]);
if(!is_null($user)) { if(!is_null($user)) {
@ -231,7 +231,7 @@ class Notes extends Extension {
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)"));
} }
else if(preg_match("/notes_by_userno=([0-9]+)/i", $event->term, $matches)) { else if(preg_match("/^notes_by_userno[=|:](\d+)$/i", $event->term, $matches)) {
$user_id = int_escape($matches[1]); $user_id = int_escape($matches[1]);
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = $user_id)"));
} }

View file

@ -31,16 +31,14 @@ class NumericScore extends Extension {
public function onDisplayingImage(DisplayingImageEvent $event) { public function onDisplayingImage(DisplayingImageEvent $event) {
global $user, $page; global $user, $page;
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
$html = $this->theme->get_voter_html($event->image); $this->theme->get_voter($event->image);
$page->add_block(new Block("Image Score", $html, "left", 20));
} }
} }
public function onUserPageBuilding(UserPageBuildingEvent $event) { public function onUserPageBuilding(UserPageBuildingEvent $event) {
global $page, $user; global $page, $user;
if($user->can("edit_other_vote")) { if($user->can("edit_other_vote")) {
$html = $this->theme->get_nuller_html($event->display_user); $this->theme->get_nuller($event->display_user);
$page->add_block(new Block("Votes", $html, "main", 60));
} }
} }
@ -219,12 +217,12 @@ class NumericScore extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/^score(<|<=|=|>=|>)(-?\d+)$/", $event->term, $matches)) { if(preg_match("/^score([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(-?\d+)$/", $event->term, $matches)) {
$cmp = $matches[1]; $cmp = ltrim($matches[1], ":") ?: "=";
$score = $matches[2]; $score = $matches[2];
$event->add_querylet(new Querylet("numeric_score $cmp $score")); $event->add_querylet(new Querylet("numeric_score $cmp $score"));
} }
if(preg_match("/^upvoted_by=(.*)$/", $event->term, $matches)) { if(preg_match("/^upvoted_by[=|:](.*)$/", $event->term, $matches)) {
$duser = User::by_name($matches[1]); $duser = User::by_name($matches[1]);
if(is_null($duser)) { if(is_null($duser)) {
throw new SearchTermParseException( throw new SearchTermParseException(
@ -234,7 +232,7 @@ class NumericScore extends Extension {
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
array("ns_user_id"=>$duser->id))); array("ns_user_id"=>$duser->id)));
} }
if(preg_match("/^downvoted_by=(.*)$/", $event->term, $matches)) { if(preg_match("/^downvoted_by[=|:](.*)$/", $event->term, $matches)) {
$duser = User::by_name($matches[1]); $duser = User::by_name($matches[1]);
if(is_null($duser)) { if(is_null($duser)) {
throw new SearchTermParseException( throw new SearchTermParseException(
@ -244,13 +242,13 @@ class NumericScore extends Extension {
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",
array("ns_user_id"=>$duser->id))); array("ns_user_id"=>$duser->id)));
} }
if(preg_match("/^upvoted_by_id=(\d+)$/", $event->term, $matches)) { if(preg_match("/^upvoted_by_id[=|:](\d+)$/", $event->term, $matches)) {
$iid = int_escape($matches[1]); $iid = int_escape($matches[1]);
$event->add_querylet(new Querylet( $event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
array("ns_user_id"=>$iid))); array("ns_user_id"=>$iid)));
} }
if(preg_match("/^downvoted_by_id=(\d+)$/", $event->term, $matches)) { if(preg_match("/^downvoted_by_id[=|:](\d+)$/", $event->term, $matches)) {
$iid = int_escape($matches[1]); $iid = int_escape($matches[1]);
$event->add_querylet(new Querylet( $event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",

View file

@ -1,8 +1,8 @@
<?php <?php
class NumericScoreTheme extends Themelet { class NumericScoreTheme extends Themelet {
public function get_voter_html(Image $image) { public function get_voter(Image $image) {
global $user; global $user, $page;
$i_image_id = int_escape($image->id); $i_image_id = int_escape($image->id);
$i_score = int_escape($image->numeric_score); $i_score = int_escape($image->numeric_score);
@ -46,11 +46,11 @@ class NumericScoreTheme extends Themelet {
</div> </div>
"; ";
} }
return $html; $page->add_block(new Block("Image Score", $html, "left", 20));
} }
public function get_nuller_html(User $duser) { public function get_nuller(User $duser) {
global $user; global $user, $page;
$html = " $html = "
<form action='".make_link("numeric_score/remove_votes_by")."' method='POST'> <form action='".make_link("numeric_score/remove_votes_by")."' method='POST'>
".$user->get_auth_html()." ".$user->get_auth_html()."
@ -58,7 +58,7 @@ class NumericScoreTheme extends Themelet {
<input type='submit' value='Delete all votes by this user'> <input type='submit' value='Delete all votes by this user'>
</form> </form>
"; ";
return $html; $page->add_block(new Block("Votes", $html, "main", 60));
} }
public function view_popular($images, $dte) { public function view_popular($images, $dte) {

View file

@ -293,6 +293,28 @@ class Pools extends Extension {
} }
} }
public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array();
if(preg_match("/^pool[=|:]([0-9]+|any|none)$/", $event->term, $matches)) {
$poolID = $matches[1];
if(preg_match("/^(any|none)$/", $poolID)){
$not = ($poolID == "none" ? "NOT" : "");
$event->add_querylet(new Querylet("images.id $not IN (SELECT DISTINCT image_id FROM pool_images)"));
}else{
$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)"));
}
}
else if(preg_match("/^pool_by_name[=|:](.*)$/", $event->term, $matches)) {
$poolTitle = str_replace("_", " ", $matches[1]);
$pool = $this->get_single_pool_from_title($poolTitle);
$poolID = 0;
if ($pool){ $poolID = $pool['id']; }
$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)"));
}
}
public function add_post_from_tag(/*str*/ $poolTag, /*int*/ $imageID){ public function add_post_from_tag(/*str*/ $poolTag, /*int*/ $imageID){
$poolTag = str_replace("_", " ", $poolTag); $poolTag = str_replace("_", " ", $poolTag);
//First check if pool tag is a title //First check if pool tag is a title

View file

@ -116,7 +116,7 @@ class Ratings extends Extension {
$set = Ratings::privs_to_sql(Ratings::get_user_privs($user)); $set = Ratings::privs_to_sql(Ratings::get_user_privs($user));
$event->add_querylet(new Querylet("rating IN ($set)")); $event->add_querylet(new Querylet("rating IN ($set)"));
} }
if(preg_match("/^rating=(?:([sqeu]+)|(safe|questionable|explicit|unknown))$/D", strtolower($event->term), $matches)) { if(preg_match("/^rating[=|:](?:([sqeu]+)|(safe|questionable|explicit|unknown))$/D", strtolower($event->term), $matches)) {
$ratings = $matches[1] ? $matches[1] : array($matches[2][0]); $ratings = $matches[1] ? $matches[1] : array($matches[2][0]);
$ratings = array_intersect(str_split($ratings), str_split(Ratings::get_user_privs($user))); $ratings = array_intersect(str_split($ratings), str_split(Ratings::get_user_privs($user)));
$set = "'" . join("', '", $ratings) . "'"; $set = "'" . join("', '", $ratings) . "'";
@ -199,7 +199,7 @@ class Ratings extends Extension {
private function no_rating_query($context) { private function no_rating_query($context) {
foreach($context as $term) { foreach($context as $term) {
if(preg_match("/^rating=/", $term)) { if(preg_match("/^rating[=|:]/", $term)) {
return false; return false;
} }
} }

View file

@ -329,9 +329,12 @@ class Upload extends Extension {
} }
$tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload"); $tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload");
$filename = basename($url);
if(!transload($url, $tmp_filename)) { $headers = transload($url, $tmp_filename);
$h_filename = (isset($headers['Content-Disposition']) ? preg_replace('/^.*filename="([^ ]+)"/i', '$1', $headers['Content-Disposition']) : null);
$filename = $h_filename ?: basename($url);
if(!$headers) {
$this->theme->display_upload_error($page, "Error with ".html_escape($filename), $this->theme->display_upload_error($page, "Error with ".html_escape($filename),
"Error reading from ".html_escape($url)); "Error reading from ".html_escape($url));
return false; return false;
@ -341,12 +344,11 @@ class Upload extends Extension {
$this->theme->display_upload_error($page, "Error with ".html_escape($filename), $this->theme->display_upload_error($page, "Error with ".html_escape($filename),
"No data found -- perhaps the site has hotlink protection?"); "No data found -- perhaps the site has hotlink protection?");
$ok = false; $ok = false;
} }else{
else {
global $user; global $user;
$pathinfo = pathinfo($url); $pathinfo = pathinfo($url);
$metadata['filename'] = $pathinfo['basename']; $metadata['filename'] = $filename;
$metadata['extension'] = $pathinfo['extension']; $metadata['extension'] = getExtension($headers['Content-Type']) ?: $pathinfo['extension'];
$metadata['tags'] = $tags; $metadata['tags'] = $tags;
$metadata['source'] = $source; $metadata['source'] = $source;

View file

@ -309,7 +309,7 @@ class UserPage extends Extension {
global $user; global $user;
$matches = array(); $matches = array();
if(preg_match("/^(poster|user)=(.*)$/i", $event->term, $matches)) { if(preg_match("/^(poster|user)[=|:](.*)$/i", $event->term, $matches)) {
$duser = User::by_name($matches[2]); $duser = User::by_name($matches[2]);
if(!is_null($duser)) { if(!is_null($duser)) {
$user_id = $duser->id; $user_id = $duser->id;
@ -319,11 +319,11 @@ class UserPage extends Extension {
} }
$event->add_querylet(new Querylet("images.owner_id = $user_id")); $event->add_querylet(new Querylet("images.owner_id = $user_id"));
} }
else if(preg_match("/^(poster|user)_id=([0-9]+)$/i", $event->term, $matches)) { else if(preg_match("/^(poster|user)_id[=|:]([0-9]+)$/i", $event->term, $matches)) {
$user_id = int_escape($matches[2]); $user_id = int_escape($matches[2]);
$event->add_querylet(new Querylet("images.owner_id = $user_id")); $event->add_querylet(new Querylet("images.owner_id = $user_id"));
} }
else if($user->can("view_ip") && preg_match("/^(poster|user)_ip=([0-9\.]+)$/i", $event->term, $matches)) { else if($user->can("view_ip") && preg_match("/^(poster|user)_ip[=|:]([0-9\.]+)$/i", $event->term, $matches)) {
$user_ip = $matches[2]; // FIXME: ip_escape? $user_ip = $matches[2]; // FIXME: ip_escape?
$event->add_querylet(new Querylet("images.owner_ip = '$user_ip'")); $event->add_querylet(new Querylet("images.owner_ip = '$user_ip'"));
} }