Merge branch 'master' of git://github.com/shish/shimmie2
This commit is contained in:
		
						commit
						5b0f0b4bef
					
				| @ -142,7 +142,7 @@ abstract class DataHandlerExtension extends Extension { | |||||||
| 	public function onDataUpload(DataUploadEvent $event) { | 	public function onDataUpload(DataUploadEvent $event) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 
 | 
 | ||||||
| 		if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { | 		if(($supported_ext = $this->supported_ext($event->type)) && ($check_contents = $this->check_contents($event->tmpname))) { | ||||||
| 			if(!move_upload_to_archive($event)) return; | 			if(!move_upload_to_archive($event)) return; | ||||||
| 			send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); | 			send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); | ||||||
| 
 | 
 | ||||||
| @ -197,6 +197,9 @@ abstract class DataHandlerExtension extends Extension { | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		elseif($supported_ext && !$check_contents){ | ||||||
|  | 			throw new UploadException("Invalid or corrupted file"); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onThumbnailGeneration(ThumbnailGenerationEvent $event) { | 	public function onThumbnailGeneration(ThumbnailGenerationEvent $event) { | ||||||
|  | |||||||
| @ -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,6 +479,18 @@ 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)) { | ||||||
|  | 					$this->set_source($matches[1]); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				if(preg_match("/^pool[=|:](.*)$/i", $tag, $matches)) { | ||||||
|  | 					if(class_exists("Pools")) { | ||||||
|  | 						$pls = new Pools(); | ||||||
|  | 						$pls->add_post_from_tag($matches[1], $this->id); | ||||||
|  | 					} | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
| 				$id = $database->get_one( | 				$id = $database->get_one( | ||||||
| 						$database->scoreql_to_sql( | 						$database->scoreql_to_sql( | ||||||
| 							"SELECT id FROM tags WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag)" | 							"SELECT id FROM tags WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag)" | ||||||
| @ -651,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) { | ||||||
| @ -663,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()) { | ||||||
| @ -812,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
 | ||||||
| @ -822,8 +839,6 @@ class Image { | |||||||
| 				$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); | ||||||
| 			if($stpe->is_querylet_set()) { | 			if($stpe->is_querylet_set()) { | ||||||
| @ -1070,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
 | ||||||
|  | |||||||
| @ -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(); | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -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))); | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -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)")); | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -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) | ||||||
| 	{ | 	{ | ||||||
|  | |||||||
| @ -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)")); | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -13,6 +13,10 @@ class PixelFileHandlerTheme extends Themelet { | |||||||
| 				foreach ($exif as $key => $section) { | 				foreach ($exif as $key => $section) { | ||||||
| 					foreach ($section as $name => $val) { | 					foreach ($section as $name => $val) { | ||||||
| 						if($key == "IFD0") { | 						if($key == "IFD0") { | ||||||
|  |                             // Cheap fix for array'd values in EXIF-data
 | ||||||
|  |                             if (is_array($val)) { | ||||||
|  |                                 $val = implode(',', $val); | ||||||
|  |                             } | ||||||
| 							$head .= html_escape("$name: $val")."<br>\n"; | 							$head .= html_escape("$name: $val")."<br>\n"; | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  | |||||||
| @ -21,6 +21,16 @@ | |||||||
|  *        <li>size>=500x500 -- no small images |  *        <li>size>=500x500 -- no small images | ||||||
|  *        <li>size<1000x1000 -- no large images |  *        <li>size<1000x1000 -- no large images | ||||||
|  *      </ul> |  *      </ul> | ||||||
|  |  *    <li>width (=, <, >, <=, >=) width, eg | ||||||
|  |  *      <ul> | ||||||
|  |  *        <li>width=1024 -- find images with 1024 width | ||||||
|  |  *        <li>width>2000 -- find images bigger than 2000 width | ||||||
|  |  *      </ul> | ||||||
|  |  *    <li>height (=, <, >, <=, >=) height, eg | ||||||
|  |  *      <ul> | ||||||
|  |  *        <li>height=768 -- find images with 768 height | ||||||
|  |  *        <li>height>1000 -- find images bigger than 1000 height | ||||||
|  |  *      </ul> | ||||||
|  *    <li>ratio (=, <, >, <=, >=) width : height, eg |  *    <li>ratio (=, <, >, <=, >=) 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 (=, <, >, <=, >=) date, eg |  *    <li>posted (=, <, >, <=, >=) date, eg | ||||||
|  *      <ul> |  *      <ul> | ||||||
|  *        <li>posted>=2009-12-25 posted<=2010-01-01 -- find images posted between christmas and new year |  *        <li>posted>=2009-12-25 posted<=2010-01-01 -- find images posted between christmas and new year | ||||||
|  *      </ul> |  *      </ul> | ||||||
|  |  *    <li>tags (=, <, >, <=, >=) 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 (=, <, >, <=, >=) number -- seach by score |  *        <li>score (=, <, >, <=, >=) 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 (=, <, >, <=, >=) number -- search for images favourited a certain number of times |  *        <li>favorites (=, <, >, <=, >=) 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 (=, <, >, <=, >=) number -- search by the number of notes an image has |  *        <li>notes (=, <, >, <=, >=) 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 (=, <, >, <=, >=) 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++; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -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)")); | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -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)", | ||||||
|  | |||||||
| @ -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) { | ||||||
|  | |||||||
| @ -1,8 +1,10 @@ | |||||||
| <?php | <?php | ||||||
|  | 
 | ||||||
| /* | /* | ||||||
|  * Name: Ouroboros API |  * Name: Ouroboros API | ||||||
|  * Author: Diftraku <diftraku[at]derpy.me> |  * Author: Diftraku <diftraku[at]derpy.me> | ||||||
|  * Description: Ouroboros-like API for Shimmie |  * Description: Ouroboros-like API for Shimmie | ||||||
|  |  * Version: 0.2 | ||||||
|  * Documentation: |  * Documentation: | ||||||
|  *   Currently working features |  *   Currently working features | ||||||
|  *   <ul> |  *   <ul> | ||||||
| @ -10,6 +12,7 @@ | |||||||
|  *       <ul> |  *       <ul> | ||||||
|  *         <li>Index/List</li> |  *         <li>Index/List</li> | ||||||
|  *         <li>Show</li> |  *         <li>Show</li> | ||||||
|  |  *         <li>Create</li> | ||||||
|  *       </ul> |  *       </ul> | ||||||
|  *     </li> |  *     </li> | ||||||
|  *     <li>Tag: |  *     <li>Tag: | ||||||
| @ -210,7 +213,10 @@ class _SafeOuroborosImage | |||||||
|         $this->parent_id = null; |         $this->parent_id = null; | ||||||
|         if (defined('ENABLED_EXTS')) { |         if (defined('ENABLED_EXTS')) { | ||||||
|             if (strstr(ENABLED_EXTS, 'rating') !== false) { |             if (strstr(ENABLED_EXTS, 'rating') !== false) { | ||||||
|                 //$this->rating = $img->rating;
 |                 // 'u' is not a "valid" rating
 | ||||||
|  |                 if ($img->rating == 's' || $img->rating == 'q' || $img->rating == 'e') { | ||||||
|  |                     $this->rating = $img->rating; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             if (strstr(ENABLED_EXTS, 'numeric_score') !== false) { |             if (strstr(ENABLED_EXTS, 'numeric_score') !== false) { | ||||||
|                 $this->score = $img->numeric_score; |                 $this->score = $img->numeric_score; | ||||||
| @ -234,6 +240,76 @@ class _SafeOuroborosImage | |||||||
|         $this->sample_url = make_http($img->get_image_link()); |         $this->sample_url = make_http($img->get_image_link()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | class OuroborosPost extends _SafeOuroborosImage | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Multipart File | ||||||
|  |      * @var array | ||||||
|  |      */ | ||||||
|  |     public $file = array(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create with rating locked | ||||||
|  |      * @var bool | ||||||
|  |      */ | ||||||
|  |     public $is_rating_locked = false; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create with notes locked | ||||||
|  |      * @var bool | ||||||
|  |      */ | ||||||
|  |     public $is_note_locked = false; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Initialize an OuroborosPost for creation | ||||||
|  |      * Mainly just acts as a wrapper and validation layer | ||||||
|  |      * @TODO implement more validation from OuroborosAPI | ||||||
|  |      * @param array $post | ||||||
|  |      */ | ||||||
|  |     public function __construct(array $post) | ||||||
|  |     { | ||||||
|  |         if (array_key_exists('tags', $post)) { | ||||||
|  |             $this->tags = $post['tags']; | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('file', $post)) { | ||||||
|  |             if (!is_null($post['file'])) { | ||||||
|  |                 assert(is_array($post['file'])); | ||||||
|  |                 assert(array_key_exists('tmp_name', $post['file'])); | ||||||
|  |                 assert(array_key_exists('name', $post['file'])); | ||||||
|  |                 $this->file = $post['file']; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('rating', $post)) { | ||||||
|  |             assert( | ||||||
|  |                 $post['rating'] == 's' || | ||||||
|  |                 $post['rating'] == 'q' || | ||||||
|  |                 $post['rating'] == 'e' | ||||||
|  |             ); | ||||||
|  |             $this->rating = $post['rating']; | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('source', $post)) { | ||||||
|  |             $this->file_url = $post['source']; | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('sourceurl', $post)) { | ||||||
|  |             $this->source = $post['sourceurl']; | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('description', $post)) { | ||||||
|  |             $this->description = $post['description']; | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('is_rating_locked', $post)) { | ||||||
|  |             $this->is_rating_locked = $post['is_rating_locked']; | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('is_note_locked', $post)) { | ||||||
|  |             $this->is_note_locked = $post['is_note_locked']; | ||||||
|  |         } | ||||||
|  |         if (array_key_exists('parent_id', $post)) { | ||||||
|  |             $this->parent_id = $post['parent_id']; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class _SafeOuroborosTag | class _SafeOuroborosTag | ||||||
| { | { | ||||||
|     public $ambiguous = false; |     public $ambiguous = false; | ||||||
| @ -249,19 +325,43 @@ class _SafeOuroborosTag | |||||||
|         $this->name = $tag['tag']; |         $this->name = $tag['tag']; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| class OuroborosAPI extends Extension | class OuroborosAPI extends Extension | ||||||
| { | { | ||||||
|     private $event; |     private $event; | ||||||
|     const ERROR_HTTP_200 = 'Request was successful'; |     private $type; | ||||||
|     const ERROR_HTTP_403 = 'Access denied'; |     const HEADER_HTTP_200 = 'OK'; | ||||||
|     const ERROR_HTTP_404 = 'Not found'; |     const MSG_HTTP_200 = 'Request was successful'; | ||||||
|     const ERROR_HTTP_420 = 'Record could not be saved'; | 
 | ||||||
|     const ERROR_HTTP_421 = 'User is throttled, try again later'; |     const HEADER_HTTP_403 = 'Forbidden'; | ||||||
|     const ERROR_HTTP_422 = 'The resource is locked and cannot be modified'; |     const MSG_HTTP_403 = 'Access denied'; | ||||||
|     const ERROR_HTTP_423 = 'Resource already exists'; | 
 | ||||||
|     const ERROR_HTTP_424 = 'The given parameters were invalid'; |     const HEADER_HTTP_404 = 'Not found'; | ||||||
|     const ERROR_HTTP_500 = 'Some unknown error occurred on the server'; |     const MSG_HTTP_404 = 'Not found'; | ||||||
|     const ERROR_HTTP_503 = 'Server cannot currently handle the request, try again later'; | 
 | ||||||
|  |     const HEADER_HTTP_418 = 'I\'m a teapot'; | ||||||
|  |     const MSG_HTTP_418 = 'Short and stout'; | ||||||
|  | 
 | ||||||
|  |     const HEADER_HTTP_420 = 'Invalid Record'; | ||||||
|  |     const MSG_HTTP_420 = 'Record could not be saved'; | ||||||
|  | 
 | ||||||
|  |     const HEADER_HTTP_421 = 'User Throttled'; | ||||||
|  |     const MSG_HTTP_421 = 'User is throttled, try again later'; | ||||||
|  | 
 | ||||||
|  |     const HEADER_HTTP_422 = 'Locked'; | ||||||
|  |     const MSG_HTTP_422 = 'The resource is locked and cannot be modified'; | ||||||
|  | 
 | ||||||
|  |     const HEADER_HTTP_423 = 'Already Exists'; | ||||||
|  |     const MSG_HTTP_423 = 'Resource already exists'; | ||||||
|  | 
 | ||||||
|  |     const HEADER_HTTP_424 = 'Invalid Parameters'; | ||||||
|  |     const MSG_HTTP_424 = 'The given parameters were invalid'; | ||||||
|  | 
 | ||||||
|  |     const HEADER_HTTP_500 = 'Internal Server Error'; | ||||||
|  |     const MSG_HTTP_500 = 'Some unknown error occurred on the server'; | ||||||
|  | 
 | ||||||
|  |     const HEADER_HTTP_503 = 'Service Unavailable'; | ||||||
|  |     const MSG_HTTP_503 = 'Server cannot currently handle the request, try again later'; | ||||||
| 
 | 
 | ||||||
|     const ERROR_POST_CREATE_MD5 = 'MD5 mismatch'; |     const ERROR_POST_CREATE_MD5 = 'MD5 mismatch'; | ||||||
|     const ERROR_POST_CREATE_DUPE = 'Duplicate'; |     const ERROR_POST_CREATE_DUPE = 'Duplicate'; | ||||||
| @ -272,120 +372,462 @@ class OuroborosAPI extends Extension | |||||||
| 
 | 
 | ||||||
|         if (preg_match("%\.(xml|json)$%", implode('/', $event->args), $matches) === 1) { |         if (preg_match("%\.(xml|json)$%", implode('/', $event->args), $matches) === 1) { | ||||||
|             $this->event = $event; |             $this->event = $event; | ||||||
|             $type = $matches[1]; |             $this->type = $matches[1]; | ||||||
|             if ($type == 'json') { |             if ($this->type == 'json') { | ||||||
|                 $page->set_type('application/json; charset=utf-8'); |                 $page->set_type('application/json; charset=utf-8'); | ||||||
|             } |             } elseif ($this->type == 'xml') { | ||||||
|             elseif ($type == 'xml') { |                 $page->set_type('text/xml; charset=utf-8'); | ||||||
|                 $page->set_type('text/xml'); |  | ||||||
|             } |             } | ||||||
|             $page->set_mode('data'); |             $page->set_mode('data'); | ||||||
|  |             $this->tryAuth(); | ||||||
| 
 | 
 | ||||||
|             if ($event->page_matches('post')) { |             if ($event->page_matches('post')) { | ||||||
|                 if ($this->match('create')) { |                 if ($this->match('create')) { | ||||||
|                     // Create
 |                     // Create
 | ||||||
|                     $post = array( |                     // @TODO Should move the validation logic into OuroborosPost instead?
 | ||||||
|                         'tags' => !empty($_REQUEST['post']['tags']) ? filter_var($_REQUEST['post']['tags'], FILTER_SANITIZE_STRING) : 'tagme', |                     if ($user->can("create_image")) { | ||||||
|                         'file' => !empty($_REQUEST['post']['file']) ? filter_var($_REQUEST['post']['file'], FILTER_UNSAFE_RAW) : null, |                         $post = array( | ||||||
|                         'rating' => !empty($_REQUEST['post']['rating']) ? filter_var($_REQUEST['post']['rating'], FILTER_SANITIZE_NUMBER_INT) : null, |                             'tags' => !empty($_REQUEST['post']['tags']) ? filter_var( | ||||||
|                         'source' => !empty($_REQUEST['post']['source']) ? filter_var($_REQUEST['post']['source'], FILTER_SANITIZE_URL) : null, |                                     urldecode($_REQUEST['post']['tags']), | ||||||
|                         'sourceurl' => !empty($_REQUEST['post']['sourceurl']) ? filter_var($_REQUEST['post']['sourceurl'], FILTER_SANITIZE_URL) : '', |                                     FILTER_SANITIZE_STRING | ||||||
|                         'description' => !empty($_REQUEST['post']['description']) ? filter_var($_REQUEST['post']['description'], FILTER_SANITIZE_STRING) : '', |                                 ) : 'tagme', | ||||||
|                         'is_rating_locked' => !empty($_REQUEST['post']['is_rating_locked']) ? filter_var($_REQUEST['post']['is_rating_locked'], FILTER_SANITIZE_NUMBER_INT) : false, |                             'file' => !empty($_REQUEST['post']['file']) ? filter_var( | ||||||
|                         'is_note_locked' => !empty($_REQUEST['post']['is_note_locked']) ? filter_var($_REQUEST['post']['is_note_locked'], FILTER_SANITIZE_NUMBER_INT) : false, |                                     $_REQUEST['post']['file'], | ||||||
|                         'parent_id' => !empty($_REQUEST['post']['parent_id']) ? filter_var($_REQUEST['post']['parent_id'], FILTER_SANITIZE_NUMBER_INT) : null, |                                     FILTER_UNSAFE_RAW | ||||||
|                     ); |                                 ) : null, | ||||||
|                     $md5 = !empty($_REQUEST['md5']) ? filter_var($_REQUEST['md5'], FILTER_SANITIZE_STRING) : null; |                             'rating' => !empty($_REQUEST['post']['rating']) ? filter_var( | ||||||
|  |                                     $_REQUEST['post']['rating'], | ||||||
|  |                                     FILTER_SANITIZE_NUMBER_INT | ||||||
|  |                                 ) : 'q', | ||||||
|  |                             'source' => !empty($_REQUEST['post']['source']) ? filter_var( | ||||||
|  |                                     urldecode($_REQUEST['post']['source']), | ||||||
|  |                                     FILTER_SANITIZE_URL | ||||||
|  |                                 ) : null, | ||||||
|  |                             'sourceurl' => !empty($_REQUEST['post']['sourceurl']) ? filter_var( | ||||||
|  |                                     urldecode($_REQUEST['post']['sourceurl']), | ||||||
|  |                                     FILTER_SANITIZE_URL | ||||||
|  |                                 ) : '', | ||||||
|  |                             'description' => !empty($_REQUEST['post']['description']) ? filter_var( | ||||||
|  |                                     $_REQUEST['post']['description'], | ||||||
|  |                                     FILTER_SANITIZE_STRING | ||||||
|  |                                 ) : '', | ||||||
|  |                             'is_rating_locked' => !empty($_REQUEST['post']['is_rating_locked']) ? filter_var( | ||||||
|  |                                     $_REQUEST['post']['is_rating_locked'], | ||||||
|  |                                     FILTER_SANITIZE_NUMBER_INT | ||||||
|  |                                 ) : false, | ||||||
|  |                             'is_note_locked' => !empty($_REQUEST['post']['is_note_locked']) ? filter_var( | ||||||
|  |                                     $_REQUEST['post']['is_note_locked'], | ||||||
|  |                                     FILTER_SANITIZE_NUMBER_INT | ||||||
|  |                                 ) : false, | ||||||
|  |                             'parent_id' => !empty($_REQUEST['post']['parent_id']) ? filter_var( | ||||||
|  |                                     $_REQUEST['post']['parent_id'], | ||||||
|  |                                     FILTER_SANITIZE_NUMBER_INT | ||||||
|  |                                 ) : null, | ||||||
|  |                         ); | ||||||
|  |                         $md5 = !empty($_REQUEST['md5']) ? filter_var($_REQUEST['md5'], FILTER_SANITIZE_STRING) : null; | ||||||
|  |                         $this->postCreate(new OuroborosPost($post), $md5); | ||||||
|  |                     } else { | ||||||
|  |                         $this->sendResponse(403, 'You cannot create new posts'); | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                 } |                 } elseif ($this->match('update')) { | ||||||
|                 elseif ($this->match('update')) { |  | ||||||
|                     // Update
 |                     // Update
 | ||||||
|                 } |                     //@todo add post update
 | ||||||
|                 elseif ($this->match('show')) { |                 } elseif ($this->match('show')) { | ||||||
|                     // Show
 |                     // Show
 | ||||||
|                     if (isset($_REQUEST['id'])) { |                     $id = !empty($_REQUEST['id']) ? filter_var($_REQUEST['id'], FILTER_SANITIZE_NUMBER_INT) : null; | ||||||
|                         $id = $_REQUEST['id']; |                     $this->postShow($id); | ||||||
|                         $posts = array(); |                 } elseif ($this->match('index') || $this->match('list')) { | ||||||
|                         $posts[] = new _SafeOuroborosImage(Image::by_id($id)); |  | ||||||
|                         $page->set_data(json_encode($posts)); |  | ||||||
|                     } |  | ||||||
|                     else { |  | ||||||
|                         $page->set_data(json_encode(array())); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 elseif ($this->match('index') || $this->match('list')) { |  | ||||||
|                     // List
 |                     // List
 | ||||||
|                     $limit = !empty($_REQUEST['limit']) ? intval(filter_var($_REQUEST['limit'], FILTER_SANITIZE_NUMBER_INT)) : 45; |                     $limit = !empty($_REQUEST['limit']) ? intval( | ||||||
|                     $p = !empty($_REQUEST['page']) ? intval(filter_var($_REQUEST['page'], FILTER_SANITIZE_NUMBER_INT)) : 1; |                         filter_var($_REQUEST['limit'], FILTER_SANITIZE_NUMBER_INT) | ||||||
|  |                     ) : 45; | ||||||
|  |                     $p = !empty($_REQUEST['page']) ? intval( | ||||||
|  |                         filter_var($_REQUEST['page'], FILTER_SANITIZE_NUMBER_INT) | ||||||
|  |                     ) : 1; | ||||||
|                     $tags = !empty($_REQUEST['tags']) ? filter_var($_REQUEST['tags'], FILTER_SANITIZE_STRING) : array(); |                     $tags = !empty($_REQUEST['tags']) ? filter_var($_REQUEST['tags'], FILTER_SANITIZE_STRING) : array(); | ||||||
|                     if (!empty($tags)) { |                     if (!empty($tags)) { | ||||||
|                         $tags = Tag::explode($tags); |                         $tags = Tag::explode($tags); | ||||||
|                     } |                     } | ||||||
|                     $start = ( $p - 1 ) * $limit; |                     $this->postIndex($limit, $p, $tags); | ||||||
|                     //var_dump($limit, $p, $tags, $start);die();
 |                 } | ||||||
|                     $results = Image::find_images(max($start, 0), min($limit, 100), $tags); |             } elseif ($event->page_matches('tag')) { | ||||||
|                     $posts = array(); |                 if ($this->match('index') || $this->match('list')) { | ||||||
|                     foreach ($results as $img) { |                     $limit = !empty($_REQUEST['limit']) ? intval( | ||||||
|                         if (!is_object($img)) { |                         filter_var($_REQUEST['limit'], FILTER_SANITIZE_NUMBER_INT) | ||||||
|                             continue; |                     ) : 50; | ||||||
|                         } |                     $p = !empty($_REQUEST['page']) ? intval( | ||||||
|                         $posts[] = new _SafeOuroborosImage($img); |                         filter_var($_REQUEST['page'], FILTER_SANITIZE_NUMBER_INT) | ||||||
|                     } |                     ) : 1; | ||||||
|                     $page->set_data(json_encode($posts)); |                     $order = (!empty($_REQUEST['order']) && ($_REQUEST['order'] == 'date' || $_REQUEST['order'] == 'count' || $_REQUEST['order'] == 'name')) ? filter_var( | ||||||
|  |                         $_REQUEST['order'], | ||||||
|  |                         FILTER_SANITIZE_STRING | ||||||
|  |                     ) : 'date'; | ||||||
|  |                     $id = !empty($_REQUEST['id']) ? intval( | ||||||
|  |                         filter_var($_REQUEST['id'], FILTER_SANITIZE_NUMBER_INT) | ||||||
|  |                     ) : null; | ||||||
|  |                     $after_id = !empty($_REQUEST['after_id']) ? intval( | ||||||
|  |                         filter_var($_REQUEST['after_id'], FILTER_SANITIZE_NUMBER_INT) | ||||||
|  |                     ) : null; | ||||||
|  |                     $name = !empty($_REQUEST['name']) ? filter_var($_REQUEST['name'], FILTER_SANITIZE_STRING) : ''; | ||||||
|  |                     $name_pattern = !empty($_REQUEST['name_pattern']) ? filter_var( | ||||||
|  |                         $_REQUEST['name_pattern'], | ||||||
|  |                         FILTER_SANITIZE_STRING | ||||||
|  |                     ) : ''; | ||||||
|  |                     $this->tagIndex($limit, $p, $order, $id, $after_id, $name, $name_pattern); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             elseif ($event->page_matches('tag')) { |         } elseif ($event->page_matches('post/show')) { | ||||||
|                 if ($this->match('index') || $this->match('list')) { |             $page->set_mode('redirect'); | ||||||
|                     $limit = !empty($_REQUEST['limit']) ? intval(filter_var($_REQUEST['limit'], FILTER_SANITIZE_NUMBER_INT)) : 50; |             $page->set_redirect(make_link(str_replace('post/show', 'post/view', implode('/', $event->args)))); | ||||||
|                     $p = !empty($_REQUEST['page']) ? intval(filter_var($_REQUEST['page'], FILTER_SANITIZE_NUMBER_INT)) : 1; |             $page->display(); | ||||||
|                     $order = (!empty($_REQUEST['order']) && ($_REQUEST['order'] == 'date' || $_REQUEST['order'] == 'count' || $_REQUEST['order'] == 'name')) ? filter_var($_REQUEST['order'], FILTER_SANITIZE_STRING) : 'date'; |             die(); | ||||||
|                     $id = !empty($_REQUEST['id']) ? intval(filter_var($_REQUEST['id'], FILTER_SANITIZE_NUMBER_INT)) : null; |         } | ||||||
|                     $after_id = !empty($_REQUEST['after_id']) ? intval(filter_var($_REQUEST['after_id'], FILTER_SANITIZE_NUMBER_INT)) : null; | 
 | ||||||
|                     $name = !empty($_REQUEST['name']) ? filter_var($_REQUEST['name'], FILTER_SANITIZE_STRING) : ''; |     } | ||||||
|                     $name_pattern = !empty($_REQUEST['name_pattern']) ? filter_var($_REQUEST['name_pattern'], FILTER_SANITIZE_STRING) : ''; | 
 | ||||||
|                     $start = ( $p - 1 ) * $limit; |     /** | ||||||
|                     $tag_data = array(); |      * Post | ||||||
|                     switch ($order) { |      */ | ||||||
|                         case 'name': | 
 | ||||||
|                             $tag_data = $database->get_col($database->scoreql_to_sql(" |     /** | ||||||
|                                 SELECT DISTINCT |      * Wrapper for post creation | ||||||
|                                     id, SCORE_STRNORM(substr(tag, 1, 1)), count |      * @param OuroborosPost $post | ||||||
|                                 FROM tags |      * @param string $md5 | ||||||
|                                 WHERE count >= :tags_min |      */ | ||||||
|                                 ORDER BY SCORE_STRNORM(substr(tag, 1, 1)) LIMIT :start, :max_items |     protected function postCreate(OuroborosPost $post, $md5 = '') | ||||||
|                             "), array("tags_min" => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit));
 |     { | ||||||
|                             break; |         global $page, $config, $user; | ||||||
|                         case 'count': |         if (!empty($md5)) { | ||||||
|                             $tag_data = $database->get_all(" |             $img = Image::by_hash($md5); | ||||||
|                                 SELECT id, tag, count |             if (!is_null($img)) { | ||||||
|                                 FROM tags |                 $this->sendResponse(420, self::ERROR_POST_CREATE_DUPE); | ||||||
|                                 WHERE count >= :tags_min |                 return; | ||||||
|                                 ORDER BY count DESC, tag ASC LIMIT :start, :max_items |             } | ||||||
|                                 ", array("tags_min" => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit));
 |         } | ||||||
|                             break; |         $meta = array(); | ||||||
|                         case 'date': |         $meta['tags'] = $post->tags; | ||||||
|                             $tag_data = $database->get_all(" |         $meta['source'] = $post->source; | ||||||
|                                 SELECT id, tag, count |         if (defined('ENABLED_EXTS')) { | ||||||
|                                 FROM tags |             if (strstr(ENABLED_EXTS, 'rating') !== false) { | ||||||
|                                 WHERE count >= :tags_min |                 $meta['rating'] = $post->rating; | ||||||
|                                 ORDER BY count DESC, tag ASC LIMIT :start, :max_items |             } | ||||||
|                                 ", array("tags_min" => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit));
 |         } | ||||||
|                             break; |         // Check where we should try for the file
 | ||||||
|                     } |         if (empty($post->file) && !empty($post->file_url) && filter_var( | ||||||
|                     $tags = array(); |                 $post->file_url, | ||||||
|                     foreach ($tag_data as $tag) { |                 FILTER_VALIDATE_URL | ||||||
|                         if (!is_array($tag)) { |             ) !== false | ||||||
|                             continue; |         ) { | ||||||
|                         } |             // Transload from source
 | ||||||
|                         $tags[] = new _SafeOuroborosTag($tag); |             $meta['file'] = tempnam('/tmp', 'shimmie_transload_' . $config->get_string('transload_engine')); | ||||||
|                     } |             $meta['filename'] = basename($post->file_url); | ||||||
|                     $page->set_data(json_encode($tags)); |             if (!transload($post->file_url, $meta['file'])) { | ||||||
|  |                 $this->sendResponse(500, 'Transloading failed'); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             $meta['hash'] = md5_file($meta['file']); | ||||||
|  |         } else { | ||||||
|  |             // Use file
 | ||||||
|  |             $meta['file'] = $post->file['tmp_name']; | ||||||
|  |             $meta['filename'] = $post->file['name']; | ||||||
|  |             $meta['hash'] = md5_file($meta['file']); | ||||||
|  |         } | ||||||
|  |         if (!empty($md5) && $md5 !== $meta['hash']) { | ||||||
|  |             $this->sendResponse(420, self::ERROR_POST_CREATE_MD5); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if (!empty($meta['hash'])) { | ||||||
|  |             $img = Image::by_hash($meta['hash']); | ||||||
|  |             if (!is_null($img)) { | ||||||
|  |                 $this->sendResponse(420, self::ERROR_POST_CREATE_DUPE); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         $meta['extension'] = pathinfo($meta['filename'], PATHINFO_EXTENSION); | ||||||
|  |         try { | ||||||
|  |             $upload = new DataUploadEvent($meta['file'], $meta); | ||||||
|  |             send_event($upload); | ||||||
|  |             $image = Image::by_hash($meta['hash']); | ||||||
|  |             if (!is_null($image)) { | ||||||
|  |                 $this->sendResponse(200, make_link('post/view/' . $image->id), true); | ||||||
|  |                 return; | ||||||
|  |             } else { | ||||||
|  |                 // Fail, unsupported file?
 | ||||||
|  |                 $this->sendResponse(500, 'Unknown error'); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } catch (UploadException $e) { | ||||||
|  |             // Cleanup in case shit hit the fan
 | ||||||
|  |             $this->sendResponse(500, $e->getMessage()); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Wrapper for getting a single post | ||||||
|  |      * @param int $id | ||||||
|  |      */ | ||||||
|  |     protected function postShow($id = null) | ||||||
|  |     { | ||||||
|  |         if (!is_null($id)) { | ||||||
|  |             $post = new _SafeOuroborosImage(Image::by_id($id)); | ||||||
|  |             $this->sendData('post', $post); | ||||||
|  |         } else { | ||||||
|  |             $this->sendResponse(424, 'ID is mandatory'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Wrapper for getting a list of posts | ||||||
|  |      * @param $limit | ||||||
|  |      * @param $page | ||||||
|  |      * @param $tags | ||||||
|  |      */ | ||||||
|  |     protected function postIndex($limit, $page, $tags) | ||||||
|  |     { | ||||||
|  |         $start = ($page - 1) * $limit; | ||||||
|  |         $results = Image::find_images(max($start, 0), min($limit, 100), $tags); | ||||||
|  |         $posts = array(); | ||||||
|  |         foreach ($results as $img) { | ||||||
|  |             if (!is_object($img)) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             $posts[] = new _SafeOuroborosImage($img); | ||||||
|  |         } | ||||||
|  |         $this->sendData('post', $posts, max($start, 0)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Tag | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Wrapper for getting a list of tags | ||||||
|  |      * @param $limit | ||||||
|  |      * @param $page | ||||||
|  |      * @param $order | ||||||
|  |      * @param $id | ||||||
|  |      * @param $after_id | ||||||
|  |      * @param $name | ||||||
|  |      * @param $name_pattern | ||||||
|  |      */ | ||||||
|  |     protected function tagIndex($limit, $page, $order, $id, $after_id, $name, $name_pattern) | ||||||
|  |     { | ||||||
|  |         global $database, $config; | ||||||
|  |         $start = ($page - 1) * $limit; | ||||||
|  |         $tag_data = array(); | ||||||
|  |         switch ($order) { | ||||||
|  |             case 'name': | ||||||
|  |                 $tag_data = $database->get_col( | ||||||
|  |                     $database->scoreql_to_sql( | ||||||
|  |                         " | ||||||
|  |                                                         SELECT DISTINCT | ||||||
|  |                                                             id, SCORE_STRNORM(substr(tag, 1, 1)), count | ||||||
|  |                                                         FROM tags | ||||||
|  |                                                         WHERE count >= :tags_min | ||||||
|  |                                                         ORDER BY SCORE_STRNORM(substr(tag, 1, 1)) LIMIT :start, :max_items | ||||||
|  |                                                     " | ||||||
|  |                     ), | ||||||
|  |                     array('tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit) | ||||||
|  |                 ); | ||||||
|  |                 break; | ||||||
|  |             case 'count': | ||||||
|  |                 $tag_data = $database->get_all( | ||||||
|  |                     " | ||||||
|  |                                                     SELECT id, tag, count | ||||||
|  |                                                     FROM tags | ||||||
|  |                                                     WHERE count >= :tags_min | ||||||
|  |                                                     ORDER BY count DESC, tag ASC LIMIT :start, :max_items | ||||||
|  |                                                     ",
 | ||||||
|  |                     array('tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit) | ||||||
|  |                 ); | ||||||
|  |                 break; | ||||||
|  |             case 'date': | ||||||
|  |                 $tag_data = $database->get_all( | ||||||
|  |                     " | ||||||
|  |                                                     SELECT id, tag, count | ||||||
|  |                                                     FROM tags | ||||||
|  |                                                     WHERE count >= :tags_min | ||||||
|  |                                                     ORDER BY count DESC, tag ASC LIMIT :start, :max_items | ||||||
|  |                                                     ",
 | ||||||
|  |                     array('tags_min' => $config->get_int('tags_min'), 'start' => $start, 'max_items' => $limit) | ||||||
|  |                 ); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         $tags = array(); | ||||||
|  |         foreach ($tag_data as $tag) { | ||||||
|  |             if (!is_array($tag)) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             $tags[] = new _SafeOuroborosTag($tag); | ||||||
|  |         } | ||||||
|  |         $this->sendData('tag', $tags, $start); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Utility methods | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sends a simple {success,reason} message to browser | ||||||
|  |      * | ||||||
|  |      * @param int $code HTTP equivalent code for the message | ||||||
|  |      * @param string $reason Reason for the code | ||||||
|  |      * @param bool $location Is $reason a location? (used mainly for post/create) | ||||||
|  |      */ | ||||||
|  |     private function sendResponse($code = 200, $reason = '', $location = false) | ||||||
|  |     { | ||||||
|  |         global $page; | ||||||
|  |         if ($code == 200) { | ||||||
|  |             $success = true; | ||||||
|  |         } else { | ||||||
|  |             $success = false; | ||||||
|  |         } | ||||||
|  |         if (empty($reason)) { | ||||||
|  |             if (defined("self::MSG_HTTP_{$code}")) { | ||||||
|  |                 $reason = constant("self::MSG_HTTP_{$code}"); | ||||||
|  |             } else { | ||||||
|  |                 $reason = self::MSG_HTTP_418; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ($code != 200) { | ||||||
|  |             $proto = $_SERVER['SERVER_PROTOCOL']; | ||||||
|  |             if (defined("self::HEADER_HTTP_{$code}")) { | ||||||
|  |                 $header = constant("self::HEADER_HTTP_{$code}"); | ||||||
|  |             } else { | ||||||
|  |                 // I'm a teapot!
 | ||||||
|  |                 $code = 418; | ||||||
|  |                 $header = self::HEADER_HTTP_418; | ||||||
|  |             } | ||||||
|  |             header("{$proto} {$code} {$header}", true); | ||||||
|  |         } | ||||||
|  |         $response = array('success' => $success, 'reason' => $reason); | ||||||
|  |         if ($this->type == 'json') { | ||||||
|  |             if ($location !== false) { | ||||||
|  |                 $response['location'] = $response['reason']; | ||||||
|  |                 unset($response['reason']); | ||||||
|  |             } | ||||||
|  |             $response = json_encode($response); | ||||||
|  |         } elseif ($this->type == 'xml') { | ||||||
|  |             // Seriously, XML sucks...
 | ||||||
|  |             $xml = new XMLWriter(); | ||||||
|  |             $xml->openMemory(); | ||||||
|  |             $xml->startDocument('1.0', 'utf-8'); | ||||||
|  |             $xml->startElement('response'); | ||||||
|  |             $xml->writeAttribute('success', var_export($success, true)); | ||||||
|  |             if ($location !== false) { | ||||||
|  |                 $xml->writeAttribute('location', $reason); | ||||||
|  |             } else { | ||||||
|  |                 $xml->writeAttribute('reason', $reason); | ||||||
|  |             } | ||||||
|  |             $xml->endElement(); | ||||||
|  |             $xml->endDocument(); | ||||||
|  |             $response = $xml->outputMemory(true); | ||||||
|  |             unset($xml); | ||||||
|  |         } | ||||||
|  |         $page->set_data($response); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Send data to the browser | ||||||
|  |      * @param string $type | ||||||
|  |      * @param mixed $data | ||||||
|  |      * @param int $offset | ||||||
|  |      */ | ||||||
|  |     private function sendData($type = '', $data = array(), $offset = 0) | ||||||
|  |     { | ||||||
|  |         global $page; | ||||||
|  |         $response = ''; | ||||||
|  |         if ($this->type == 'json') { | ||||||
|  |             $response = json_encode($data); | ||||||
|  |         } elseif ($this->type == 'xml') { | ||||||
|  |             $xml = new XMLWriter(); | ||||||
|  |             $xml->openMemory(); | ||||||
|  |             $xml->startDocument('1.0', 'utf-8'); | ||||||
|  |             if (array_key_exists(0, $data)) { | ||||||
|  |                 $xml->startElement($type . 's'); | ||||||
|  |                 if ($type == 'post') { | ||||||
|  |                     $xml->writeAttribute('count', count($data)); | ||||||
|  |                     $xml->writeAttribute('offset', $offset); | ||||||
|                 } |                 } | ||||||
|  |                 if ($type == 'tag') { | ||||||
|  |                     $xml->writeAttribute('type', 'array'); | ||||||
|  |                 } | ||||||
|  |                 foreach ($data as $item) { | ||||||
|  |                     $this->createItemXML($xml, $type, $item); | ||||||
|  |                 } | ||||||
|  |                 $xml->endElement(); | ||||||
|  |             } else { | ||||||
|  |                 $this->createItemXML($xml, $type, $data); | ||||||
|  |             } | ||||||
|  |             $xml->endDocument(); | ||||||
|  |             $response = $xml->outputMemory(true); | ||||||
|  |             unset($xml); | ||||||
|  |         } | ||||||
|  |         $page->set_data($response); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private function createItemXML(XMLWriter &$xml, $type, $item) | ||||||
|  |     { | ||||||
|  |         $xml->startElement($type); | ||||||
|  |         foreach ($item as $key => $val) { | ||||||
|  |             if ($key == 'created_at' && $type == 'post') { | ||||||
|  |                 $xml->writeAttribute($key, $val['s']); | ||||||
|  |             } else { | ||||||
|  |                 if (is_bool($val)) { | ||||||
|  |                     $val = $val ? 'true' : 'false'; | ||||||
|  |                 } | ||||||
|  |                 $xml->writeAttribute($key, $val); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         $xml->endElement(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Try to figure who is uploading | ||||||
|  |      * | ||||||
|  |      * Currently checks for either user & session in request or cookies | ||||||
|  |      * and initializes a global User | ||||||
|  |      * @param void | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     private function tryAuth() | ||||||
|  |     { | ||||||
|  |         global $config, $user; | ||||||
|  | 
 | ||||||
|  |         if (isset($_REQUEST['user']) && isset($_REQUEST['session'])) { | ||||||
|  |             //Auth by session data from query
 | ||||||
|  |             $name = $_REQUEST['user']; | ||||||
|  |             $session = $_REQUEST['session']; | ||||||
|  |             $duser = User::by_session($name, $session); | ||||||
|  |             if (!is_null($duser)) { | ||||||
|  |                 $user = $duser; | ||||||
|  |             } else { | ||||||
|  |                 $user = User::by_id($config->get_int("anon_id", 0)); | ||||||
|  |             } | ||||||
|  |         } elseif (isset($_COOKIE[$config->get_string('cookie_prefix', 'shm') . '_' . 'session']) && | ||||||
|  |             isset($_COOKIE[$config->get_string('cookie_prefix', 'shm') . '_' . 'user']) | ||||||
|  |         ) { | ||||||
|  |             //Auth by session data from cookies
 | ||||||
|  |             $session = $_COOKIE[$config->get_string('cookie_prefix', 'shm') . '_' . 'session']; | ||||||
|  |             $user = $_COOKIE[$config->get_string('cookie_prefix', 'shm') . '_' . 'user']; | ||||||
|  |             $duser = User::by_session($user, $session); | ||||||
|  |             if (!is_null($duser)) { | ||||||
|  |                 $user = $duser; | ||||||
|  |             } else { | ||||||
|  |                 $user = User::by_id($config->get_int("anon_id", 0)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private function match($page) { |     /** | ||||||
|  |      * Helper for matching API methods from event | ||||||
|  |      * @param $page | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     private function match($page) | ||||||
|  |     { | ||||||
|         return (preg_match("%{$page}\.(xml|json)$%", implode('/', $this->event->args), $matches) === 1); |         return (preg_match("%{$page}\.(xml|json)$%", implode('/', $this->event->args), $matches) === 1); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -71,6 +71,13 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 			log_info("pools", "extension installed"); | 			log_info("pools", "extension installed"); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if ($config->get_int("ext_pools_version") < 2){ | ||||||
|  | 			$database->Execute("ALTER TABLE pools ADD UNIQUE INDEX (title);"); | ||||||
|  | 			$database->Execute("ALTER TABLE pools ADD lastupdated TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;"); | ||||||
|  | 
 | ||||||
|  | 			$config->set_int("ext_pools_version", 2); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Add a block to the Board Config / Setup
 | 	// Add a block to the Board Config / Setup
 | ||||||
| @ -111,7 +118,7 @@ class Pools extends Extension { | |||||||
| 						$this->theme->new_pool_composer($page); | 						$this->theme->new_pool_composer($page); | ||||||
| 					} else { | 					} else { | ||||||
| 						$errMessage = "You must be registered and logged in to create a new pool."; | 						$errMessage = "You must be registered and logged in to create a new pool."; | ||||||
| 						$this->theme->display_error($errMessage); | 						$this->theme->display_error(401, "Error", $errMessage); | ||||||
| 					} | 					} | ||||||
| 					break; | 					break; | ||||||
| 
 | 
 | ||||||
| @ -122,7 +129,7 @@ class Pools extends Extension { | |||||||
| 						$page->set_redirect(make_link("pool/view/".$newPoolID)); | 						$page->set_redirect(make_link("pool/view/".$newPoolID)); | ||||||
| 					} | 					} | ||||||
| 					catch(PoolCreationException $e) { | 					catch(PoolCreationException $e) { | ||||||
| 						$this->theme->display_error($e->error); | 						$this->theme->display_error(400, "Error", $e->error); | ||||||
| 					} | 					} | ||||||
| 					break; | 					break; | ||||||
| 
 | 
 | ||||||
| @ -168,7 +175,7 @@ class Pools extends Extension { | |||||||
| 							$page->set_mode("redirect"); | 							$page->set_mode("redirect"); | ||||||
| 							$page->set_redirect(make_link("pool/view/".$pool_id)); | 							$page->set_redirect(make_link("pool/view/".$pool_id)); | ||||||
| 						} else { | 						} else { | ||||||
| 							$this->theme->display_error("Permssion denied."); | 							$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 					break; | 					break; | ||||||
| @ -177,7 +184,7 @@ class Pools extends Extension { | |||||||
| 					if ($this->have_permission($user, $pool)) { | 					if ($this->have_permission($user, $pool)) { | ||||||
| 						$this->import_posts($pool_id); | 						$this->import_posts($pool_id); | ||||||
| 					} else { | 					} else { | ||||||
| 						$this->theme->display_error("Permssion denied."); | 						$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); | ||||||
| 					} | 					} | ||||||
| 					break; | 					break; | ||||||
| 
 | 
 | ||||||
| @ -187,7 +194,7 @@ class Pools extends Extension { | |||||||
| 						$page->set_mode("redirect"); | 						$page->set_mode("redirect"); | ||||||
| 						$page->set_redirect(make_link("pool/view/".$pool_id)); | 						$page->set_redirect(make_link("pool/view/".$pool_id)); | ||||||
| 					} else { | 					} else { | ||||||
| 						$this->theme->display_error("Permssion denied."); | 						$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); | ||||||
| 					} | 					} | ||||||
| 					break; | 					break; | ||||||
| 
 | 
 | ||||||
| @ -197,7 +204,18 @@ class Pools extends Extension { | |||||||
| 						$page->set_mode("redirect"); | 						$page->set_mode("redirect"); | ||||||
| 						$page->set_redirect(make_link("pool/view/".$pool_id)); | 						$page->set_redirect(make_link("pool/view/".$pool_id)); | ||||||
| 					} else { | 					} else { | ||||||
| 						$this->theme->display_error("Permssion denied."); | 						$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					break; | ||||||
|  | 
 | ||||||
|  | 				case "edit_description": | ||||||
|  | 					if ($this->have_permission($user, $pool)) { | ||||||
|  | 						$this->edit_description(); | ||||||
|  | 						$page->set_mode("redirect"); | ||||||
|  | 						$page->set_redirect(make_link("pool/view/".$pool_id)); | ||||||
|  | 					} else { | ||||||
|  | 						$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					break; | 					break; | ||||||
| @ -210,7 +228,7 @@ class Pools extends Extension { | |||||||
| 						$page->set_mode("redirect"); | 						$page->set_mode("redirect"); | ||||||
| 						$page->set_redirect(make_link("pool/list")); | 						$page->set_redirect(make_link("pool/list")); | ||||||
| 					} else { | 					} else { | ||||||
| 						$this->theme->display_error("Permssion denied."); | 						$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page"); | ||||||
| 					} | 					} | ||||||
| 					break; | 					break; | ||||||
| 
 | 
 | ||||||
| @ -275,6 +293,45 @@ 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){ | ||||||
|  | 		$poolTag = str_replace("_", " ", $poolTag); | ||||||
|  | 		//First check if pool tag is a title
 | ||||||
|  | 		if(ctype_digit($poolTag)){ | ||||||
|  | 			//If string only contains numeric characters, assume it is $poolID
 | ||||||
|  | 			if($this->get_single_pool($poolTag)){ //Make sure pool exists
 | ||||||
|  | 				$this->add_post($poolTag, $imageID); | ||||||
|  | 			} | ||||||
|  | 		}else{ | ||||||
|  | 			//If string doesn't contain only numeric characters, check to see if tag is title.
 | ||||||
|  | 			$pool = $this->get_single_pool_from_title($poolTag); | ||||||
|  | 			if($pool){ | ||||||
|  | 				$this->add_post($pool['id'], $imageID); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* ------------------------------------------------- */ | 	/* ------------------------------------------------- */ | ||||||
| 	/* --------------  Private Functions  -------------- */ | 	/* --------------  Private Functions  -------------- */ | ||||||
| 	/* ------------------------------------------------- */ | 	/* ------------------------------------------------- */ | ||||||
| @ -309,13 +366,26 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 		$poolsPerPage = $config->get_int("poolsListsPerPage"); | 		$poolsPerPage = $config->get_int("poolsListsPerPage"); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 		$order_by = ""; | ||||||
|  | 		$order = get_prefixed_cookie("ui-order-pool"); | ||||||
|  | 		if($order == "created" || is_null($order)){ | ||||||
|  | 			$order_by = "ORDER BY p.date DESC"; | ||||||
|  | 		}elseif($order == "updated"){ | ||||||
|  | 			$order_by = "ORDER BY p.lastupdated DESC"; | ||||||
|  | 		}elseif($order == "name"){ | ||||||
|  | 			$order_by = "ORDER BY p.title ASC"; | ||||||
|  | 		}elseif($order == "count"){ | ||||||
|  | 			$order_by = "ORDER BY p.posts DESC"; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		$pools = $database->get_all(" | 		$pools = $database->get_all(" | ||||||
| 				SELECT p.id, p.user_id, p.public, p.title, p.description, | 				SELECT p.id, p.user_id, p.public, p.title, p.description, | ||||||
| 				       p.posts, u.name as user_name | 				       p.posts, u.name as user_name | ||||||
| 				FROM pools AS p | 				FROM pools AS p | ||||||
| 				INNER JOIN users AS u | 				INNER JOIN users AS u | ||||||
| 				ON p.user_id = u.id | 				ON p.user_id = u.id | ||||||
| 				ORDER BY p.date DESC | 				$order_by | ||||||
| 				LIMIT :l OFFSET :o | 				LIMIT :l OFFSET :o | ||||||
| 				", array("l"=>$poolsPerPage, "o"=>$pageNumber * $poolsPerPage)
 | 				", array("l"=>$poolsPerPage, "o"=>$pageNumber * $poolsPerPage)
 | ||||||
| 				); | 				); | ||||||
| @ -336,7 +406,10 @@ class Pools extends Extension { | |||||||
| 			throw new PoolCreationException("You must be registered and logged in to add a image."); | 			throw new PoolCreationException("You must be registered and logged in to add a image."); | ||||||
| 		} | 		} | ||||||
| 		if(empty($_POST["title"])) { | 		if(empty($_POST["title"])) { | ||||||
| 			throw new PoolCreationException("Pool needs a title"); | 			throw new PoolCreationException("Pool title is empty."); | ||||||
|  | 		} | ||||||
|  | 		if($this->get_single_pool_from_title($_POST["title"])) { | ||||||
|  | 			throw new PoolCreationException("A pool using this title already exists."); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$public = $_POST["public"] == "Y" ? "Y" : "N"; | 		$public = $_POST["public"] == "Y" ? "Y" : "N"; | ||||||
| @ -372,6 +445,16 @@ class Pools extends Extension { | |||||||
| 		return $database->get_row("SELECT * FROM pools WHERE id=:id", array("id"=>$poolID)); | 		return $database->get_row("SELECT * FROM pools WHERE id=:id", array("id"=>$poolID)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieve information about a pool given a pool title. | ||||||
|  | 	 * @param $poolTitle Integer | ||||||
|  | 	 * @retval 2D array (with only 1 element in the one dimension) | ||||||
|  | 	 */ | ||||||
|  | 	private function get_single_pool_from_title(/*string*/ $poolTitle) { | ||||||
|  | 		global $database; | ||||||
|  | 		return $database->get_row("SELECT * FROM pools WHERE title=:title", array("title"=>$poolTitle)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get all of the pool IDs that an image is in, given an image ID. | 	 * Get all of the pool IDs that an image is in, given an image ID. | ||||||
| 	 * @param $imageID Integer | 	 * @param $imageID Integer | ||||||
| @ -476,6 +559,17 @@ class Pools extends Extension { | |||||||
| 		return $poolID; | 		return $poolID; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* | ||||||
|  | 	 * Allows editing of pool description. | ||||||
|  | 	 */ | ||||||
|  | 	private function edit_description() { | ||||||
|  | 		global $database; | ||||||
|  | 
 | ||||||
|  | 		$poolID = int_escape($_POST['pool_id']); | ||||||
|  | 		$database->execute("UPDATE pools SET description=:dsc WHERE id=:pid", array("dsc"=>$_POST['description'], "pid"=>$poolID)); | ||||||
|  | 
 | ||||||
|  | 		return $poolID; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * This function checks if a given image is contained within a given pool. | 	 * This function checks if a given image is contained within a given pool. | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								ext/pools/script.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								ext/pools/script.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | $(function() { | ||||||
|  | 	var order_pool = $.cookie("shm_ui-order-pool") || "created"; | ||||||
|  | 	$("#order_pool option[value="+order_pool+"]").attr("selected", true); | ||||||
|  | 
 | ||||||
|  | 	$('#order_pool').change(function(){ | ||||||
|  | 		var val = $("#order_pool option:selected").val(); | ||||||
|  | 		$.cookie("shm_ui-order-pool", val, {path: '/', expires: 365}); //FIXME: This won't play nice if COOKIE_PREFIX is not "shm_".
 | ||||||
|  | 		window.location.href = ''; | ||||||
|  | 	}); | ||||||
|  | }); | ||||||
| @ -67,11 +67,21 @@ class PoolsTheme extends Themelet { | |||||||
| 			<br><a href="'.make_link("pool/updated").'">Pool Changes</a> | 			<br><a href="'.make_link("pool/updated").'">Pool Changes</a> | ||||||
| 		'; | 		'; | ||||||
| 
 | 
 | ||||||
|  | 		$order_html = ' | ||||||
|  | 			<select id="order_pool"> | ||||||
|  | 			  <option value="created">Recently created</option> | ||||||
|  | 			  <option value="updated">Last updated</option> | ||||||
|  | 			  <option value="name">Name</option> | ||||||
|  | 			  <option value="count">Post count</option> | ||||||
|  | 			</select> | ||||||
|  | 		'; | ||||||
|  | 
 | ||||||
| 		$blockTitle = "Pools"; | 		$blockTitle = "Pools"; | ||||||
| 		$page->set_title(html_escape($blockTitle)); | 		$page->set_title(html_escape($blockTitle)); | ||||||
| 		$page->set_heading(html_escape($blockTitle)); | 		$page->set_heading(html_escape($blockTitle)); | ||||||
| 		$page->add_block(new Block($blockTitle, $html, "main", 10)); | 		$page->add_block(new Block($blockTitle, $html, "main", 10)); | ||||||
| 		$page->add_block(new Block("Navigation", $nav_html, "left", 10)); | 		$page->add_block(new Block("Navigation", $nav_html, "left", 10)); | ||||||
|  | 		$page->add_block(new Block("Order By", $order_html, "left", 15)); | ||||||
| 
 | 
 | ||||||
| 		$this->display_paginator($page, "pool/list", null, $pageNumber, $totalPages); | 		$this->display_paginator($page, "pool/list", null, $pageNumber, $totalPages); | ||||||
| 	} | 	} | ||||||
| @ -156,6 +166,13 @@ class PoolsTheme extends Themelet { | |||||||
| 			$pool_images .= "\n".$thumb_html."\n"; | 			$pool_images .= "\n".$thumb_html."\n"; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		$nav_html = ' | ||||||
|  | 			<a href="'.make_link().'">Index</a> | ||||||
|  | 			<br><a href="'.make_link("pool/new").'">Create Pool</a> | ||||||
|  | 			<br><a href="'.make_link("pool/updated").'">Pool Changes</a> | ||||||
|  | 		'; | ||||||
|  | 
 | ||||||
|  | 		$page->add_block(new Block("Navigation", $nav_html, "left", 10)); | ||||||
| 		$page->add_block(new Block("Viewing Posts", $pool_images, "main", 30));		 | 		$page->add_block(new Block("Viewing Posts", $pool_images, "main", 30));		 | ||||||
| 		$this->display_paginator($page, "pool/view/".$pools[0]['id'], null, $pageNumber, $totalPages); | 		$this->display_paginator($page, "pool/view/".$pools[0]['id'], null, $pageNumber, $totalPages); | ||||||
| 	} | 	} | ||||||
| @ -312,8 +329,17 @@ class PoolsTheme extends Themelet { | |||||||
| 	public function edit_pool(Page $page, /*array*/ $pools, /*array*/ $images) { | 	public function edit_pool(Page $page, /*array*/ $pools, /*array*/ $images) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 
 | 
 | ||||||
| 		$this->display_top($pools, "Editing Pool", true); |  | ||||||
| 
 | 
 | ||||||
|  | 		/* EDIT POOL DESCRIPTION */ | ||||||
|  | 		$desc_html = " | ||||||
|  | 			".make_form(make_link("pool/edit_description"))." | ||||||
|  | 					<textarea name='description'>".$pools[0]['description']."</textarea><br /> | ||||||
|  | 					<input type='hidden' name='pool_id' value='".$pools[0]['id']."'> | ||||||
|  | 					<input type='submit' value='Change Description' /> | ||||||
|  | 			</form> | ||||||
|  | 		";
 | ||||||
|  | 
 | ||||||
|  | 		/* REMOVE POOLS */ | ||||||
| 		$pool_images = "\n<form action='".make_link("pool/remove_posts")."' method='POST' name='checks'>"; | 		$pool_images = "\n<form action='".make_link("pool/remove_posts")."' method='POST' name='checks'>"; | ||||||
| 
 | 
 | ||||||
| 		foreach($images as $pair) { | 		foreach($images as $pair) { | ||||||
| @ -331,6 +357,9 @@ class PoolsTheme extends Themelet { | |||||||
| 			"<input type='hidden' name='pool_id' value='".$pools[0]['id']."'>". | 			"<input type='hidden' name='pool_id' value='".$pools[0]['id']."'>". | ||||||
| 			"</form>"; | 			"</form>"; | ||||||
| 
 | 
 | ||||||
|  | 		$pools[0]['description'] = ""; //This is a rough fix to avoid showing the description twice.
 | ||||||
|  | 		$this->display_top($pools, "Editing Pool", true); | ||||||
|  | 		$page->add_block(new Block("Editing Description", $desc_html, "main", 28)); | ||||||
| 		$page->add_block(new Block("Editing Posts", $pool_images, "main", 30)); | 		$page->add_block(new Block("Editing Posts", $pool_images, "main", 30)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -389,20 +418,5 @@ class PoolsTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 		$this->display_paginator($page, "pool/updated", null, $pageNumber, $totalPages); | 		$this->display_paginator($page, "pool/updated", null, $pageNumber, $totalPages); | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * Display an error message to the user. |  | ||||||
| 	 */ |  | ||||||
| 	public function display_error(/*int*/ $code, /*string*/ $title, /*string*/ $message) { |  | ||||||
| 		global $page; |  | ||||||
| 		 |  | ||||||
| 		// Quick n' Dirty fix
 |  | ||||||
| 		$message = $code; |  | ||||||
| 
 |  | ||||||
| 		$page->set_title("Error"); |  | ||||||
| 		$page->set_heading("Error"); |  | ||||||
| 		$page->add_block(new Block("Error", $errMessage, "main", 10)); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| ?>
 | ?>
 | ||||||
|  | |||||||
| @ -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; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| /* Imageboard to Shimmie */ | /* Imageboard to Shimmie */ | ||||||
| // This should work with "most" sites running Danbooru/Gelbooru/Shimmie
 | // This should work with "most" sites running Danbooru/Gelbooru/Shimmie
 | ||||||
| // TODO: Make this use jQuery! (if we can be sure that jquery is loaded)
 |  | ||||||
| // maxsize, supext, CA are set inside the bookmarklet (see theme.php)
 | // maxsize, supext, CA are set inside the bookmarklet (see theme.php)
 | ||||||
| 
 | 
 | ||||||
| var maxsize = (maxsize.match("(?:\.*[0-9])")) * 1024; // This assumes we are only working with MB.
 | var maxsize = (maxsize.match("(?:\.*[0-9])")) * 1024; // This assumes we are only working with MB.
 | ||||||
| @ -25,67 +24,84 @@ else if(CA === 2) { // New Tags | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| /* | /* | ||||||
|  * Danbooru (oreno.imouto | konachan | sankakucomplex) |  * Danbooru2 | ||||||
|  |  * jQuery should always active here, meaning we can use jQuery in this part of the bookmarklet. | ||||||
|  */ |  */ | ||||||
| if(document.getElementById("post_tags") !== null) { | 
 | ||||||
|  | if(document.getElementById("post_tag_string") !== null) { | ||||||
| 	if (typeof tag !== "ftp://ftp." && chk !==1) { | 	if (typeof tag !== "ftp://ftp." && chk !==1) { | ||||||
| 		var tag = document.getElementById("post_tags").value; | 		var tag = $('#post_tag_string').text().replace(/\n/g, ""); | ||||||
| 	} | 	} | ||||||
| 	tag = tag.replace(/\+/g, "%2B"); // This should stop + not showing in tags :x
 | 	tag = tag.replace(/\+/g, "%2B"); | ||||||
| 
 | 
 | ||||||
| 	var source = "http://" + document.location.hostname + document.location.href.match("\/post\/show\/[0-9]+"); | 	var source = "http://" + document.location.hostname + document.location.href.match("\/posts\/[0-9]+"); | ||||||
| 	if(source.search("oreno\\.imouto") >= 0 || source.search("konachan\\.com") >= 0) { | 
 | ||||||
| 		var rating = document.getElementById("stats").innerHTML.match("<li>Rating: (.*) <span")[1]; | 	var rlist = $('[name="post[rating]"]'); | ||||||
| 	} | 	for(x=0;x<3;x++){ | ||||||
| 	else { | 		var rating = (rlist[x].checked == true ? rlist[x].value : rating); | ||||||
| 		var rating = document.getElementById("stats").innerHTML.match("<li>Rating: (.*)<\/li>")[1]; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if(tag.search(/\bflash\b/)===-1){ | 	var fileinfo = $('#sidebar > section:eq(3) > ul > :contains("Size") > a'); | ||||||
| 		var highres_url = document.getElementById("highres").href; | 	var furl = "http://" + document.location.hostname + fileinfo.attr('href'); | ||||||
| 		if(source.search("oreno\\.imouto") >= 0 || source.search("konachan\\.com") >= 0){ // oreno's theme seems to have moved the filesize
 | 	var fs = fileinfo.text().split(" "); | ||||||
| 			var filesize = document.getElementById("highres").innerHTML.match("[a-zA-Z0-9]+ \\(+([0-9]+\\.[0-9]+) ([a-zA-Z]+)"); | 	var filesize = (fs[1] == "MB" ? fs[0] * 1024 : fs[0]); | ||||||
|  | 
 | ||||||
|  | 	if(supext.search(furl.match("[a-zA-Z0-9]+$")[0]) !== -1){ | ||||||
|  | 		if(filesize <= maxsize){ | ||||||
|  | 			location.href = ste+furl+"&tags="+tag+"&rating="+rating+"&source="+source; | ||||||
|  | 		} | ||||||
|  | 		else{ | ||||||
|  | 			alert(toobig); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else{ | ||||||
|  | 		alert(notsup); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * konachan | sankakucomplex | gelbooru | ||||||
|  |  */ | ||||||
|  | else if(document.getElementById('tag-sidebar') !== null) { | ||||||
|  | 	if (typeof tag !== "ftp://ftp." && chk !==1) { | ||||||
|  | 		if(document.location.href.search("sankakucomplex\\.com") >= 0 || document.location.href.search("gelbooru\\.com")){ | ||||||
|  | 			var tag = document.getElementById('tag-sidebar').innerText.replace(/ /g, "_").replace(/[\?_]*(.*?)_(\(\?\)_)?[0-9]+\n/g, "$1 "); | ||||||
| 		}else{ | 		}else{ | ||||||
| 			var filesize = document.getElementById("stats").innerHTML.match("[0-9] \\(((?:\.*[0-9])) ([a-zA-Z]+)"); | 			var tag = document.getElementById("post_tags").value; | ||||||
| 		} |  | ||||||
| 		if(filesize[2] == "MB") { |  | ||||||
| 			var filesize = filesize[1] * 1024; |  | ||||||
| 		} |  | ||||||
| 		else { |  | ||||||
| 			var filesize = filesize[2].match("[0-9]+"); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if(supext.search(highres_url.match("http\:\/\/.*\\.([a-z0-9]+)")[1]) !== -1) { |  | ||||||
| 			if(filesize <= maxsize) { |  | ||||||
| 				if(source.search("oreno\\.imouto") >= 0) { |  | ||||||
| 					// this regex tends to be a bit picky with tags -_-;;
 |  | ||||||
| 					var highres_url = highres_url.match("(http\:\/\/[a-z0-9]+\.[a-z]+\.[a-z]\/[a-z0-9]+\/[a-z0-9]+)\/[a-z0-9A-Z%_-]+(\.[a-zA-Z0-9]+)"); |  | ||||||
| 					var highres_url = highres_url[1]+highres_url[2]; // this should bypass hotlink protection
 |  | ||||||
| 				} |  | ||||||
| 				else if(source.search("konachan\\.com") >= 0) { |  | ||||||
| 					// konachan affixs konachan.com to the start of the tags, this requires different regex
 |  | ||||||
| 					var highres_url = highres_url.match("(http\:\/\/[a-z0-9]+\.[a-z]+\.[a-z]\/[a-z0-9]+\/[a-z0-9]+)\/[a-z0-9A-Z%_]+\.[a-zA-Z0-9%_-]+(\.[a-z0-9A-Z]+)") |  | ||||||
| 					var highres_url = highres_url[1]+highres_url[2]; |  | ||||||
| 				} |  | ||||||
| 				location.href = ste+highres_url+"&tags="+tag+"&rating="+rating+"&source="+source; |  | ||||||
| 			} |  | ||||||
| 			else{ |  | ||||||
| 				alert(toobig); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		else{ |  | ||||||
| 			alert(notsup); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else { | 	tag = tag.replace(/\+/g, "%2B"); | ||||||
| 		if(supext.search("swf") !== -1) { | 
 | ||||||
| 			location.href = ste+document.getElementsByName("movie")[0].value+"&tags="+tag+"&rating="+rating+"&source="+source; | 	var source = "http://" + document.location.hostname + (document.location.href.match("\/post\/show\/[0-9]+") || encodeURIComponent(document.location.href.match(/\/index\.php\?page=post&s=view&id=[0-9]+/))); | ||||||
|  | 
 | ||||||
|  | 	var rating = document.getElementById("stats").innerHTML.match("Rating: ([a-zA-Z]+)")[1]; | ||||||
|  | 
 | ||||||
|  | 	if(source.search("sankakucomplex\\.com") >= 0 || source.search("konachan\\.com") >= 0){ | ||||||
|  | 		var fileinfo = document.getElementById("highres"); | ||||||
|  | 		//NOTE: If highres doesn't exist, post must be flash (only sankakucomplex has flash)
 | ||||||
|  | 	}else if(source.search("gelbooru\\.com") >= 0){ | ||||||
|  | 		var fileinfo = document.getElementById('pfd').parentNode.parentNode.getElementsByTagName('a')[0]; | ||||||
|  | 		//gelbooru has no easy way to select the original image link, so we need to double check it is the correct link.
 | ||||||
|  | 		fileinfo = (fileinfo.getAttribute('href') == "#" ? document.getElementById('pfd').parentNode.parentNode.getElementsByTagName('a')[1] : fileinfo); | ||||||
|  | 	} | ||||||
|  | 	fileinfo = fileinfo || document.getElementsByTagName('embed')[0]; //If fileinfo is null then image is most likely flash.
 | ||||||
|  | 	var furl = fileinfo.href || fileinfo.src; | ||||||
|  | 	var fs = (fileinfo.innerText.match(/[0-9]+ (KB|MB)/) || ["0 KB"])[0].split(" "); | ||||||
|  | 	var filesize = (fs[1] == "MB" ? fs[0] * 1024 : fs[0]); | ||||||
|  | 
 | ||||||
|  | 	if(supext.search(furl.match("[a-zA-Z0-9]+$")[0]) !== -1){ | ||||||
|  | 		if(filesize <= maxsize){ | ||||||
|  | 			location.href = ste+furl+"&tags="+tag+"&rating="+rating+"&source="+source; | ||||||
| 		} | 		} | ||||||
| 		else{ | 		else{ | ||||||
| 			alert(notsup); | 			alert(toobig); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	else{ | ||||||
|  | 		alert(notsup); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*  | /*  | ||||||
| @ -129,36 +145,3 @@ else if(document.getElementsByTagName("title")[0].innerHTML.search("Image [0-9.- | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|  * Gelbooru |  | ||||||
|  */ |  | ||||||
| else if(document.getElementById("tags") !== null) { |  | ||||||
| 	if (typeof tag !=="ftp://ftp." && chk !==1) { |  | ||||||
| 		var tag = document.getElementById("tags").value; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	var rating = document.getElementById("stats").innerHTML.match("<li>Rating: (.*)<\/li>")[1]; |  | ||||||
| 
 |  | ||||||
| 	// Can't seem to grab source due to url containing a &
 |  | ||||||
| 	// var source="http://" + document.location.hostname + document.location.href.match("\/index\.php?page=post&s=view\\&id=.*");
 |  | ||||||
| 	 |  | ||||||
| 	// Updated Nov. 24, 2013 by jgen.
 |  | ||||||
| 	var gmi;	 |  | ||||||
| 	try { |  | ||||||
| 		gmi = document.getElementById("image").src.match(".*img[0-9]*\.gelbooru\.com[\/]+images[\/]+[0-9]+[\/]+[a-z0-9]+\.[a-z0-9]+")[0]; |  | ||||||
| 		 |  | ||||||
| 		// Since Gelbooru does not allow flash, no need to search for flash tag.
 |  | ||||||
| 		// Gelbooru doesn't show file size in statistics either...
 |  | ||||||
| 		if(supext.search(gmi.match("http\:\/\/.*\\.([a-z0-9]+)")[1]) !== -1){ |  | ||||||
| 			location.href = ste+gmi+"&tags="+tag+"&rating="+rating;//+"&source="+source;
 |  | ||||||
| 		} |  | ||||||
| 		else{ |  | ||||||
| 			alert(notsup); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	catch (err) |  | ||||||
| 	{ |  | ||||||
| 		alert("Unable to locate the image on the page!\n(Gelbooru may have changed the structure of their page, please file a bug.)"); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -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; | ||||||
| 			 | 			 | ||||||
|  | |||||||
| @ -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'")); | ||||||
| 		} | 		} | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user