Example #1
0
 /**
  * @param Page $page
  * @param int $image_id
  * @param array $history
  */
 public function display_history_page(Page $page, $image_id, $history)
 {
     global $user;
     $start_string = "\n\t\t\t<div style='text-align: left'>\n\t\t\t\t" . make_form(make_link("tag_history/revert")) . "\n\t\t\t\t\t<ul style='list-style-type:none;'>\n\t\t";
     $history_list = "";
     $n = 0;
     foreach ($history as $fields) {
         $n++;
         $current_id = $fields['id'];
         $current_tags = html_escape($fields['tags']);
         $name = $fields['name'];
         $date_set = autodate($fields['date_set']);
         $h_ip = $user->can("view_ip") ? " " . show_ip($fields['user_ip'], "Tagging Image #{$image_id} as '{$current_tags}'") : "";
         $setter = "<a href='" . make_link("user/" . url_escape($name)) . "'>" . html_escape($name) . "</a>{$h_ip}";
         $selected = $n == 2 ? " checked" : "";
         $current_tags = Tag::explode($current_tags);
         $taglinks = array();
         foreach ($current_tags as $tag) {
             $taglinks[] = "<a href='" . make_link("post/list/" . $tag . "/1") . "'>" . $tag . "</a>";
         }
         $current_tags = Tag::implode($taglinks);
         $history_list .= "\n\t\t\t\t<li>\n\t\t\t\t\t<input type='radio' name='revert' id='{$current_id}' value='{$current_id}'{$selected}>\n\t\t\t\t\t<label for='{$current_id}'>\n\t\t\t\t\t\t{$current_tags}\n\t\t\t\t\t\t<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\t\t\t\t\t\tSet by {$setter} {$date_set}\n\t\t\t\t\t</label>\n\t\t\t\t</li>\n\t\t\t\t";
     }
     $end_string = "\n\t\t\t\t\t</ul>\n\t\t\t\t\t<input type='submit' value='Revert To'>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t";
     $history_html = $start_string . $history_list . $end_string;
     $page->set_title('Image ' . $image_id . ' Tag History');
     $page->set_heading('Tag History: ' . $image_id);
     $page->add_block(new NavBlock());
     $page->add_block(new Block("Tag History", $history_html, "main", 10));
 }
Example #2
0
 private function build_stats(Image $image)
 {
     $h_owner = html_escape($image->get_owner()->name);
     $h_ownerlink = "<a href='" . make_link("user/{$h_owner}") . "'>{$h_owner}</a>";
     $h_ip = html_escape($image->owner_ip);
     $h_date = autodate($image->posted);
     $h_filesize = to_shorthand_int($image->filesize);
     global $user;
     if ($user->can("view_ip")) {
         $h_ownerlink .= " ({$h_ip})";
     }
     $html = "\n\t\tId: {$image->id}\n\t\t<br>Posted: {$h_date} by {$h_ownerlink}\n\t\t<br>Size: {$image->width}x{$image->height}\n\t\t<br>Filesize: {$h_filesize}\n\t\t";
     if (!is_null($image->source)) {
         $h_source = html_escape($image->source);
         if (substr($image->source, 0, 7) != "http://" && substr($image->source, 0, 8) != "https://") {
             $h_source = "http://" . $h_source;
         }
         $html .= "<br>Source: <a href='{$h_source}'>link</a>";
     }
     if (class_exists("Ratings")) {
         if ($image->rating == null || $image->rating == "u") {
             $image->rating = "u";
         }
         $h_rating = Ratings::rating_to_human($image->rating);
         $html .= "<br>Rating: {$h_rating}";
     }
     return $html;
 }
