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