Example #3
0
 public function get_user_editor_html(Image $image)
 {
     global $user;
     $h_owner = html_escape($image->get_owner()->name);
     $h_av = $image->get_owner()->get_avatar_html();
     $h_date = autodate($image->posted);
     $h_ip = $user->can("view_ip") ? " (" . show_ip($image->owner_ip, "Image posted {$image->posted}") . ")" : "";
     return "\n\t\t\t<tr>\n\t\t\t\t<th>Uploader</th>\n\t\t\t\t<td>\n\t\t" . ($user->can("edit_image_owner") ? "\n\t\t\t\t\t<span class='view'><a class='username' href='" . make_link("user/{$h_owner}") . "'>{$h_owner}</a>{$h_ip}, {$h_date}</span>\n\t\t\t\t\t<input class='edit' type='text' name='tag_edit__owner' value='{$h_owner}'>\n\t\t" : "\n\t\t\t\t\t<a class='username' href='" . make_link("user/{$h_owner}") . "'>{$h_owner}</a>{$h_ip}, {$h_date}\n\t\t") . "\n\t\t\t\t</td>\n\t\t\t\t<td width='80px' rowspan='4'>{$h_av}</td>\n\t\t\t</tr>\n\t\t";
 }
Example #4
0
 private function build_stats($image)
 {
     $h_owner = html_escape($image->get_owner()->name);
     $h_ownerlink = "<a href='" . make_link("user/{$h_owner}") . "'>{$h_owner}</a>";
     $h_ip = html_escape($image->owner_ip);
     $h_date = autodate($image->posted);
     $h_filesize = to_shorthand_int($image->filesize);
     global $user;
     if ($user->is_admin()) {
         $h_ownerlink .= " ({$h_ip})";
     }
     $html = "\n\t\tId: {$image->id}\n\t\t<br>Posted: {$h_date} by {$h_ownerlink}\n\t\t<br>Size: {$image->width}x{$image->height}\n\t\t<br>Filesize: {$h_filesize}\n\t\t";
     if (!is_null($image->source)) {
         $h_source = html_escape($image->source);
         if (substr($image->source, 0, 7) != "http://") {
             $h_source = "http://" . $h_source;
         }
         $html .= "<br>Source: <a href='{$h_source}'>link</a>";
     }
     return $html;
 }
Example #5
0
 protected function comment_to_html(Comment $comment, $trim = false)
 {
     global $user;
     $tfe = new TextFormattingEvent($comment->comment);
     send_event($tfe);
     $i_uid = int_escape($comment->owner_id);
     $h_name = html_escape($comment->owner_name);
     $h_poster_ip = html_escape($comment->poster_ip);
     $h_comment = $trim ? substr($tfe->stripped, 0, 50) . "..." : $tfe->formatted;
     $i_comment_id = int_escape($comment->comment_id);
     $i_image_id = int_escape($comment->image_id);
     $h_posted = autodate($comment->posted);
     $h_userlink = "<a class='username' href='" . make_link("user/{$h_name}") . "'>{$h_name}</a>";
     $h_dellink = $user->is_admin() ? "<br>({$h_poster_ip}, <a " . "onclick=\"return confirm('Delete comment by {$h_name}:\\n" . $tfe->stripped . "');\" " . "href='" . make_link("comment/delete/{$i_comment_id}/{$i_image_id}") . "'>Del</a>)" : "";
     $h_imagelink = $trim ? "<a href='" . make_link("post/view/{$i_image_id}") . "'>&gt;&gt;&gt;</a>\n" : "";
     if ($trim) {
         return "<p class='comment'>{$h_userlink} {$h_dellink}<br/>{$h_posted}<br/>{$h_comment}</p>";
     } else {
         return "\n\t\t\t\t<table class='comment'><tr>\n\t\t\t\t\t<td class='meta'>{$h_userlink}<br/>{$h_posted}{$h_dellink}</td>\n\t\t\t\t\t<td>{$h_comment}</td>\n\t\t\t\t</tr></table>\n\t\t\t";
     }
 }
 protected function comment_to_html(Comment $comment, $trim = false)
 {
     global $user;
     $tfe = new TextFormattingEvent($comment->comment);
     send_event($tfe);
     //$i_uid = int_escape($comment->owner_id);
     $h_name = html_escape($comment->owner_name);
     //$h_poster_ip = html_escape($comment->poster_ip);
     $h_comment = $trim ? substr($tfe->stripped, 0, 50) . "..." : $tfe->formatted;
     $i_comment_id = int_escape($comment->comment_id);
     $i_image_id = int_escape($comment->image_id);
     $h_posted = autodate($comment->posted);
     $stripped_nonl = str_replace("\n", "\\n", substr($tfe->stripped, 0, 50));
     $stripped_nonl = str_replace("\r", "\\r", $stripped_nonl);
     $h_userlink = "<a class='username' href='" . make_link("user/{$h_name}") . "'>{$h_name}</a>";
     $h_del = $user->can("delete_comment") ? ' - <a onclick="return confirm(\'Delete comment by ' . $h_name . ':\\n' . $stripped_nonl . '\');" ' . 'href="' . make_link('comment/delete/' . $i_comment_id . '/' . $i_image_id) . '">Del</a>' : '';
     //$h_imagelink = $trim ? "<a href='".make_link("post/view/$i_image_id")."'>&gt;&gt;&gt;</a>\n" : "";
     if ($trim) {
         return "<p class='comment'>{$h_userlink} {$h_del}<br/>{$h_posted}<br/>{$h_comment}</p>";
     } else {
         return "\n\t\t\t\t<table class='comment'><tr>\n\t\t\t\t\t<td class='meta'>{$h_userlink}<br/>{$h_posted}{$h_del}</td>\n\t\t\t\t\t<td>{$h_comment}</td>\n\t\t\t\t</tr></table>\n\t\t\t";
     }
 }
Example #7
0
 protected function build_info(Image $image, $editor_parts)
 {
     global $user;
     $owner = $image->get_owner();
     $h_owner = html_escape($owner->name);
     $h_ip = html_escape($image->owner_ip);
     $h_source = html_escape($image->source);
     $i_owner_id = int_escape($owner->id);
     $h_date = autodate($image->posted);
     $html = "";
     $html .= "<p>Uploaded by <a href='" . make_link("user/{$h_owner}") . "'>{$h_owner}</a> {$h_date}";
     if ($user->is_admin()) {
         $html .= " ({$h_ip})";
     }
     if (!is_null($image->source)) {
         if (substr($image->source, 0, 7) == "http://") {
             $html .= " (<a href='{$h_source}'>source</a>)";
         } else {
             $html .= " (<a href='http://{$h_source}'>source</a>)";
         }
     }
     $html .= $this->build_image_editor($image, $editor_parts);
     return $html;
 }
 /**
  * Someone please explain this
  *
  * @param string $tmpl
  * @param string $_escape
  * @return string
  */
 public function parse_link_template($tmpl, $_escape = "url_escape")
 {
     global $config;
     // don't bother hitting the database if it won't be used...
     $tags = "";
     if (strpos($tmpl, '$tags') !== false) {
         // * stabs dynamically typed languages with a rusty spoon *
         $tags = $this->get_tag_list();
         $tags = str_replace("/", "", $tags);
         $tags = preg_replace("/^\\.+/", "", $tags);
     }
     $base_href = $config->get_string('base_href');
     $fname = $this->get_filename();
     $base_fname = strpos($fname, '.') ? substr($fname, 0, strrpos($fname, '.')) : $fname;
     $tmpl = str_replace('$id', $this->id, $tmpl);
     $tmpl = str_replace('$hash_ab', substr($this->hash, 0, 2), $tmpl);
     $tmpl = str_replace('$hash_cd', substr($this->hash, 2, 2), $tmpl);
     $tmpl = str_replace('$hash', $this->hash, $tmpl);
     $tmpl = str_replace('$tags', $_escape($tags), $tmpl);
     $tmpl = str_replace('$base', $base_href, $tmpl);
     $tmpl = str_replace('$ext', $this->ext, $tmpl);
     $tmpl = str_replace('$size', "{$this->width}x{$this->height}", $tmpl);
     $tmpl = str_replace('$filesize', to_shorthand_int($this->filesize), $tmpl);
     $tmpl = str_replace('$filename', $_escape($base_fname), $tmpl);
     $tmpl = str_replace('$title', $_escape($config->get_string("title")), $tmpl);
     $tmpl = str_replace('$date', $_escape(autodate($this->posted, false)), $tmpl);
     // nothing seems to use this, sending the event out to 50 exts is a lot of overhead
     if (!SPEED_HAX) {
         $plte = new ParseLinkTemplateEvent($tmpl, $this);
         send_event($plte);
         $tmpl = $plte->link;
     }
     static $flexihash = null;
     static $fh_last_opts = null;
     $matches = array();
     if (preg_match("/(.*){(.*)}(.*)/", $tmpl, $matches)) {
         $pre = $matches[1];
         $opts = $matches[2];
         $post = $matches[3];
         if ($opts != $fh_last_opts) {
             $fh_last_opts = $opts;
             $flexihash = new Flexihash();
             foreach (explode(",", $opts) as $opt) {
                 $parts = explode("=", $opt);
                 $parts_count = count($parts);
                 $opt_val = "";
                 $opt_weight = 0;
                 if ($parts_count === 2) {
                     $opt_val = $parts[0];
                     $opt_weight = $parts[1];
                 } elseif ($parts_count === 1) {
                     $opt_val = $parts[0];
                     $opt_weight = 1;
                 }
                 $flexihash->addTarget($opt_val, $opt_weight);
             }
         }
         $choice = $flexihash->lookup($pre . $post);
         $tmpl = $pre . $choice . $post;
     }
     return $tmpl;
 }
Example #9
0
 public function onUserPageBuilding(Event $event)
 {
     global $page, $user, $config;
     $h_join_date = autodate($event->display_user->join_date);
     $event->add_stats("Joined: {$h_join_date}", 10);
     $av = $event->display_user->get_avatar_html();
     if ($av) {
         $event->add_stats($av, 0);
     }
     ksort($event->stats);
     $this->theme->display_user_page($event->display_user, $event->stats);
     if ($user->id == $event->display_user->id) {
         $ubbe = new UserBlockBuildingEvent();
         send_event($ubbe);
         ksort($ubbe->parts);
         $this->theme->display_user_links($page, $user, $ubbe->parts);
     }
     if (($user->is_admin() || $user->id == $event->display_user->id) && $user->id != $config->get_int('anon_id')) {
         $this->theme->display_ip_list($page, $this->count_upload_ips($event->display_user), $this->count_comment_ips($event->display_user));
     }
 }
Example #10
0
 public function display_history($histories, $pageNumber, $totalPages)
 {
     global $user, $page;
     $html = "<table id='poolsList' class='zebra'>" . "<thead><tr>" . "<th>Image</th>" . "<th>Note</th>" . "<th>Body</th>" . "<th>Updater</th>" . "<th>Date</th>";
     if (!$user->is_anonymous()) {
         $html .= "<th>Action</th>";
     }
     $html .= "</tr></thead>" . "<tbody>";
     $n = 0;
     foreach ($histories as $history) {
         $oe = $n++ % 2 == 0 ? "even" : "odd";
         $image_link = "<a href='" . make_link("post/view/" . $history['image_id']) . "'>" . $history['image_id'] . "</a>";
         $history_link = "<a href='" . make_link("note/history/" . $history['note_id']) . "'>" . $history['note_id'] . "." . $history['review_id'] . "</a>";
         $user_link = "<a href='" . make_link("user/" . $history['user_name']) . "'>" . $history['user_name'] . "</a>";
         $revert_link = "<a href='" . make_link("note/revert/" . $history['note_id'] . "/" . $history['review_id']) . "'>Revert</a>";
         $html .= "<tr class='{$oe}'>" . "<td>" . $image_link . "</td>" . "<td>" . $history_link . "</td>" . "<td style='text-align:left;'>" . $history['note'] . "</td>" . "<td>" . $user_link . "</td>" . "<td>" . autodate($history['date']) . "</td>";
         if (!$user->is_anonymous()) {
             $html .= "<td>" . $revert_link . "</td>";
         }
     }
     $html .= "</tr></tbody></table>";
     $page->set_title("Note History");
     $page->set_heading("Note History");
     $page->add_block(new Block("Note History", $html, "main", 10));
     $this->display_paginator($page, "note/updated", null, $pageNumber, $totalPages);
 }
Example #11
0
 /**
  * @param \Comment $comment
  * @param bool $trim
  * @return string
  */
 protected function comment_to_html(Comment $comment, $trim = false)
 {
     global $config, $user;
     $tfe = new TextFormattingEvent($comment->comment);
     send_event($tfe);
     $i_uid = int_escape($comment->owner_id);
     $h_name = html_escape($comment->owner_name);
     $h_poster_ip = html_escape($comment->poster_ip);
     $h_timestamp = autodate($comment->posted);
     $h_comment = $trim ? truncate($tfe->stripped, 50) : $tfe->formatted;
     $i_comment_id = int_escape($comment->comment_id);
     $i_image_id = int_escape($comment->image_id);
     if ($i_uid == $config->get_int("anon_id")) {
         $anoncode = "";
         $anoncode2 = "";
         if ($this->show_anon_id) {
             $anoncode = '<sup>' . $this->anon_id . '</sup>';
             if (!array_key_exists($comment->poster_ip, $this->anon_map)) {
                 $this->anon_map[$comment->poster_ip] = $this->anon_id;
             }
             #if($user->can("view_ip")) {
             #$style = " style='color: ".$this->get_anon_colour($comment->poster_ip).";'";
             if ($user->can("view_ip") || $config->get_bool("comment_samefags_public", false)) {
                 if ($this->anon_map[$comment->poster_ip] != $this->anon_id) {
                     $anoncode2 = '<sup>(' . $this->anon_map[$comment->poster_ip] . ')</sup>';
                 }
             }
         }
         $h_userlink = "<span class='username'>" . $h_name . $anoncode . $anoncode2 . "</span>";
         $this->anon_id++;
     } else {
         $h_userlink = '<a class="username" href="' . make_link('user/' . $h_name) . '">' . $h_name . '</a>';
     }
     $stripped_nonl = str_replace("\n", "\\n", substr($tfe->stripped, 0, 50));
     $stripped_nonl = str_replace("\r", "\\r", $stripped_nonl);
     $hb = $comment->owner_class == "hellbanned" ? "hb" : "";
     if ($trim) {
         $html = "\n\t\t\t<div class=\"comment {$hb}\">\n\t\t\t\t{$h_userlink}: {$h_comment}\n\t\t\t\t<a href=\"" . make_link("post/view/{$i_image_id}#c{$i_comment_id}") . "\">&gt;&gt;&gt;</a>\n\t\t\t</div>\n\t\t\t";
     } else {
         $h_avatar = "";
         if (!empty($comment->owner_email)) {
             $hash = md5(strtolower($comment->owner_email));
             $cb = date("Y-m-d");
             $h_avatar = "<img src=\"http://www.gravatar.com/avatar/{$hash}.jpg?cacheBreak={$cb}\"><br>";
         }
         $h_reply = " - <a href='javascript: replyTo({$i_image_id}, {$i_comment_id}, \"{$h_name}\")'>Reply</a>";
         $h_ip = $user->can("view_ip") ? "<br>" . show_ip($comment->poster_ip, "Comment posted {$comment->posted}") : "";
         $h_del = $user->can("delete_comment") ? ' - <a onclick="return confirm(\'Delete comment by ' . $h_name . ':\\n' . $stripped_nonl . '\');" ' . 'href="' . make_link('comment/delete/' . $i_comment_id . '/' . $i_image_id) . '">Del</a>' : '';
         $html = "\n\t\t\t\t<div class=\"comment {$hb}\" id=\"c{$i_comment_id}\">\n\t\t\t\t\t<div class=\"info\">\n\t\t\t\t\t{$h_avatar}\n\t\t\t\t\t{$h_timestamp}{$h_reply}{$h_ip}{$h_del}\n\t\t\t\t\t</div>\n\t\t\t\t\t{$h_userlink}: {$h_comment}\n\t\t\t\t</div>\n\t\t\t";
     }
     return $html;
 }
Example #12
0
 private function get_history($histories)
 {
     global $user;
     $html = "<table id='poolsList' class='zebra'>" . "<thead><tr>" . "<th>Image</th>" . "<th>Note</th>" . "<th>Body</th>" . "<th>Updater</th>" . "<th>Date</th>";
     if (!$user->is_anonymous()) {
         $html .= "<th>Action</th>";
     }
     $html .= "</tr></thead>" . "<tbody>";
     foreach ($histories as $history) {
         $image_link = "<a href='" . make_link("post/view/" . $history['image_id']) . "'>" . $history['image_id'] . "</a>";
         $history_link = "<a href='" . make_link("note/history/" . $history['note_id']) . "'>" . $history['note_id'] . "." . $history['review_id'] . "</a>";
         $user_link = "<a href='" . make_link("user/" . $history['user_name']) . "'>" . $history['user_name'] . "</a>";
         $revert_link = "<a href='" . make_link("note/revert/" . $history['note_id'] . "/" . $history['review_id']) . "'>Revert</a>";
         $html .= "<tr>" . "<td>" . $image_link . "</td>" . "<td>" . $history_link . "</td>" . "<td style='text-align:left;'>" . $history['note'] . "</td>" . "<td>" . $user_link . "</td>" . "<td>" . autodate($history['date']) . "</td>";
         if (!$user->is_anonymous()) {
             $html .= "<td>" . $revert_link . "</td>";
         }
     }
     $html .= "</tr></tbody></table>";
     return $html;
 }
Example #13
0
 /**
  * @param UserPageBuildingEvent $event
  */
 public function onUserPageBuilding(UserPageBuildingEvent $event)
 {
     global $user, $config;
     $h_join_date = autodate($event->display_user->join_date);
     if ($event->display_user->can("hellbanned")) {
         $h_class = $event->display_user->class->parent->name;
     } else {
         $h_class = $event->display_user->class->name;
     }
     $event->add_stats("Joined: {$h_join_date}", 10);
     $event->add_stats("Class: {$h_class}", 90);
     $av = $event->display_user->get_avatar_html();
     if ($av) {
         $event->add_stats($av, 0);
     } else {
         if ($config->get_string("avatar_host") == "gravatar" && $user->id == $event->display_user->id) {
             $event->add_stats("No avatar? This gallery uses <a href='http://gravatar.com'>Gravatar</a> for avatar hosting, use the" . "<br>same email address here and there to have your avatar synced<br>", 0);
         }
     }
 }
Example #14
0
 protected function comment_to_html($comment, $trim = false)
 {
     global $user;
     $tfe = new TextFormattingEvent($comment->comment);
     // sending this event to all ~50 exts has a lot of overhead
     if (SPEED_HAX) {
         $bb = new BBCode();
         $bb->receive_event($tfe);
     } else {
         send_event($tfe);
     }
     $i_uid = int_escape($comment->owner_id);
     $h_name = html_escape($comment->owner_name);
     $h_poster_ip = html_escape($comment->poster_ip);
     $h_timestamp = autodate($comment->posted);
     $h_comment = $trim ? substr($tfe->stripped, 0, 50) . "..." : $tfe->formatted;
     $i_comment_id = int_escape($comment->comment_id);
     $i_image_id = int_escape($comment->image_id);
     $anoncode = "";
     if ($h_name == "Anonymous" && $this->anon_id >= 0) {
         $anoncode = "<sup>{$this->anon_id}</sup>";
         $this->anon_id++;
     }
     $h_userlink = "<a href='" . make_link("user/{$h_name}") . "'>{$h_name}</a>{$anoncode}";
     $stripped_nonl = str_replace("\n", "\\n", substr($tfe->stripped, 0, 50));
     $stripped_nonl = str_replace("\r", "\\r", $stripped_nonl);
     $h_dellink = $user->is_admin() ? "<br>({$h_poster_ip}, {$h_timestamp}, <a " . "onclick=\"return confirm('Delete comment by {$h_name}:\\n{$stripped_nonl}');\" " . "href='" . make_link("comment/delete/{$i_comment_id}/{$i_image_id}") . "'>Del</a>)" : "";
     if ($trim) {
         return "\n\t\t\t\t{$h_userlink}: {$h_comment}\n\t\t\t\t<a href='" . make_link("post/view/{$i_image_id}") . "'>&gt;&gt;&gt;</a>\n\t\t\t\t{$h_dellink}\n\t\t\t";
     } else {
         //$avatar = "";
         //if(!empty($comment->owner->email)) {
         //	$hash = md5(strtolower($comment->owner->email));
         //	$avatar = "<img src=\"http://www.gravatar.com/avatar/$hash.jpg\"><br>";
         //}
         $oe = $this->comments_shown++ % 2 == 0 ? "even" : "odd";
         return "\n\t\t\t\t<a name='{$i_comment_id}'></a>\n\t\t\t\t<div class='{$oe} comment'>\n\t\t\t\t<!--<span class='timeago' style='float: right;'>{$h_timestamp}</span>-->\n\t\t\t\t{$h_userlink}: {$h_comment}\n\t\t\t\t{$h_dellink}\n\t\t\t\t</div>\n\t\t\t";
     }
 }
Example #15
0
 private function make_thread_list($threads, $showAdminOptions)
 {
     $html = "<table id='threadList' class='zebra'>" . "<thead><tr>" . "<th>Title</th>" . "<th>Author</th>" . "<th>Updated</th>" . "<th>Responses</th>";
     if ($showAdminOptions) {
         $html .= "<th>Actions</th>";
     }
     $html .= "</tr></thead><tbody>";
     $current_post = 0;
     foreach ($threads as $thread) {
         $oe = $current_post++ % 2 == 0 ? "even" : "odd";
         global $config;
         $titleSubString = $config->get_int('forumTitleSubString');
         if ($titleSubString < strlen($thread["title"])) {
             $title = substr($thread["title"], 0, $titleSubString);
             $title = $title . "...";
         } else {
             $title = $thread["title"];
         }
         if ($thread["sticky"] == "Y") {
             $sticky = "Sticky: ";
         } else {
             $sticky = "";
         }
         $html .= "<tr class='{$oe}'>" . '<td class="left">' . $sticky . '<a href="' . make_link("forum/view/" . $thread["id"]) . '">' . $title . "</a></td>" . '<td><a href="' . make_link("user/" . $thread["user_name"]) . '">' . $thread["user_name"] . "</a></td>" . "<td>" . autodate($thread["uptodate"]) . "</td>" . "<td>" . $thread["response_count"] . "</td>";
         if ($showAdminOptions) {
             $html .= '<td><a href="' . make_link("forum/nuke/" . $thread["id"]) . '" title="Delete ' . $title . '">Delete</a></td>';
         }
         $html .= "</tr>";
     }
     $html .= "</tbody></table>";
     return $html;
 }