/**
 * Fetch a list of trackbacks for an entry
 *
 * @access public
 * @param   int     The ID of the entry
 * @param   string  How many trackbacks to show
 * @param   boolean If true, also non-approved trackbacks will be shown
 * @return
 */
function &serendipity_fetchTrackbacks($id, $limit = null, $showAll = false)
{
    global $serendipity;
    if (!$showAll) {
        $and = "AND status = 'approved'";
    }
    $query = "SELECT * FROM {$serendipity['dbPrefix']}comments WHERE entry_id = '" . (int) $id . "' AND (type = 'TRACKBACK' OR type = 'PINGBACK') {$and} ORDER BY id";
    if (isset($limit)) {
        $limit = serendipity_db_limit_sql($limit);
        $query .= " {$limit}";
    }
    $comments = serendipity_db_query($query);
    if (!is_array($comments)) {
        return array();
    }
    return $comments;
}
/**
 * Fetch an array of comments to a specific entry id
 *
 * @access public
 * @param   int     The Entry ID to fetch comments for
 * @param   int     How many comments to fetch (empty: all)
 * @param   string  How shall comments be ordered (ASC|DESC)
 * @param   boolean Shall non-approved comments be displayed?
 * @param   string  Comment type to fetch
 * @return  array   The SQL result of comments
 */
function serendipity_fetchComments($id, $limit = null, $order = '', $showAll = false, $type = 'NORMAL', $where = '')
{
    global $serendipity;
    $and = '';
    if (!empty($limit)) {
        $limit = serendipity_db_limit_sql($limit);
    } else {
        $limit = '';
    }
    if ($type == 'comments' || empty($type)) {
        $type = 'NORMAL';
    } elseif ($type == 'trackbacks') {
        $type = 'TRACKBACK';
    } elseif ($type == 'pingbacks') {
        $type = 'PINGBACK';
    } elseif ($type == 'comments_and_trackbacks') {
        $type = '%';
    }
    if (!empty($id)) {
        $and .= " AND co.entry_id = '" . (int) $id . "'";
    }
    if (!$showAll) {
        $and .= ' AND co.status = \'approved\'';
    }
    $and .= $where;
    if ($serendipity['dbType'] == 'postgres' || $serendipity['dbType'] == 'pdo-postgres') {
        $group = '';
        $distinct = 'DISTINCT';
    } else {
        $group = 'GROUP BY co.id';
        $distinct = '';
    }
    $query = "SELECT {$distinct}\n                    co.id,\n                    co.entry_id, co.timestamp, co.title AS ctitle, co.email, co.url, co.ip, co.body, co.type, co.subscribed,\n                    co.author,\n                    e.title,\n                    e.timestamp AS entrytimestamp,\n                    e.id AS entryid,\n                    e.authorid,\n                    co.id AS commentid,\n                    co.parent_id AS parent_id\n              FROM\n                    {$serendipity['dbPrefix']}comments AS co\n                    LEFT JOIN {$serendipity['dbPrefix']}entries AS e ON (co.entry_id = e.id)\n              WHERE co.type LIKE '" . $type . "' AND co.entry_id > 0 {$and}\n              {$group}\n              ORDER BY\n                    " . ($where != '' ? '' : 'co.id') . " " . ($order != '' ? $order : '') . "\n                    {$limit}";
    $comments = serendipity_db_query($query, false, 'assoc');
    if (!is_array($comments)) {
        $comments = array();
    }
    $addData = array('id' => $id, 'limit' => $limit, 'order' => $order, 'showAll' => $showAll, 'type' => $type, 'where' => $where);
    serendipity_plugin_api::hook_event('fetchcomments', $comments, $addData);
    return $comments;
}
 function generate_content(&$title)
 {
     global $serendipity;
     $number = $this->get_config('number');
     $dateformat = $this->get_config('dateformat');
     $category = $this->get_config('category', 'none');
     $show_where = $this->get_config('show_where', 'both');
     if ($show_where == 'extended' && (!isset($serendipity['GET']['id']) || !is_numeric($serendipity['GET']['id']))) {
         return false;
     } else {
         if ($show_where == 'overview' && isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])) {
             return false;
         }
     }
     if ($category == '_cur') {
         $category = $serendipity['GET']['category'];
         if (empty($category) && !empty($serendipity['GET']['id'])) {
             $entry = serendipity_fetchEntry('id', $serendipity['GET']['id']);
             $category = $entry['categories'][0]['categoryid'];
         }
     }
     $title = $this->get_config('title', $this->title);
     $number_from_sw = $this->get_config('number_from');
     $randomize = $this->get_config('randomize') == "yes" ? true : false;
     $sql_condition = array();
     $sql_condition['joins'] = '';
     $sql_condition['and'] = '';
     if ($category != 'none' && !empty($category)) {
         $sql_categories = array();
         if (is_numeric($category)) {
             $sql_categories[] = $category;
         } else {
             $sql_categories = explode('^', $category);
         }
         $category_parts = array();
         foreach ($sql_categories as $sql_category) {
             $category_parts[] = "\n" . implode(' AND ', serendipity_fetchCategoryRange($sql_category));
         }
         $sql_condition['and'] .= ' AND (c.category_left BETWEEN ' . implode(' OR c.category_left BETWEEN ', $category_parts) . ')';
     }
     if (!$number || !is_numeric($number) || $number < 1) {
         $number = 10;
     }
     $sql_number = serendipity_db_limit_sql($number);
     $db = $serendipity['dbType'];
     switch ($number_from_sw) {
         case 'skip':
             $sql_number = serendipity_db_limit_sql(serendipity_db_limit($serendipity['fetchLimit'], $number));
             break;
     }
     if (!$dateformat || strlen($dateformat) < 1) {
         $dateformat = '%A, %B %e %Y';
     }
     if ($randomize) {
         if ($db == 'mysql' || $db == 'mysqli') {
             $sql_order = "ORDER BY RAND()";
         } else {
             // SQLite and PostgreSQL support this, hooray.
             $sql_order = "ORDER BY RANDOM()";
         }
     } else {
         $sql_order = "ORDER BY timestamp DESC ";
     }
     $sql_condition['and'] .= "AND timestamp <= " . time();
     serendipity_ACL_SQL($sql_condition, $category == 'none');
     if (!stristr($sql_condition['joins'], $serendipity['dbPrefix'] . 'category')) {
         $sql_condition['joins'] = ' LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'category AS c  ON ec.categoryid = c.categoryid ' . $sql_condition['joins'];
     }
     if (!stristr($sql_condition['joins'], $serendipity['dbPrefix'] . 'entrycat')) {
         $sql_condition['joins'] = ' LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'entrycat AS ec ON id = ec.entryid ' . $sql_condition['joins'];
     }
     $entries_query = "SELECT DISTINCT id,\n                                title,\n                                timestamp,\n                                epm.value AS multilingual_title\n                           FROM {$serendipity['dbPrefix']}entries AS e\n                                {$sql_condition['joins']}\n\n                LEFT OUTER JOIN {$serendipity['dbPrefix']}entryproperties AS epm\n                             ON (epm.entryid = e.id AND epm.property = 'multilingual_title_" . $serendipity['lang'] . "')\n\n                          WHERE isdraft = 'false' {$sql_condition['and']}\n                                {$sql_order}\n                                {$sql_number}";
     $entries = serendipity_db_query($entries_query);
     if (is_string($entries)) {
         echo $entries . "<br />\n";
         echo $entries_query . "<br />\n";
     }
     if (isset($entries) && is_array($entries)) {
         echo '<dl>' . "\n";
         foreach ($entries as $k => $entry) {
             if (!empty($entry['multilingual_title'])) {
                 $entry['title'] = $entry['multilingual_title'];
             }
             $entryLink = serendipity_archiveURL($entry['id'], $entry['title'], 'serendipityHTTPPath', true, array('timestamp' => $entry['timestamp']));
             if (empty($entry['title'])) {
                 $entry['title'] = '#' . $entry['id'];
             }
             echo '<dt class="serendipity_recententries_entrylink"><a href="' . $entryLink . '" title="' . serendipity_specialchars($entry['title']) . '">' . serendipity_specialchars($entry['title']) . '</a></dt>' . "\n" . '<dd class="serendipity_recententries_entrydate serendipitySideBarDate">' . serendipity_specialchars(serendipity_strftime($dateformat, $entry['timestamp'])) . '</dd>' . "\n";
         }
         echo '</dl>' . "\n\n";
     }
 }
/**
 * Gets a list of media items from our media database
 *
 * LONG
 *
 * @access public
 * @param   int     The offset to start fetching media files
 * @param   int     How many items to fetch
 * @param   int     The number (referenced varaible) of fetched items
 * @param   string  The "ORDER BY" sql part when fetching items
 * @param   string  Order by DESC or ASC
 * @param   string  Only fetch files from a specific directory
 * @param   string  Only fetch specific filenames
 * @param   string  Only fetch media with specific keyword
 * @param   array   An array of restricting filter sets
 * @param   boolean Apply strict directory checks, or include subdirectories?
 * @return  array   Resultset of images
 */
function serendipity_fetchImagesFromDatabase($start = 0, $limit = 0, &$total, $order = false, $ordermode = false, $directory = '', $filename = '', $keywords = '', $filter = array(), $strict_directory = false)
{
    global $serendipity;
    $cond = array('joinparts' => array(), 'parts' => array());
    $orderfields = serendipity_getImageFields();
    if (empty($order) || !isset($orderfields[$order])) {
        $order = 'i.date';
    }
    if (!is_array($filter)) {
        $filter = array();
    }
    if (empty($ordermode) || $ordermode != 'DESC' && $ordermode != 'ASC') {
        $ordermode = 'DESC';
    }
    if ($order == 'name') {
        $order = 'realname ' . $ordermode . ', name';
    }
    if ($limit != 0) {
        $limitsql = serendipity_db_limit_sql(serendipity_db_limit($start, $limit));
    }
    if ($strict_directory) {
        $cond['parts']['directory'] = " AND i.path = '" . serendipity_db_escape_string($directory) . "'\n";
    } elseif (!empty($directory)) {
        $cond['parts']['directory'] = " AND i.path LIKE '" . serendipity_db_escape_string($directory) . "%'\n";
    }
    if (!empty($filename)) {
        $cond['parts']['filename'] = " AND (i.name     like '%" . serendipity_db_escape_string($filename) . "%' OR\n                  i.realname like '%" . serendipity_db_escape_string($filename) . "%')\n";
    }
    if (!is_array($keywords)) {
        if (!empty($keywords)) {
            $keywords = explode(';', $keywords);
        } else {
            $keywords = array();
        }
    }
    if (count($keywords) > 0) {
        $cond['parts']['keywords'] = " AND (mk.property IN ('" . serendipity_db_implode("', '", $keywords, 'string') . "'))\n";
        $cond['joinparts']['keywords'] = true;
    }
    foreach ($filter as $f => $fval) {
        if (!isset($orderfields[$f]) || empty($fval)) {
            continue;
        }
        if (is_array($fval)) {
            if (empty($fval['from']) || empty($fval['to'])) {
                continue;
            }
            if ($orderfields[$f]['type'] == 'date') {
                $fval['from'] = serendipity_convertToTimestamp(trim($fval['from']));
                $fval['to'] = serendipity_convertToTimestamp(trim($fval['to']));
            }
            if (substr($f, 0, 3) === 'bp.') {
                $realf = substr($f, 3);
                $cond['parts']['filter'] .= " AND (bp2.property = '{$realf}' AND bp2.value >= " . (int) $fval['from'] . " AND bp2.value <= " . (int) $fval['to'] . ")\n";
            } else {
                $cond['parts']['filter'] .= " AND ({$f} >= " . (int) $fval['from'] . " AND {$f} <= " . (int) $fval['to'] . ")\n";
            }
        } elseif ($f == 'i.authorid') {
            $cond['parts']['filter'] .= " AND (\n                                    (hp.property = 'authorid' AND hp.value = " . (int) $fval . ")\n                                    OR\n                                    (i.authorid = " . (int) $fval . ")\n                                )\n";
            $cond['joinparts']['hiddenproperties'] = true;
        } elseif ($orderfields[$f]['type'] == 'int') {
            if (substr($f, 0, 3) === 'bp.') {
                $realf = substr($f, 3);
                $cond['parts']['filter'] .= " AND (bp2.property = '{$realf}' AND bp2.value = '" . serendipity_db_escape_string(trim($fval)) . "')\n";
            } else {
                $cond['parts']['filter'] .= " AND ({$f} = '" . serendipity_db_escape_string(trim($fval)) . "')\n";
            }
        } else {
            if (substr($f, 0, 3) === 'bp.') {
                $realf = substr($f, 3);
                $cond['parts']['filter'] .= " AND (bp2.property = '{$realf}' AND bp2.value LIKE '%" . serendipity_db_escape_string(trim($fval)) . "%')\n";
            } else {
                $cond['parts']['filter'] .= " AND ({$f} LIKE '%" . serendipity_db_escape_string(trim($fval)) . "%')\n";
            }
        }
        $cond['joinparts']['filterproperties'] = true;
    }
    if (isset($serendipity['authorid']) && !serendipity_checkPermission('adminImagesViewOthers')) {
        $cond['parts']['authorid'] .= " AND (i.authorid = 0 OR i.authorid = " . (int) $serendipity['authorid'] . ")\n";
    }
    $cond['and'] = 'WHERE 1=1 ' . implode("\n", $cond['parts']);
    $cond['args'] = func_get_args();
    serendipity_plugin_api::hook_event('fetch_images_sql', $cond);
    serendipity_ACL_SQL($cond, false, 'directory');
    if ($cond['joinparts']['keywords']) {
        $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS mk\n                                        ON (mk.mediaid = i.id AND mk.property_group = 'base_keyword')\n";
    }
    if (substr($order, 0, 3) === 'bp.') {
        $cond['orderproperty'] = substr($order, 3);
        $cond['orderkey'] = 'bp.value';
        $order = 'bp.value';
        $cond['joinparts']['properties'] = true;
    } else {
        $cond['orderkey'] = "''";
    }
    if ($cond['joinparts']['properties']) {
        $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS bp\n                                        ON (bp.mediaid = i.id AND bp.property_group = 'base_property' AND bp.property = '{$cond['orderproperty']}')\n";
    }
    if ($cond['joinparts']['filterproperties']) {
        $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS bp2\n                                        ON (bp2.mediaid = i.id AND bp2.property_group = 'base_property')\n";
    }
    if ($cond['joinparts']['hiddenproperties']) {
        $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS hp\n                                        ON (hp.mediaid = i.id AND hp.property_group = 'base_hidden')\n";
    }
    if ($serendipity['dbType'] == 'postgres' || $serendipity['dbType'] == 'pdo-postgres') {
        $cond['group'] = '';
        $cond['distinct'] = 'DISTINCT';
    } else {
        $cond['group'] = 'GROUP BY i.id';
        $cond['distinct'] = '';
    }
    $basequery = "FROM {$serendipity['dbPrefix']}images AS i\n       LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a\n                    ON i.authorid = a.authorid\n                       {$cond['joins']}\n\n                       {$cond['and']}";
    $query = "SELECT {$cond['distinct']} i.id, {$cond[orderkey]} AS orderkey, i.name, i.extension, i.mime, i.size, i.dimensions_width, i.dimensions_height, i.date, i.thumbnail_name, i.authorid, i.path, i.hotlink, i.realname,\n                     a.realname AS authorname\n                     {$basequery}\n                     {$cond['group']}\n            ORDER BY {$order} {$ordermode} {$limitsql}";
    $rs = serendipity_db_query($query, false, 'assoc');
    if (!is_array($rs) && $rs !== true && $rs !== 1) {
        echo '<div>' . $rs . '</div>';
        return array();
    } elseif (!is_array($rs)) {
        return array();
    }
    $total_query = "SELECT count(i.id)\n                           {$basequery}\n                           GROUP BY i.id";
    $total_rs = serendipity_db_query($total_query, false, 'num');
    if (is_array($total_rs)) {
        $total = count($total_rs);
    }
    return $rs;
}
/**
 * Searches the list of entries by a specific term
 *
 * @todo: Allow to show results of staticpage plugins or others
 * @access public
 * @param   string      The searchterm (may contain wildcards)
 * @param   int         Restrict the number of results [also uses $serendipity['GET']['page'] for pagination]
 * @param   array       Add search Results at the top
 * @return  array       Returns the superarray of entries found
 */
function &serendipity_searchEntries($term, $limit = '', $searchresults = '')
{
    global $serendipity;
    static $log_queries = false;
    if ($log_queries) {
        $fp = fopen($serendipity['serendipityPath'] . '/archives/queries.csv', 'a');
        fwrite($fp, date('Y-m-d H:i') . ';' . $_SERVER['REMOTE_ADDR'] . ';' . $term . "\n");
        fclose($fp);
    }
    $orig_limit = $limit;
    if ($limit == '') {
        $limit = $serendipity['fetchLimit'];
    }
    if (isset($serendipity['GET']['page']) && $serendipity['GET']['page'] > 1 && !strstr($limit, ',')) {
        $limit = serendipity_db_limit(($serendipity['GET']['page'] - 1) * $limit, $limit);
    }
    $limit = serendipity_db_limit_sql($limit);
    $term = serendipity_db_escape_string($term);
    $cond = array();
    $relevance_enabled = false;
    if ($serendipity['dbType'] == 'postgres' || $serendipity['dbType'] == 'pdo-postgres') {
        $cond['group'] = '';
        $cond['distinct'] = 'DISTINCT';
        $r = serendipity_db_query("SELECT count(routine_name) AS counter\n                                     FROM information_schema.routines\n                                    WHERE routine_name LIKE 'to_tsvector'\n                                      AND specific_catalog = '" . $serendipity['dbName'] . "'");
        if (is_array($r) && $r[0]['counter'] > 0) {
            $term = str_replace('&amp;', '&', $term);
            $cond['find_part'] = "(\n            to_tsvector('english', title)    @@to_tsquery('{$term}') OR\n            to_tsvector('english', body)     @@to_tsquery('{$term}') OR\n            to_tsvector('english', extended) @@to_tsquery('{$term}')\n            )";
        } else {
            $cond['find_part'] = "(title ILIKE '%{$term}%' OR body ILIKE '%{$term}%' OR extended ILIKE '%{$term}%')";
        }
    } elseif ($serendipity['dbType'] == 'sqlite' || $serendipity['dbType'] == 'sqlite3') {
        // Very extensive SQLite search. There currently seems no other way to perform fulltext search in SQLite
        // But it's better than no search at all :-D
        $cond['group'] = 'GROUP BY e.id';
        $cond['distinct'] = '';
        $term = serendipity_mb('strtolower', $term);
        $cond['find_part'] = "(lower(title) LIKE '%{$term}%' OR lower(body) LIKE '%{$term}%' OR lower(extended) LIKE '%{$term}%')";
    } else {
        $cond['group'] = 'GROUP BY e.id';
        $cond['distinct'] = '';
        $term = str_replace('&quot;', '"', $term);
        $relevance_enabled = true;
        if (preg_match('@["\\+\\-\\*~<>\\(\\)]+@', $term)) {
            $cond['find_part'] = "MATCH(title,body,extended) AGAINST('{$term}' IN BOOLEAN MODE)";
        } else {
            $cond['find_part'] = "MATCH(title,body,extended) AGAINST('{$term}')";
        }
    }
    switch ($serendipity['searchsort']) {
        case 'relevance':
            if ($relevance_enabled) {
                $cond['searchorderby'] = $cond['find_part'] . " DESC";
            } else {
                $cond['searchorderby'] = "timestamp DESC";
            }
            break;
        case 'timestamp':
        default:
            $cond['searchorderby'] = "timestamp DESC";
            break;
    }
    $cond['and'] = " AND isdraft = 'false' " . (!serendipity_db_bool($serendipity['showFutureEntries']) ? " AND timestamp <= " . serendipity_db_time() : '');
    serendipity_plugin_api::hook_event('frontend_fetchentries', $cond, array('source' => 'search', 'term' => $term));
    serendipity_ACL_SQL($cond, 'limited');
    $serendipity['fullCountQuery'] = "\n                      FROM\n                            {$serendipity['dbPrefix']}entries e\n                 LEFT JOIN  {$serendipity['dbPrefix']}authors a\n                        ON  e.authorid = a.authorid\n                 LEFT JOIN  {$serendipity['dbPrefix']}entrycat ec\n                        ON  e.id = ec.entryid\n                            {$cond['joins']}\n                     WHERE\n                            ({$cond['find_part']})\n                            {$cond['and']}";
    $querystring = "SELECT {$cond['distinct']}\n                            {$cond['addkey']}\n                            e.id,\n                            e.authorid,\n                            a.realname AS author,\n                            e.allow_comments,\n                            e.moderate_comments,\n                            a.email,\n                            e.timestamp,\n                            e.comments,\n                            e.title,\n                            e.body,\n                            e.extended,\n                            e.trackbacks,\n                            e.exflag,\n                            e.isdraft,\n                            e.last_modified,\n                            a.username AS loginname\n                    {$serendipity['fullCountQuery']}\n                    {$cond['group']}\n                    {$cond['having']}\n                  ORDER BY  {$cond['searchorderby']}\n                    {$limit}";
    $search =& serendipity_db_query($querystring);
    //Add param searchresults at the top and remove duplicates.
    if (is_array($searchresults)) {
        $ids_current = array();
        foreach ($searchresults as $idx => $data) {
            $ids_current[$data['id']] = true;
        }
        foreach ($search as $idx => $data) {
            if (isset($ids_current[$data['id']])) {
                unset($search[$idx]);
            }
        }
        $search = array_merge($searchresults, $search);
    }
    //if * wasn't already appended and if there are none or not enough
    //results, search again for entries containing the searchterm as a part
    if (strpos($term, '*') === false) {
        if (!is_array($search)) {
            return serendipity_searchEntries($term . '*', $orig_limit);
        } else {
            if (count($search) < 4) {
                return serendipity_searchEntries($term . '*', $orig_limit, $search);
            }
        }
    }
    if (is_array($search)) {
        serendipity_fetchEntryData($search);
    }
    return $search;
}
    function event_hook($event, &$bag, &$eventData, $addData = null)
    {
        global $serendipity;
        $hooks =& $bag->get('event_hooks');
        if (isset($hooks[$event])) {
            // Moved from above: only get image data if we're actually going to do something
            $this->set_valid_image_data();
            // Get dimensions of image, only if not text-only
            if ($this->image_name) {
                // Is this a single-image bar, or a single segment?
                $ratio = $this->image_width / $this->image_height;
                if ($ratio < $this->max_segment_ratio) {
                    // This is probably a single segment. Square segments
                    // will have a ratio of 0.3; long, flat segments won't
                    // get up to 1.0 unless they're 3 times as wide as they
                    // are tall; full-bar images with square segments will
                    // be 1.666; and full-bar images with tall, narrow
                    // segments will be greater than 1.0 unless they're
                    // nearly twice as high as they are wide.
                    $this->image_width = $this->image_width * 5;
                }
            }
            switch ($event) {
                //Javascript for ajax functionality
                case 'frontend_footer':
                    if ($this->get_config('ajax') == true) {
                        ?>
<script type="text/javascript">
/*<![CDATA[ */
ajaxloader = new Image();
ajaxloader.src = "<?php 
                        echo $serendipity['baseURL'];
                        ?>
plugins/serendipity_event_karma/img/ajax-loader.gif";
for (i=1;i<6;i++) {
    jQuery('.serendipity_karmaVoting_link'+i).click(function(event) {
        event.preventDefault();
        karmaId = jQuery(this).attr('href').match(/\[karmaId\]=([0-9]+)/);
        vote(jQuery(this).html(),karmaId[1]);
    });
}

function vote(karmaVote,karmaId) {
    // Send the data using post and put the results in place
    jQuery('#karma_vote'+karmaId).parent().children('.serendipity_karmaVoting_links').replaceWith('<div class="serendipity_karmaVoting_links ajaxloader"><img src="<?php 
                        echo $serendipity['baseURL'];
                        ?>
plugins/serendipity_event_karma/img/ajax-loader.gif" border="0" alt="ajax-loader" /></div>');
    jQuery.post("<?php 
                        echo $serendipity['baseURL'] . $serendipity['permalinkPluginPath'];
                        ?>
/karma-ajaxquery", { karmaVote: karmaVote, karmaId: karmaId }, function(data) {
        jQuery('#karma_vote'+karmaId).parent().replaceWith(data);
    });
}
/* ]]>*/
</script>
<?php 
                    }
                    // Hook for ajax calls
                // Hook for ajax calls
                case 'external_plugin':
                    $theUri = (string) str_replace('&amp;', '&', $eventData);
                    $uri_parts = explode('?', $theUri);
                    // Try to get request parameters from eventData name
                    if (!empty($uri_parts[1])) {
                        $reqs = explode('&', $uri_parts[1]);
                        foreach ($reqs as $id => $req) {
                            $val = explode('=', $req);
                            if (empty($_REQUEST[$val[0]])) {
                                $_REQUEST[$val[0]] = $val[1];
                            }
                        }
                    }
                    $parts = explode('_', $uri_parts[0]);
                    switch ($parts[0]) {
                        case 'karma-ajaxquery':
                            $this->performkarmaVote();
                            $q = "SELECT SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits\n                                    FROM " . $serendipity['dbPrefix'] . "karma\n                                   WHERE entryid = '" . (int) $_POST['karmaId'] . "';";
                            $sql = serendipity_db_query($q);
                            $track_clicks = serendipity_db_bool($this->get_config('visits_active', true));
                            $track_karma = serendipity_db_bool($this->get_config('karma_active', true));
                            $enough_votes = $track_karma && $sql[0]['votes'] >= $this->get_config('min_disp_votes', 0);
                            $enough_visits = $track_clicks && $sql[0]['visits'] >= $this->get_config('min_disp_visits', 0);
                            $textual_msg = true;
                            $textual_current = true;
                            $textual_visits = true;
                            if ($this->image_name != '0') {
                                $textual_msg = $this->get_config('textual_msg', 'true');
                                $textual_current = $this->get_config('textual_current', 'true');
                                $textual_visits = $this->get_config('textual_visits', 'true');
                            }
                            $temp = $this->karmaVoted((int) $_POST['karmaVote'], $sql[0]['points'], $sql[0]['votes']);
                            $myvote = $temp['myvote'];
                            $msg = $temp['msg'];
                            $bar = $temp['bar'];
                            $temp = $this->createkarmaBlock((int) $_POST['karmaId'], $textual_msg, $msg, $bar, $enough_votes, $textual_current, $enough_visits, $textual_visits, $sql[0]['points'], $sql[0]['votes']);
                            $karma_block = $temp['karma_block'];
                            $points = $temp['points'];
                            echo sprintf($karma_block, $myvote, $points, $sql[0]['votes'], $sql[0]['visits'], '');
                            break;
                    }
                    return true;
                    break;
                    // Early hook, before any page is displayed
                // Early hook, before any page is displayed
                case 'frontend_configure':
                    $this->performkarmaVote();
                    return true;
                    break;
                    // CSS generation hooks
                // CSS generation hooks
                case 'backend_header':
                    if ($serendipity['GET']['adminModule'] == 'event_display' && $serendipity['GET']['adminAction'] == 'karmalog' || $serendipity['GET']['adminModule'] == 'plugins') {
                        // Generate the CSS for the graphical rating bar selector
                        //
                        // The CSS appears to be generated in a completely
                        // different instance of Serendipity, as if index.php gets
                        // called separately for the CSS.
                        //
                        // Note that the css_backend hook adds properties to the
                        // serendipity_admin.css, but that file is *always*
                        // cached.  We use backend_header and add the CSS to the
                        // HEAD styles to make it dynamic. (Edit: with 2.0 this has changed)
                        // Get the CSS, set $this->image_name so we'll output the
                        // standard graphical CSS prologue if any images are found.
                        $this->createRatingSelector();
                        print "<style type='text/css'>\n";
                        $align = 'center';
                        $bg = $this->get_config('preview_bg', false);
                        if (!empty($bg)) {
                            if (strpos($bg, ';') !== false || strpos($bg, ',') !== false) {
                                $bg = 'red';
                            }
                            print "\n.serendipity_karmaVote_selectorTable {\n    background: {$bg};\n}\n";
                        }
                        print "\n.serendipityAdminContent .serendipity_karmaVoting_links {\n    margin: 5px;\n}\n";
                        if ($serendipity['version'][0] > 1) {
                            print "\n</style>\n";
                        }
                    }
                    if ($serendipity['version'][0] > 1) {
                        break;
                        return true;
                    }
                case 'css_backend':
                case 'css':
                    // Some CSS notes:
                    //
                    // .serendipity_karmaVoting is the class for the karma wrapper/container,
                    //      including the text explanations, messages, and rating bar.
                    //      (currently a div)
                    // .serendipity_karmaVoting a specifies the links for the text-mode
                    //      rating bar
                    // .serendipity_karmaError is the class for any text indicating an
                    //      error condition
                    // .serendipity_karmaSuccess is the class for any text indicating
                    //      successful operation
                    // .serendipity_karmaVoting_links is the container for the graphical
                    //      rating bar (currently an ol)
                    // .serendipity_karmaVoting_links a indicates the various voting links in
                    //      the graphical rating bar
                    // .serendipity_karmaVoting_current-rating is the class for the current
                    //      rating in the graphical rating bar
                    //  a.serendipity_karmaVoting_link1, _link2, etc are the classes applied
                    //      to the individual voting links
                    // Note that there are two possible template types: early
                    // templates that only handle the text rating bars, and
                    // newer templates that understand the graphical raters.
                    // We check for both types and act appropriately.
                    /*--JAM: Let's just skip this whole hassle
                      if (!$align) {
                          $align = $this->get_config('alignment', 'detect');
                      }
                      if ($align == 'detect') {
                      */
                    $align = $this->get_config('alignment');
                    // Try to let the template take care of it
                    if ($this->image_name == '0') {
                        // Text-only rating bar is used
                        if (strpos($eventData, '.serendipity_karmaVoting')) {
                            // Template is handling all our CSS
                            return true;
                        }
                    }
                    /* --JAM: else {
                               // Graphical rating bar is used
                               if (strpos($eventData, '.serendipity_karmaVoting_images')) {
                                   // Template is handling all our CSS
                                   return true;
                               }
                               // Check for old text-only templates
                               $pos = strpos($eventData, '.serendipity_karmaVoting');
                               while ($pos && ($align == 'detect')) {
                                   // Find text-align: in the current block
                                   $endpos = strpos($eventData, '}', $pos);
                                   if (!$endpos) {
                                       // Broken CSS
                                       break;
                                   }
                                   $alignpos = strpos($eventData, 'text-align:', $pos);
                                   // Can't check for comments, or I would.  Hope
                                   // the first is the correct one.
                                   if ($alignpos && $alignpos < $endpos) {
                                       $start = $alignpos + 11;
                                       $alignend = strpos($eventData, ';', $alignpos);
                                       if ($alignend)
                                       {
                                           // All valid.  Pull out the alignment.
                                           $len = $alignend - $start;
                                           $align = trim(substr($eventData, $start, $len));
                                       }
                                   }
                                   $pos = strpos($eventData, '.serendipity_karmaVoting', $endpos);
                               }
                               // I should have a valid alignment or 'detect' in $align now.
                           }
                       }
                       // If we couldn't detect the alignment, guess 'right'
                       if ($align == 'detect') {
                           $align = 'right';
                       }
                       --JAM: END COMMENT BLOCK */
                    if ($serendipity['version'][0] < 2 && $event == 'backend_header') {
                        print "<style type='text/css'>\n";
                    }
                    // Since errors might be printed at any time, always
                    // output the text-mode CSS
                    print <<<EOS
.serendipity_karmaVoting {
    text-align: {$align};
    font-size: 7pt;
    margin: 0px;
}

.serendipity_karmaVoting a {
    font-size: 7pt;
    text-decoration: none;
}

.serendipity_karmaVoting a:hover {
    color: green;
}

.serendipity_karmaError {
    color: #FF8000;
}
.serendipity_karmaSuccess {
    color: green;
}
EOS;
                    // Only output the image CSS if it's needed
                    if ($this->image_name != '0') {
                        $img = $serendipity['baseURL'] . "plugins/serendipity_event_karma/img/" . $this->image_name;
                        $h = $this->image_height / 3;
                        $w = $this->image_width;
                        switch ($align) {
                            case 'left':
                                $margin = '0px auto 0px 0px';
                                break;
                            case 'center':
                                $margin = '0px auto';
                                break;
                            case 'right':
                            default:
                                $margin = '0px 0px 0px auto';
                                break;
                        }
                        // The CSS here is lifted largely from
                        // http://komodomedia.com/blog/index.php/2007/01/20/css-star-rating-redux/
                        //
                        // Note, however that margin has been changed for
                        // multiple cases and all unitless measurements have
                        // been specified in pixels.  Additionally, measures
                        // have been taken to align the text.
                        print <<<END_IMG_CSS

.serendipity_karmaVoting_links,
.serendipity_karmaVoting_links a:hover,
.serendipity_karmaVoting_current-rating {
    background: url({$img}) left;
    font-size: 0;
}
.ajaxloader {
    background-image: none;
}
.serendipity_karmaVoting_links {
    position: relative;
    width: {$w}px;
    height: {$h}px;
    overflow: hidden;
    list-style: none;
    margin: {$margin};
    padding: 0;
    background-position: left top;
    text-align: center;
}
.serendipity_karmaVoting_links li {
   display: inline;
}
.serendipity_karmaVoting_links a ,
.serendipity_karmaVoting_current-rating {
    position:absolute;
    top: 0;
    left: 0;
    text-indent: -9000em;
    height: {$h}px;
    line-height: {$h}px;
    outline: none;
    overflow: hidden;
    border: none;
}
.serendipity_karmaVoting_links a:hover {
    background-position: left bottom;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link1 {
    width: 20%;
    z-index: 6;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link2 {
    width: 40%;
    z-index: 5;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link3 {
    width: 60%;
    z-index: 4;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link4 {
    width: 80%;
    z-index: 3;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link5 {
  width: 100%;
    z-index: 2;
}
.serendipity_karmaVoting_links .serendipity_karmaVoting_current-rating {
    z-index: 1;
    background-position: left center;
}

END_IMG_CSS;
                        // Add selector images CSS, if necessary
                        if (!empty($this->select_css)) {
                            print $this->select_css;
                        }
                    }
                    // End if image bar defined
                    if ($serendipity['version'][0] < 2 && $event == 'backend_header') {
                        print "\n</style>\n";
                    }
                    return true;
                    break;
                    //--TODO: Comment the functionality of this event hook.
                //--TODO: Comment the functionality of this event hook.
                case 'event_additional_statistics':
                    $sql = array();
                    $sql['visits_top'] = array('visits', 'DESC');
                    $sql['visits_bottom'] = array('visits', 'ASC');
                    $sql['votes_top'] = array('votes', 'DESC');
                    $sql['votes_bottom'] = array('votes', 'ASC');
                    $sql['points_top'] = array('points', 'DESC');
                    $sql['points_bottom'] = array('points', 'ASC');
                    foreach ($sql as $key => $rows) {
                        $q = "SELECT e.id,\n                                     e.title,\n                                     e.timestamp,\n                                     SUM(k.{$rows[0]}) AS no\n                                FROM {$serendipity['dbPrefix']}karma\n                                     AS k\n                                JOIN {$serendipity['dbPrefix']}entries\n                                     AS e\n                                  ON k.entryid = e.id\n                            WHERE k.{$rows[0]} IS NOT NULL AND k.{$rows[0]} != 0\n                            GROUP BY e.id, e.title, e.timestamp ORDER BY no {$rows[1]} LIMIT {$addData['maxitems']}";
                        $sql_rows = serendipity_db_query($q);
                        ?>
    <section>
        <h3><?php 
                        echo constant('PLUGIN_KARMA_STATISTICS_' . strtoupper($key));
                        ?>
</h3>

        <dl>
<?php 
                        if (is_array($sql_rows)) {
                            foreach ($sql_rows as $id => $row) {
                                ?>
            <dt><a href="<?php 
                                echo serendipity_archiveURL($row['id'], $row['title'], 'serendipityHTTPPath', true, array('timestamp' => $row['timestamp']));
                                ?>
"><?php 
                                echo function_exists('serendipity_specialchars') ? serendipity_specialchars($row['title']) : htmlspecialchars($row['title'], ENT_COMPAT, LANG_CHARSET);
                                ?>
</a></dt>
            <dd><?php 
                                echo $row['no'];
                                ?>
 <?php 
                                echo constant('PLUGIN_KARMA_STATISTICS_' . strtoupper($rows[0]) . '_NO');
                                ?>
</dd>
    <?php 
                            }
                        }
                        ?>
        </dl>
    </section>
<?php 
                    }
                    return true;
                    break;
                    // Add voting information to entries
                // Add voting information to entries
                case 'entry_display':
                    // Update database if necessary
                    if ($this->get_config('dbversion', 0) != PLUGIN_KARMA_DB_VERSION) {
                        $this->checkScheme();
                    }
                    // Find the ID of this entry
                    if (isset($serendipity['GET']['id'])) {
                        $entryid = (int) serendipity_db_escape_string($serendipity['GET']['id']);
                    } elseif (preg_match(PAT_COMMENTSUB, $_SERVER['REQUEST_URI'], $matches)) {
                        $entryid = (int) $matches[1];
                    } else {
                        $entryid = false;
                    }
                    // If we're actually reading the entry, not voting or editing it...
                    if ($entryid && empty($serendipity['GET']['adminAction']) && !$serendipity['GET']['karmaVote']) {
                        // Update the number of visits
                        // Are we supposed to track visits?
                        $track_clicks = serendipity_db_bool($this->get_config('visits_active', true)) && $this->track_clicks_allowed_by_user();
                        if ($track_clicks && $_SERVER['REQUEST_METHOD'] == 'GET') {
                            $sql = serendipity_db_query("UPDATE {$serendipity['dbPrefix']}karma \n                                    SET visits = visits + 1 \n                                  WHERE entryid = {$entryid}", true);
                            if (serendipity_db_affected_rows() < 1) {
                                serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}karma (entryid, points, votes, lastvote, visits) \n                                              VALUES ('{$entryid}', 0, 0, 0, 1)");
                            }
                        }
                    }
                    // Set a cookie to look for later, verifying that cookies are enabled
                    serendipity_setCookie('check', '1');
                    switch ($this->karmaVote) {
                        case 'nocookie':
                            // Users with no cookies won't be able to vote.
                            $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_NOCOOKIE . '</div>';
                            // Continue until output
                        // Continue until output
                        case 'timeout2':
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_CLOSED . '</div>';
                            }
                            // Continue until output
                        // Continue until output
                        case 'timeout':
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . sprintf(PLUGIN_KARMA_TIMEOUT, $this->karmaTimeOut) . '</div>';
                            }
                            // Continue until output
                        // Continue until output
                        case 'alreadyvoted':
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_ALREADYVOTED . '</div>';
                            }
                            // Continue until output
                        // Continue until output
                        case 'invalid1':
                        case 'invalid2':
                        case 'invalid':
                            // Set message
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_INVALID . '</div>';
                            }
                            // Continue until output
                            /* OUTPUT MESSAGE */
                            //--TODO: Shouldn't this work with the cache plugin, too?
                            if ($addData['extended']) {
                                $eventData[0]['exflag'] = 1;
                                $eventData[0]['add_footer'] .= $msg;
                            } else {
                                $elements = count($eventData);
                                // Find the right container to store our message in.
                                for ($i = 0; $i < $elements; $i++) {
                                    if ($eventData[$i]['id'] == $this->karmaId) {
                                        $eventData[$i]['add_footer'] .= $msg;
                                    }
                                }
                            }
                            break;
                        case 'voted':
                        default:
                            // If there's no data, there's no need to go on
                            if (!is_array($eventData)) {
                                return;
                            }
                            // Find out what the admin wants
                            $track_clicks = serendipity_db_bool($this->get_config('visits_active', true));
                            $track_karma = serendipity_db_bool($this->get_config('karma_active', true));
                            if (serendipity_db_bool($this->get_config('karma_active_registered', false))) {
                                if (!serendipity_userLoggedIn()) {
                                    $track_karma = false;
                                }
                            }
                            $track_exits = serendipity_db_bool($this->get_config('exits_active', true));
                            // Get the limits
                            $now = time();
                            $karmatime = $this->get_config('max_karmatime', 7);
                            $max_karmatime = $karmatime * 24 * 60 * 60;
                            // Accept infinite voting
                            if ($max_karmatime <= 0) {
                                $max_karmatime = $now;
                            }
                            //--TODO: Ensure that this works with the Custom Permalinks plugin
                            // (We've seen trouble; it votes correctly, but redirects to the front page)
                            $url = serendipity_currentURL(true);
                            // Voting is only allowed on entries.  Therefore voting URLs must be
                            // either single-entry URLs or summary URLs.  serendipity_currentURL
                            // converts them to an "ErrorDocument-URI", so we can focus on the
                            // query portion of the URI.
                            //
                            // Single-entry URLs should be well-defined.  They can be permalinks,
                            // of course; otherwise they're of the configured pattern.
                            //
                            // Summary URLs could be a little harder.  The summary pages that
                            // include entries are: frontpage, category, author, and archives.
                            // It's possible a plugin would show entries, but if that's the case
                            // we don't need to allow the user to vote on them.  Still, that's
                            // a lot of URLs to check for.
                            //
                            // Then there's the problem of the rest of the query.  It could
                            // include stuff we really want to keep around, like template
                            // overrides or something.  One can even add serendipity variables
                            // to the URL in extreme cases.
                            //
                            // It seems that canonicalizing the URL will be quite difficult.
                            // The only thing we can say for certain is that whatever the
                            // current URL is, it got us to this page, and we'd like to return
                            // to this page after we cast our vote.
                            // Remove any clutter from our previous voting activity
                            $url_parts = parse_url(serendipity_currentURL(true));
                            if (!empty($url_parts['query'])) {
                                $exclude = array('serendipity[karmaVote]', 'serendipity[karmaId]');
                                // I tried using parse_str, but it gave me very weird results
                                // with embedded arrays
                                //parse_str($url_parts['query'], $q_parts);
                                $q_parts = array();
                                // I don't know why this URL has been HTML encoded.  Oh well.
                                $pairs = explode('&amp;', $url_parts['query']);
                                foreach ($pairs as $pair) {
                                    $parts = explode('=', $pair);
                                    $q_parts[$parts[0]] = $parts[1];
                                }
                                foreach ($q_parts as $key => $value) {
                                    if (in_array($key, $exclude)) {
                                        $rm = preg_quote("{$key}={$value}");
                                        $url = preg_replace("@(&amp;|&)?{$rm}@", '', $url);
                                    }
                                }
                            }
                            if (substr($url, -1) != '?') {
                                $url .= '&amp;';
                            }
                            // Get the cookie data (past votes, etc)
                            $karma = isset($serendipity['COOKIE']['karmaVote']) ? unserialize($serendipity['COOKIE']['karmaVote']) : array();
                            // Get all required entry IDs, making keys match keys in eventData
                            $entries = array();
                            if ($addData['extended'] || $addData['preview']) {
                                // We're in extended or preview mode, we only need the current ID
                                $eventData[0]['exflag'] = 1;
                                $entries[0] = (int) $eventData[0]['id'];
                            } elseif (!serendipity_db_bool($this->get_config('extended_only', false))) {
                                // We're in overview mode, and we want rating bars for all the entry IDs
                                foreach (array_keys($eventData) as $key) {
                                    if (isset($eventData[$key]['id'])) {
                                        $entries[$key] = (int) $eventData[$key]['id'];
                                    }
                                }
                            }
                            // Fetch votes for all entry IDs. Store them in an array for later usage.
                            $q = 'SELECT k.entryid, SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits
                                    FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
                                   WHERE k.entryid IN (' . implode(', ', $entries) . ') GROUP BY k.entryid';
                            $sql = serendipity_db_query($q);
                            $rows = array();
                            if ($sql && is_array($sql)) {
                                foreach ($sql as $row) {
                                    $rows[$row['entryid']] = array('votes' => $row['votes'], 'points' => $row['points'], 'visits' => $row['visits']);
                                }
                            }
                            $this->prepareExits($entries);
                            // Add karma block to the footer of each entry
                            //
                            // The entries array was populated, above, so its keys match the eventData array,
                            // and overview entries are skipped if "extended only" is enabled
                            foreach (array_keys($entries) as $i) {
                                // Get the statistics
                                $entryid = $eventData[$i]['id'];
                                $votes = !empty($rows[$entryid]['votes']) ? $rows[$entryid]['votes'] : 0;
                                $points = !empty($rows[$entryid]['points']) ? $rows[$entryid]['points'] : 0;
                                $visits = !empty($rows[$entryid]['visits']) ? $rows[$entryid]['visits'] : 0;
                                $enough_votes = $track_karma && $votes >= $this->get_config('min_disp_votes', 0);
                                $enough_visits = $track_clicks && $visits >= $this->get_config('min_disp_visits', 0);
                                $textual_msg = true;
                                $textual_current = true;
                                $textual_visits = true;
                                if ($this->image_name != '0') {
                                    $textual_msg = $this->get_config('textual_msg', 'true');
                                    $textual_current = $this->get_config('textual_current', 'true');
                                    $textual_visits = $this->get_config('textual_visits', 'true');
                                }
                                // Where's the footer?  Normally it would be
                                // in eventData[n]['add_footer'] but if the
                                // cache plugin is used, it's in
                                // eventData[n]['properties']['ep_cache_add_footer'].
                                // This method retrieves it either way.
                                $footer =& $this->getFieldReference('add_footer', $eventData[$i]);
                                // Depending on what existed, $footer could
                                // be referencing the cached version, the
                                // uncached version, or even a new empty
                                // string.  In particular, if $eventData[$i]
                                // has no properties, and no 'add_footer' key,
                                // $footer is referencing a new empty string,
                                // so adding a karma bar to $footer would do
                                // nothing.
                                //
                                // We could be referencing an empty uncached
                                // 'add_footer', but empty cache entries are
                                // never returned.
                                //
                                // Reference a footer that will be printed
                                if (empty($footer) && !isset($eventData[$i]['add_footer']) && is_array($eventData[$i])) {
                                    $eventData[$i]['add_footer'] = '';
                                    $footer =& $eventData[$i]['add_footer'];
                                    // It's still empty, but it's referencing
                                    // the right place.
                                }
                                if ($track_exits) {
                                    $footer .= $this->getExits($entryid, true);
                                }
                                // Pick the appropriate intro msg and rating bar
                                // No msg or bar if karma is disabled
                                if ($track_karma) {
                                    if (isset($karma[$entryid])) {
                                        // We already voted for this one
                                        $temp = $this->karmaVoted($karma[$entryid], $points, $votes);
                                        $myvote = $temp['myvote'];
                                        $msg = $temp['msg'];
                                        $bar = $temp['bar'];
                                    } elseif ($eventData[$i]['timestamp'] < $now - $max_karmatime) {
                                        // Too late to vote for this one
                                        $msg = '<div class="serendipity_karmaClosed">' . sprintf(PLUGIN_KARMA_CLOSED, $karmatime) . '</div>';
                                        // Just a current rating bar, if any
                                        $bar = $this->createRatingBar(null, $points, $votes);
                                    } else {
                                        // We can vote for this; make the whole voting block
                                        $rate_msg = $this->get_config('rate_msg', PLUGIN_KARMA_VOTETEXT);
                                        $msg = '<div class="serendipity_karmaVoting_text">' . $rate_msg . '</div>';
                                        // Full voting bar
                                        $bar = $this->createRatingBar($entryid, $points, $votes);
                                    }
                                }
                                // Create the karma block
                                $temp = $this->createkarmaBlock($entryid, $textual_msg, $msg, $bar, $enough_votes, $textual_current, $enough_visits, $textual_visits, $points, $votes);
                                $karma_block = $temp['karma_block'];
                                $points = $temp['points'];
                                /*
                                  print("<h3>--DEBUG: Karma block code:</h3>\n<pre>\n");
                                  print_r(htmlspecialchars($karma_block));
                                  print("\n</pre>\n");
                                */
                                // Substitute the % stuff and add it to the footer
                                $eventData[$i]['properties']['myvote'] = $myvote;
                                $eventData[$i]['properties']['points'] = $points;
                                $eventData[$i]['properties']['votes'] = $votes;
                                $eventData[$i]['properties']['visits'] = $visits;
                                $footer .= sprintf($karma_block, $myvote, $points, $votes, $visits, $url);
                            }
                            // foreach key in entries
                    }
                    // End switch on karma voting status
                    return true;
                    break;
                    // Display the Karma Log link on the sidebar
                // Display the Karma Log link on the sidebar
                case 'backend_sidebar_admin_appearance':
                    ?>
<li><a href="?serendipity[adminModule]=event_display&amp;serendipity[adminAction]=karmalog"><?php 
                    echo PLUGIN_KARMA_DISPLAY_LOG;
                    ?>
</a></li>
<?php 
                    return true;
                    break;
                    // Display the Karma Log!
                    //case 'external_plugin':
                // Display the Karma Log!
                //case 'external_plugin':
                case 'backend_sidebar_entries_event_display_karmalog':
                    // Print any stored messages
                    //foreach ($serendipity['karma_messages'] as $msg) {
                    //    print("<div class='serendipityAdminInfo'>$msg</div>\n");
                    //}
                    // Was I asked to process any votes?
                    if (($serendipity['POST']['delete_button'] || $serendipity['POST']['approve_button']) && sizeof($serendipity['POST']['delete']) != 0 && serendipity_checkFormToken()) {
                        foreach ($serendipity['POST']['delete'] as $d => $i) {
                            $kdata = $serendipity['POST']['karmalog' . $i];
                            // validate posted variables
                            // posted points
                            $ppoints = $kdata['points'];
                            if (!is_numeric($ppoints) || (int) $ppoints < -2 || (int) $ppoints > 2) {
                                print "<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_INVALID_INPUT . "</span>\n";
                                return false;
                            }
                            // posted id
                            $pid = $kdata['entryid'];
                            if (!is_numeric($pid)) {
                                print "<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_INVALID_INPUT . "</span>\n";
                                return false;
                            }
                            // posted IP
                            $pip = long2ip(ip2long($kdata['ip']));
                            if ($pip == -1 || $pip === FALSE) {
                                print "<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_INVALID_INPUT . "</span>\n";
                                return false;
                            }
                            // posted user agent (need a better validator, I think)
                            $puser_agent = $kdata['user_agent'];
                            if (serendipity_db_escape_string($puser_agent) != $puser_agent) {
                                print "<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_INVALID_INPUT . "</span>\n";
                                return false;
                            }
                            // posted vote time
                            $pvotetime = $kdata['votetime'];
                            $unixsecs = date('U', $kdata['votetime']);
                            if ($pvotetime != $unixsecs) {
                                print "<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_INVALID_INPUT . "</span>\n";
                                return false;
                            }
                            // Remove karma from entry?
                            if ($serendipity['POST']['delete_button']) {
                                // Fetch vote total for the entry IDs
                                $q = 'SELECT k.*
                                    FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
                                    WHERE k.entryid IN (' . $pid . ') GROUP BY k.entryid';
                                $sql = serendipity_db_query($q);
                                if (is_array($sql)) {
                                    $karma = $sql[0];
                                    $update = sprintf("UPDATE {$serendipity['dbPrefix']}karma\n                                        SET points   = %s,\n                                        votes    = %s\n                                        WHERE entryid  = %s", serendipity_db_escape_string($karma['points'] - $ppoints), serendipity_db_escape_string($karma['votes'] - 1), serendipity_db_escape_string($pid));
                                    $updated = serendipity_db_query($update);
                                    if ($updated != 1) {
                                        printf("<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_REMOVE_ERROR . "</span>\n", $pid);
                                        // Don't delete from karma log if we couldn't take away the points
                                        continue;
                                    }
                                } else {
                                    // This will only happen if someone is messing with the karma table or submit data
                                    printf("<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_UPDATE_ERROR . "</span>", $pid);
                                    continue;
                                }
                            }
                            // Remove vote from log (approved or deleted, doesn't matter)
                            $del = sprintf("DELETE FROM {$serendipity['dbPrefix']}karmalog\n                                WHERE entryid = %s AND ip = '%s' AND user_agent LIKE '%%%s%%' AND votetime = %s LIMIT 1", serendipity_db_escape_string($pid), serendipity_db_escape_string($pip), serendipity_db_escape_string($puser_agent), serendipity_db_escape_string($pvotetime));
                            $deleted = serendipity_db_query($del);
                            // User feedback
                            if ($deleted == 1) {
                                if ($serendipity['POST']['delete_button']) {
                                    printf("<span class='msg_success'><span class='icon-ok-circled'></span> " . PLUGIN_KARMA_REMOVED_POINTS . "</span>\n", $ppoints, $pid);
                                } else {
                                    printf("<span class='msg_success'><span class='icon-ok-circled'></span> " . PLUGIN_KARMA_APPROVED_POINTS . "</span>\n", $ppoints, $pid);
                                }
                            } else {
                                printf("<span class='msg_error'><span class='icon-attention-circled'></span> " . PLUGIN_KARMA_REMOVE_ERROR . "</span>\n", $pid);
                            }
                        }
                    }
                    // URL; expected to be event_display and karmalog, respectively
                    $url = '?serendipity[adminModule]=' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($serendipity['GET']['adminModule']) : htmlspecialchars($serendipity['GET']['adminModule'], ENT_COMPAT, LANG_CHARSET)) . '&serendipity[adminAction]=' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($serendipity['GET']['adminAction']) : htmlspecialchars($serendipity['GET']['adminAction'], ENT_COMPAT, LANG_CHARSET));
                    // Filters
                    print "\n<h2>" . PLUGIN_KARMA_DISPLAY_LOG . "</h2>\n<form id='karmafilters' name='karmafilters' action='' method='get'>\n    <input name='serendipity[adminModule]' type='hidden' value='{$serendipity['GET']['adminModule']}'>\n    <input name='serendipity[adminAction]' type='hidden' value='{$serendipity['GET']['adminAction']}'>\n\n    <ul class='filters_toolbar clearfix plainList'>\n        <li><a class='button_link' href='#serendipity_admin_filters' title='" . FILTERS . "'><span class='icon-filter'></span><span class='visuallyhidden'> " . FILTERS . "</span></a></li>\n        <li><a class='button_link' href='#serendipity_admin_sort' title='" . SORT_ORDER . "'><span class='icon-sort'></span><span class='visuallyhidden'> " . SORT_ORDER . "</span></a></li>\n    </ul>\n\n    <fieldset id='serendipity_admin_filters' class='additional_info filter_pane'>\n        <legend><span class='visuallyhidden'>" . FILTERS . "</span></legend>\n\n        <div class='clearfix'>\n            <div class='form_field'>\n                <label for='serendipity_filter_useragent'>User Agent</label>\n                <input id='serendipity_filter_useragent' name='serendipity[filter][user_agent]' type='text' value='" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($serendipity['GET']['filter']['user_agent']) : htmlspecialchars($serendipity['GET']['filter']['user_agent'], ENT_COMPAT, LANG_CHARSET)) . "'>\n            </div>\n\n            <div class='form_field'>\n                <label for='serendipity_filter_ip'>" . IP . "</label>\n                <input id='serendipity_filter_ip' name='serendipity[filter][ip]' type='text' value='" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($serendipity['GET']['filter']['ip']) : htmlspecialchars($serendipity['GET']['filter']['ip'], ENT_COMPAT, LANG_CHARSET)) . "'>\n            </div>\n\n            <div class='form_field'>\n                <label for='serendipity_filter_entryid'>Entry ID</label>\n                <input id='serendipity_filter_entryid' name='serendipity[filter][entryid]' type='text' value='" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($serendipity['GET']['filter']['entryid']) : htmlspecialchars($serendipity['GET']['filter']['entryid'], ENT_COMPAT, LANG_CHARSET)) . "'>\n            </div>\n\n            <div class='form_field'>\n                <label for='serendipity_filter_title'>Entry title</label>\n                <input id='serendipity_filter_title' name='serendipity[filter][title]' type='text' value='" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($serendipity['GET']['filter']['title']) : htmlspecialchars($serendipity['GET']['filter']['title'], ENT_COMPAT, LANG_CHARSET)) . "'>\n            </div>\n        </div>\n\n        <div class='form_buttons'>\n            <input name='submit' type='submit' value='" . GO . "'>\n        </div>\n    </fieldset>\n";
                    // Set all filters into $and and $searchString
                    if (!empty($serendipity['GET']['filter']['entryid'])) {
                        $val = $serendipity['GET']['filter']['entryid'];
                        $and .= "AND l.entryid = '" . serendipity_db_escape_string($val) . "'";
                        $searchString .= "&amp;serendipity['filter']['entryid']=" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($val) : htmlspecialchars($val, ENT_COMPAT, LANG_CHARSET));
                    }
                    if (!empty($serendipity['GET']['filter']['ip'])) {
                        $val = $serendipity['GET']['filter']['ip'];
                        $and .= "AND l.ip = '" . serendipity_db_escape_string($val) . "'";
                        $searchString .= "&amp;serendipity['filter']['ip']=" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($val) : htmlspecialchars($val, ENT_COMPAT, LANG_CHARSET));
                    }
                    if (!empty($serendipity['GET']['filter']['user_agent'])) {
                        $val = $serendipity['GET']['filter']['user_agent'];
                        $and .= "AND l.user_agent LIKE '%" . serendipity_db_escape_string($val) . "%'";
                        $searchString .= "&amp;serendipity['filter']['user_agent']=" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($val) : htmlspecialchars($val, ENT_COMPAT, LANG_CHARSET));
                    }
                    if (!empty($serendipity['GET']['filter']['title'])) {
                        $val = $serendipity['GET']['filter']['title'];
                        $and .= "AND e.title LIKE '%" . serendipity_db_escape_string($val) . "%'";
                        $searchString .= "&amp;serendipity['filter']['title']=" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($val) : htmlspecialchars($val, ENT_COMPAT, LANG_CHARSET));
                    }
                    // Sorting (controls go after filtering controls in form above)
                    $sort_order = array('votetime' => DATE, 'user_agent' => USER_AGENT, 'title' => TITLE, 'entryid' => 'ID');
                    if (empty($serendipity['GET']['sort']['ordermode']) || $serendipity['GET']['sort']['ordermode'] != 'ASC') {
                        $desc = true;
                        $serendipity['GET']['sort']['ordermode'] = 'DESC';
                    }
                    if (!empty($serendipity['GET']['sort']['order']) && !empty($sort_order[$serendipity['GET']['sort']['order']])) {
                        $curr_order = $serendipity['GET']['sort']['order'];
                        $orderby = serendipity_db_escape_string($curr_order . ' ' . $serendipity['GET']['sort']['ordermode']);
                    } else {
                        $curr_order = 'votetime';
                        $orderby = 'votetime ' . serendipity_db_escape_string($serendipity['GET']['sort']['ordermode']);
                    }
                    print "\n    <fieldset id='serendipity_admin_sort' class='additional_info filter_pane'>\n        <legend><span class='visuallyhidden'>" . SORT_ORDER . "</span></legend>\n\n        <div class='clearfix'>\n            <div class='form_select'>\n                <label for='serendipity_sort_order'>" . SORT_BY . "</label>\n                <select id='serendipity_sort_order' name='serendipity[sort][order]'>\n";
                    foreach ($sort_order as $order => $val) {
                        print "\n  <option value='{$order}'" . ($curr_order == $order ? " selected='selected'" : '') . ">{$val}</option>\n";
                    }
                    print "\n                </select>\n            </div>\n            <div class='form_select'>\n                <label for='serendipity_sort_ordermode'>" . SORT_ORDER . "</label>\n                <select id='serendipity_sort_ordermode' name='serendipity[sort][ordermode]'>\n                    <option value='DESC'" . ($desc ? " selected='selected'" : '') . ">" . SORT_ORDER_DESC . "</option>\n                    <option value='ASC'" . ($desc ? '' : " selected='selected'") . ">" . SORT_ORDER_ASC . "</option>\n                </select>\n            </div>\n        </div>\n\n        <div class='form_buttons'>\n            <input name='submit' type='submit' value='" . GO . "'>\n        </div>\n    </fieldset>\n</form>\n";
                    // Paging (partly ripped from include/admin/comments.inc.php)
                    $commentsPerPage = (int) (!empty($serendipity['GET']['filter']['perpage']) ? $serendipity['GET']['filter']['perpage'] : 25);
                    $sql = serendipity_db_query("SELECT COUNT(*) AS total FROM {$serendipity['dbPrefix']}karmalog l WHERE 1 = 1 " . $and, true);
                    if (is_string($sql)) {
                        print "<span class='msg_error'><span class='icon-attention-circled'></span> " . $sql . "</span>\n";
                    }
                    $totalVotes = is_array($sql) && is_int($sql['total']) ? $sql['total'] : 0;
                    $pages = $commentsPerPage == COMMENTS_FILTER_ALL ? 1 : ceil($totalVotes / (int) $commentsPerPage);
                    $page = (int) $serendipity['GET']['page'];
                    if ($page == 0 || $page > $pages) {
                        $page = 1;
                    }
                    if ($page > 1) {
                        $linkPrevious = $url . '&amp;serendipity[page]=' . ($page - 1) . $searchString;
                    }
                    if ($pages > $page) {
                        $linkNext = $url . '&amp;serendipity[page]=' . ($page + 1) . $searchString;
                    }
                    if ($commentsPerPage == COMMENTS_FILTER_ALL) {
                        $limit = '';
                    } else {
                        $limit = serendipity_db_limit_sql(serendipity_db_limit(($page - 1) * (int) $commentsPerPage, (int) $commentsPerPage));
                    }
                    // Variables for display
                    if ($linkPrevious) {
                        $linkPrevious = '<a class="button_link" href="' . $linkPrevious . '" title="' . PREVIOUS . '"><span class="icon-left-dir"></span><span class="visuallyhidden"> ' . PREVIOUS . '</span></a>';
                    } else {
                        $linkPrevious = '<span class="visuallyhidden">' . NO_ENTRIES_TO_PRINT . '</span>';
                    }
                    if ($linkNext) {
                        $linkNext = '<a class="button_link" href="' . $linkNext . '" title="' . NEXT . '"><span class="visuallyhidden">' . NEXT . ' </span><span class="icon-right-dir"></span></a>';
                    } else {
                        $linkNext = '<span class="visuallyhidden">' . NO_ENTRIES_TO_PRINT . '</span>';
                    }
                    $paging = sprintf(PAGE_BROWSE_COMMENTS, $page, $pages, $totalVotes);
                    // Retrieve the next batch of karma votes
                    // [entryid, points, ip, user_agent, votetime]
                    $sql = serendipity_db_query("SELECT l.entryid AS entryid, l.points AS points, l.ip AS ip, l.user_agent AS user_agent, l.votetime AS votetime, e.title AS title FROM {$serendipity['dbPrefix']}karmalog l\n                        LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = l.entryid)\n                        WHERE 1 = 1 " . $and . "\n                        ORDER BY {$orderby} {$limit}");
                    // Start the form for display and deleting
                    if (is_array($sql)) {
                        print "<form action='' method='post' name='formMultiDelete' id='formMultiDelete'>\n" . serendipity_setFormToken();
                        // Start the vote table
                        print "\n<div class='clearfix karma_pane'>\n<ul id='karmalog' class='clearfix karmalog plainList zebra_list'>\n";
                        // Print each vote
                        $i = 0;
                        foreach ($sql as $vote) {
                            $i++;
                            // entryid, title, points, ip, user_agent, votetime
                            if (strlen($vote['title']) > 40) {
                                $votetitle = substr($vote['title'], 0, 40) . '&hellip;';
                            } else {
                                $votetitle = $vote['title'];
                            }
                            $entrylink = serendipity_archiveURL($vote['entryid'], $vote['title'], 'serendipityHTTPPath', true);
                            $entryFilterHtml = "<a class='button_link filter_karma' href='{$url}&serendipity[filter][entryid]={$vote['entryid']}' title='" . FILTERS . "'><span class='icon-filter'></span><span class='visuallyhidden'>" . FILTERS . "</span></a>";
                            $ipFilterHtml = "<a class='button_link filter_karma' href='{$url}&serendipity[filter][ip]={$vote['ip']}' title='" . FILTERS . "'><span class='icon-filter'></span><span class='visuallyhidden'>" . FILTERS . "</span></a>";
                            $timestr = strftime('%a %b %d %Y, %H:%M:%S', $vote['votetime']);
                            $cssClass = $i % 2 == 0 ? 'even' : 'odd';
                            $barClass = str_replace(array('.', ' '), array('_', '_'), $this->image_name);
                            $barHtml = $this->createRatingBar(null, $vote['points'], 1, $barClass);
                            $barHtml = sprintf($barHtml, 'what', $vote['points'], '1');
                            print "\n    <li id='karma_{$i}' class='{$cssClass} clearfix'>\n        <input type='hidden' name='serendipity[karmalog{$i}][points]' value='{$vote['points']}'>\n        <input type='hidden' name='serendipity[karmalog{$i}][entryid]' value='{$vote['entryid']}'>\n        <input type='hidden' name='serendipity[karmalog{$i}][votetime]' value='{$vote['votetime']}'>\n        <input type='hidden' name='serendipity[karmalog{$i}][ip]' value='{$vote['ip']}'>\n        <input type='hidden' name='serendipity[karmalog{$i}][user_agent]' value='{$vote['user_agent']}'>\n\n        <div class='form_check'>\n            <input id='multidelete_karma_{$i}' class='multidelete' type='checkbox' name='serendipity[delete][{$i}]' value='{$i}' data-multidelid='karma_{$i}'>\n            <label for='multidelete_karma_{$i}' class='visuallyhidden'>" . TOGGLE_SELECT . "</label>\n        </div>\n\n        <h4><a href='{$entrylink}' title='ID: {$vote['entryid']}'>{$votetitle}</a>\n            <button class='toggle_info button_link' type='button' data-href='#karma_data_{$i}'><span class='icon-info-circled'></span><span class='visuallyhidden'> " . MORE . "</span></button>\n            {$entryFilterHtml}\n        </h4>\n\n        {$barHtml}\n\n        <div id='karma_data_{$i}' class='additional_info'>\n            <dl class='clearfix comment_data'>\n                <dt>" . ON . "</dt>\n                <dd>{$timestr}</dd>\n                <dt>IP</dt>\n                <dd>{$vote['ip']} {$ipFilterHtml}</dd>\n                <dt><abbr title='User-Agent' lang='en'>UA</abbr></dt>\n                <dd>{$vote['user_agent']}</dd>\n            </dl>\n        </div>\n    </li>\n";
                        }
                        // End the vote table
                        print "\n                            </ul>\n                            ";
                        // Print the footer paging table
                        print "\n<nav class='pagination'>\n    <h3>{$paging}</h3>\n    <ul class='clearfix'>\n        <li class='prev'>{$linkPrevious}</li>\n        <li class='next'>{$linkNext}</li>\n    </ul>\n</nav>\n</div>\n";
                        if (is_array($sql)) {
                            print "\n<div class='form_buttons'>\n<input class='invert_selection' name='toggle' type='button' value='" . INVERT_SELECTIONS . "'> \n<input class='state_cancel' name='serendipity[delete_button]' type='submit' title='" . PLUGIN_KARMA_DELETE_VOTES . "' value='" . DELETE . "'>\n</div>\n</form>\n";
                        }
                    } else {
                        print "\n<span class='msg_notice'><span class='icon-info-circled'></span> No logs to display. You need to enable karma logging, if you want to see single votes displayed here.</span>\n";
                    }
                    return true;
                    break;
                default:
                    return false;
            }
            // End switch on event hooks
        } else {
            return false;
        }
    }
/**
 * Display HTML output data of a Exit/Referrer list
 *
 * @access public
 * @see serendipity_displayTopExits()
 * @see serendipity_displayTopReferrers()
 * @param   string      Name of the DB table to show data from (exits|referrers)
 * @param  boolean  Whether to use HTML links for URLs
 * @param  int      Interval for which the top exits are aggregated
 * @return
 */
function serendipity_displayTopUrlList($list, $limit, $use_links = true, $interval = 7)
{
    global $serendipity;
    if ($limit) {
        $limit = serendipity_db_limit_sql($limit);
    }
    /* HACK */
    if (preg_match('/^mysqli?/', $serendipity['dbType'])) {
        /* Nonportable SQL due to MySQL date functions,
         * but produces rolling 7 day totals, which is more
         * interesting
         */
        $query = "SELECT scheme, host, SUM(count) AS total\n                  FROM {$serendipity['dbPrefix']}{$list}\n                  WHERE day > date_sub(current_date, interval " . (int) $interval . " day)\n                  GROUP BY host\n                  ORDER BY total DESC, host\n                  {$limit}";
    } else {
        /* Portable version of the same query */
        $query = "SELECT scheme, host, SUM(count) AS total\n                  FROM {$serendipity['dbPrefix']}{$list}\n                  GROUP BY scheme, host\n                  ORDER BY total DESC, host\n                  {$limit}";
    }
    $rows = serendipity_db_query($query);
    echo "<span class='serendipityReferer'>";
    if (is_array($rows)) {
        foreach ($rows as $row) {
            if ($use_links) {
                printf('<a href="%1$s://%2$s" title="%2$s" >%2$s</a> (%3$s)<br />', htmlspecialchars($row['scheme']), htmlspecialchars($row['host']), htmlspecialchars($row['total']));
            } else {
                printf('%1$s (%2$s)<br />', htmlspecialchars($row['host']), htmlspecialchars($row['total']));
            }
        }
    }
    echo "</span>";
}
    function event_hook($event, &$bag, &$eventData, $addData = null)
    {
        global $serendipity;
        $hooks =& $bag->get('event_hooks');
        if (isset($hooks[$event])) {
            // Moved from above: only get image data if we're actually going to do something
            $this->set_valid_image_data();
            // Get dimensions of image, only if not text-only
            if ($this->image_name) {
                // Is this a single-image bar, or a single segment?
                $ratio = $this->image_width / $this->image_height;
                if ($ratio < $max_segment_ratio) {
                    // This is probably a single segment. Square segments
                    // will have a ratio of 0.3; long, flat segments won't
                    // get up to 1.0 unless they're 3 times as wide as they
                    // are tall; full-bar images with square segments will
                    // be 1.666; and full-bar images with tall, narrow
                    // segments will be greater than 1.0 unless they're
                    // nearly twice as high as they are wide.
                    $this->image_width = $this->image_width * 5;
                }
            }
            switch ($event) {
                // Early hook, before any page is displayed
                case 'frontend_configure':
                    // Make sure the karmaVote cookie is set, even if empty <a name="#1" />
                    if (!isset($serendipity['COOKIE']['karmaVote'])) {
                        serendipity_setCookie('karmaVote', serialize(array()));
                    }
                    // If user didn't vote, we're done.
                    if (!isset($serendipity['GET']['karmaId']) || !isset($serendipity['GET']['karmaVote'])) {
                        return;
                    }
                    // Get URL vote data
                    $this->karmaId = (int) $serendipity['GET']['karmaId'];
                    $this->karmaVoting = (int) $serendipity['GET']['karmaVote'];
                    // karmaVote cookie was just set (see name="#1"); this boils down to
                    // "if check cookie isn't 1, there's no real cookie".
                    // The check cookie gets set when a rater is displayed,
                    // so you've got no business voting if you haven't even
                    // seen the rater yet.
                    if (!isset($serendipity['COOKIE']['karmaVote']) or $serendipity['COOKIE']['check'] != '1') {
                        $this->karmaVote = 'nocookie';
                        return;
                    }
                    // Everything is ready.  Get the cookie vote data.
                    $karma = unserialize($serendipity['COOKIE']['karmaVote']);
                    // Stop on invalid votes (cookie invalid, or URL data incorrect)
                    if (!is_array($karma) || !is_numeric($this->karmaVoting) || !is_numeric($this->karmaId) || $this->karmaVoting > 2 || $this->karmaVoting < -2) {
                        $this->karmaVote = 'invalid1';
                        return;
                    }
                    // Stop if the cookie says we already voted
                    if (!empty($karma[$this->karmaId])) {
                        $this->karmaVote = 'alreadyvoted';
                        return;
                    }
                    // We don't want bots hitting the karma-voting
                    $agent = $_SERVER['HTTP_USER_AGENT'];
                    if (stristr($agent, 'google') || stristr($agent, 'LinkWalker') || stristr($agent, 'zermelo') || stristr($agent, 'NimbleCrawler')) {
                        $this->karmaVote = 'invalid1';
                        return;
                    }
                    // Voting takes place here.
                    //
                    // Get voting data from the database (keeps all entries,
                    // even if no karma match)
                    $q = 'SELECT *
                            FROM ' . $serendipity['dbPrefix'] . 'entries AS e
                 LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'karma   AS k
                              ON e.id = k.entryid
                           WHERE e.id = ' . serendipity_db_escape_string($this->karmaId) . ' LIMIT 1';
                    $row = serendipity_db_query($q, true);
                    // If there's no entry with this ID, we're done
                    //
                    // --TODO: Modify the plugin to allow arbitrary voting with generated IDs
                    if (!isset($row) || !is_array($row)) {
                        $this->karmaVote = 'invalid2';
                        return;
                    }
                    $now = time();
                    if ($row['votes'] === '0' || $row['votes'] > 0) {
                        // Votes for this entry already exist. Do some checking.
                        $max_entrytime = $this->get_config('max_entrytime', 1440) * 60;
                        $max_votetime = $this->get_config('max_votetime', 5) * 60;
                        $max_karmatime = $this->get_config('max_karmatime', 7) * 24 * 60 * 60;
                        // Allow infinite voting when 0 or negative
                        if ($max_karmatime <= 0) {
                            $max_karmatime = $now;
                        }
                        // If the entry's timestamp is too old for voting,
                        // we're done.
                        if ($row['timestamp'] < $now - $max_karmatime) {
                            $this->karmaVote = 'timeout2';
                            return;
                        }
                        // If the entry is in the grace period, or votes
                        // aren't too close together, record the vote.
                        if ($row['timestamp'] > $now - $max_entrytime || $row['lastvote'] + $max_votetime < $now || $row['lastvote'] == 0) {
                            // Update votes
                            $q = sprintf("UPDATE {$serendipity['dbPrefix']}karma\n                                  SET points   = %s,\n                                      votes    = %s,\n                                      lastvote = %s\n                                WHERE entryid  = %s", $row['points'] + $this->karmaVoting, $row['votes'] + 1, $now, $this->karmaId);
                            serendipity_db_query($q);
                        } else {
                            // Entry was too recently voted upon.  Figure out
                            // how long until voting will be allowed (in minutes).
                            $this->karmaVote = 'timeout';
                            $this->karmaTimeOut = abs(ceil(($now - ($row['lastvote'] + $max_votetime)) / 60));
                            return;
                        }
                    } else {
                        // No row. Use INSERT instead of UPDATE.
                        $q = sprintf("INSERT INTO {$serendipity['dbPrefix']}karma\n                                       (entryid, points, votes, lastvote, visits)\n                                VALUES (%s,      %s,     %s,    %s,       %s)", $this->karmaId, $this->karmaVoting, 1, $now, 0);
                        $sql = serendipity_db_query($q);
                    }
                    // Log the vote
                    if (serendipity_db_bool($this->get_config('logging', false))) {
                        $q = sprintf("INSERT INTO {$serendipity['dbPrefix']}karmalog\n                                       (entryid, points, ip, user_agent, votetime)\n                                VALUES (%s, %s, '%s', '%s', %s)", $this->karmaId, $this->karmaVoting, serendipity_db_escape_string($_SERVER['REMOTE_ADDR']), substr(serendipity_db_escape_string($_SERVER['HTTP_USER_AGENT']), 0, 255), $now);
                        $sql = serendipity_db_query($q);
                        if (is_string($sql)) {
                            mail($serendipity['serendipityEmail'], 'KARMA ERROR', $q . '<br />' . $sql . '<br />');
                        }
                    }
                    // Set the cookie that we already voted for this entry
                    $karma[$this->karmaId] = $this->karmaVoting;
                    $this->karmaVote = 'voted';
                    serendipity_setCookie('karmaVote', serialize($karma));
                    return true;
                    break;
                    // CSS generation hooks
                // CSS generation hooks
                case 'backend_header':
                    // Generate the CSS for the graphical rating bar selector
                    //
                    // The CSS appears to be generated in a completely
                    // different instance of Serendipity, as if index.php gets
                    // called separately for the CSS.
                    //
                    // Note that the css_backend hook adds properties to the
                    // serendipity_admin.css, but that file is *always*
                    // cached.  We use backend_header and add the CSS to the
                    // HEAD styles to make it dynamic.
                    // Get the CSS, set $this->image_name so we'll output the
                    // standard graphical CSS prologue if any images are found.
                    $this->createRatingSelector();
                    print "<style type='text/css'>\n";
                    $align = 'center';
                    $bg = $this->get_config('preview_bg', false);
                    if (!empty($bg)) {
                        if (strpos($bg, ';') !== false || strpos($bg, ',') !== false) {
                            $bg = 'red';
                        }
                        print "\n.serendipity_karmaVote_selectorTable {\n    background: {$bg};\n}\n";
                    }
                    print "\n.serendipityAdminContent .serendipity_karmaVoting_links {\n    margin: 5px;\n}\n";
                case 'css':
                    // Some CSS notes:
                    //
                    // .serendipity_karmaVoting is the class for the karma wrapper/container,
                    //      including the text explanations, messages, and rating bar.
                    //      (currently a div)
                    // .serendipity_karmaVoting a specifies the links for the text-mode
                    //      rating bar
                    // .serendipity_karmaError is the class for any text indicating an
                    //      error condition
                    // .serendipity_karmaSuccess is the class for any text indicating
                    //      successful operation
                    // .serendipity_karmaVoting_links is the container for the graphical
                    //      rating bar (currently an ol)
                    // .serendipity_karmaVoting_links a indicates the various voting links in
                    //      the graphical rating bar
                    // .serendipity_karmaVoting_current-rating is the class for the current
                    //      rating in the graphical rating bar
                    //  a.serendipity_karmaVoting_link1, _link2, etc are the classes applied
                    //      to the individual voting links
                    // Note that there are two possible template types: early
                    // templates that only handle the text rating bars, and
                    // newer templates that understand the graphical raters.
                    // We check for both types and act appropriately.
                    /*--JAM: Let's just skip this whole hassle
                      if (!$align) {
                          $align = $this->get_config('alignment', 'detect');
                      }
                      if ($align == 'detect') {
                      */
                    $align = $this->get_config('alignment', 'center');
                    // Try to let the template take care of it
                    if ($this->image_name == '0') {
                        // Text-only rating bar is used
                        if (strpos($eventData, '.serendipity_karmaVoting')) {
                            // Template is handling all our CSS
                            return true;
                        }
                    }
                    /* --JAM: else {
                               // Graphical rating bar is used
                               if (strpos($eventData, '.serendipity_karmaVoting_images')) {
                                   // Template is handling all our CSS
                                   return true;
                               }
                               // Check for old text-only templates
                               $pos = strpos($eventData, '.serendipity_karmaVoting');
                               while ($pos && ($align == 'detect')) {
                                   // Find text-align: in the current block
                                   $endpos = strpos($eventData, '}', $pos);
                                   if (!$endpos) {
                                       // Broken CSS
                                       break;
                                   }
                                   $alignpos = strpos($eventData, 'text-align:', $pos);
                                   // Can't check for comments, or I would.  Hope
                                   // the first is the correct one.
                                   if ($alignpos && $alignpos < $endpos) {
                                       $start = $alignpos + 11;
                                       $alignend = strpos($eventData, ';', $alignpos);
                                       if ($alignend)
                                       {
                                           // All valid.  Pull out the alignment.
                                           $len = $alignend - $start;
                                           $align = trim(substr($eventData, $start, $len));
                                       }
                                   }
                                   $pos = strpos($eventData, '.serendipity_karmaVoting', $endpos);
                               }
                               // I should have a valid alignment or 'detect' in $align now. 
                           }
                       }
                       // If we couldn't detect the alignment, guess 'right'
                       if ($align == 'detect') {
                           $align = 'right';
                       }
                       --JAM: END COMMENT BLOCK */
                    // Since errors might be printed at any time, always
                    // output the text-mode CSS
                    print <<<EOS
.serendipity_karmaVoting {
    text-align: {$align};
    font-size: 7pt;
    margin: 0px;
}

.serendipity_karmaVoting a {
    font-size: 7pt;
    text-decoration: none;
}

.serendipity_karmaVoting a:hover {
    color: green;
}

.serendipity_karmaError {
    color: #FF8000;
}
.serendipity_karmaSuccess {
    color: green;
}
EOS;
                    // Only output the image CSS if it's needed
                    if ($this->image_name != '0') {
                        $img = $serendipity['baseURL'] . "plugins/serendipity_event_karma/img/" . $this->image_name;
                        $h = $this->image_height / 3;
                        $w = $this->image_width;
                        switch ($align) {
                            case 'left':
                                $margin = '0px auto 0px 0px';
                                break;
                            case 'center':
                                $margin = '0px auto';
                                break;
                            case 'right':
                            default:
                                $margin = '0px 0px 0px auto';
                                break;
                        }
                        // The CSS here is lifted largely from
                        // http://komodomedia.com/blog/index.php/2007/01/20/css-star-rating-redux/
                        //
                        // Note, however that margin has been changed for
                        // multiple cases and all unitless measurements have
                        // been specified in pixels.  Additionally, measures
                        // have been taken to align the text.
                        print <<<END_IMG_CSS

.serendipity_karmaVoting_links,
.serendipity_karmaVoting_links a:hover,
.serendipity_karmaVoting_current-rating {
    background: url({$img}) left;
    font-size: 0;
}
.serendipity_karmaVoting_links {
    position: relative;
    width: {$w}px;
    height: {$h}px;
    overflow: hidden;
    list-style: none;
    margin: {$margin};
    padding: 0px;
    background-position: left top;     
    text-align: center;
}
.serendipity_karmaVoting_links li {
   display: inline; 
}
.serendipity_karmaVoting_links a ,
.serendipity_karmaVoting_current-rating {
    position:absolute;
    top: 0px;
    left: 0px;
    text-indent: -9000em;
    height: {$h}px;
    line-height: {$h}px;
    outline: none;
    overflow: hidden;
    border: none;
}
.serendipity_karmaVoting_links a:hover {
    background-position: left bottom;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link1 {
    width: 20%;
    z-index: 6;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link2 {
    width: 40%;
    z-index: 5;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link3 {
    width: 60%;
    z-index: 4;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link4 {
    width: 80%;
    z-index: 3;
}
.serendipity_karmaVoting_links a.serendipity_karmaVoting_link5 {
  width: 100%;
    z-index: 2;
}
.serendipity_karmaVoting_links .serendipity_karmaVoting_current-rating {
    z-index: 1;
    background-position: left center;
}

END_IMG_CSS;
                        // Add selector images CSS, if necessary
                        if (!empty($this->select_css)) {
                            print $this->select_css;
                        }
                    }
                    // End if image bar defined
                    if ($event == 'backend_header') {
                        print "\n</style>\n";
                    }
                    return true;
                    break;
                    //--TODO: Comment the functionality of this event hook.
                //--TODO: Comment the functionality of this event hook.
                case 'event_additional_statistics':
                    $sql = array();
                    $sql['visits_top'] = array('visits', 'DESC');
                    $sql['visits_bottom'] = array('visits', 'ASC');
                    $sql['votes_top'] = array('votes', 'DESC');
                    $sql['votes_bottom'] = array('votes', 'ASC');
                    $sql['points_top'] = array('points', 'DESC');
                    $sql['points_bottom'] = array('points', 'ASC');
                    foreach ($sql as $key => $rows) {
                        $q = "SELECT e.id,\n                                     e.title,\n                                     e.timestamp,\n                                     SUM(k.{$rows[0]}) AS no\n                                FROM {$serendipity['dbPrefix']}karma\n                                     AS k\n                                JOIN {$serendipity['dbPrefix']}entries\n                                     AS e\n                                  ON k.entryid = e.id\n                            WHERE k.{$rows[0]} IS NOT NULL AND k.{$rows[0]} != 0\n                            GROUP BY e.id, e.title, e.timestamp ORDER BY no {$rows[1]} LIMIT {$addData['maxitems']}";
                        $sql_rows = serendipity_db_query($q);
                        ?>
    <dt><strong><?php 
                        echo constant('PLUGIN_KARMA_STATISTICS_' . strtoupper($key));
                        ?>
</strong></dt>
    <dl>
<?php 
                        if (is_array($sql_rows)) {
                            foreach ($sql_rows as $id => $row) {
                                ?>
        <dt><strong><a href="<?php 
                                echo serendipity_archiveURL($row['id'], $row['title'], 'serendipityHTTPPath', true, array('timestamp' => $row['timestamp']));
                                ?>
"><?php 
                                echo htmlspecialchars($row['title']);
                                ?>
</a></strong></dt>
        <dd><?php 
                                echo $row['no'];
                                ?>
 <?php 
                                echo constant('PLUGIN_KARMA_STATISTICS_' . strtoupper($rows[0]) . '_NO');
                                ?>
</dd>
    <?php 
                            }
                        }
                        ?>
    </dl>
<?php 
                    }
                    return true;
                    break;
                    // Add voting information to entries
                // Add voting information to entries
                case 'entry_display':
                    // Update database if necessary
                    if ($this->get_config('dbversion', 0) != PLUGIN_KARMA_DB_VERSION) {
                        $this->checkScheme();
                    }
                    // Find the ID of this entry
                    if (isset($serendipity['GET']['id'])) {
                        $entryid = (int) serendipity_db_escape_string($serendipity['GET']['id']);
                    } elseif (preg_match(PAT_COMMENTSUB, $_SERVER['REQUEST_URI'], $matches)) {
                        $entryid = (int) $matches[1];
                    } else {
                        $entryid = false;
                    }
                    // If we're actually reading the entry, not voting or editing it...
                    if ($entryid && empty($serendipity['GET']['adminAction']) && !$serendipity['GET']['karmaVote']) {
                        // Update the number of visits
                        // Are we supposed to track visits?
                        $track_clicks = serendipity_db_bool($this->get_config('visits_active', true)) && $this->track_clicks_allowed_by_user();
                        if ($track_clicks && $_SERVER['REQUEST_METHOD'] == 'GET') {
                            $sql = serendipity_db_query("UPDATE {$serendipity['dbPrefix']}karma \n                                    SET visits = visits + 1 \n                                  WHERE entryid = {$entryid}", true);
                            if (serendipity_db_affected_rows() < 1) {
                                serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}karma (entryid, points, votes, lastvote, visits) \n                                              VALUES ('{$entryid}', 0, 0, 0, 1)");
                            }
                        }
                    }
                    // Set a cookie to look for later, verifying that cookies are enabled
                    serendipity_setCookie('check', '1');
                    switch ($this->karmaVote) {
                        case 'nocookie':
                            // Users with no cookies won't be able to vote.
                            $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_NOCOOKIE . '</div>';
                            // Continue until output
                        // Continue until output
                        case 'timeout2':
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_CLOSED . '</div>';
                            }
                            // Continue until output
                        // Continue until output
                        case 'timeout':
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . sprintf(PLUGIN_KARMA_TIMEOUT, $this->karmaTimeOut) . '</div>';
                            }
                            // Continue until output
                        // Continue until output
                        case 'alreadyvoted':
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_ALREADYVOTED . '</div>';
                            }
                            // Continue until output
                        // Continue until output
                        case 'invalid1':
                        case 'invalid2':
                        case 'invalid':
                            // Set message
                            if (!isset($msg)) {
                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_INVALID . '</div>';
                            }
                            // Continue until output
                            /* OUTPUT MESSAGE */
                            //--TODO: Shouldn't this work with the cache plugin, too?
                            if ($addData['extended']) {
                                $eventData[0]['exflag'] = 1;
                                $eventData[0]['add_footer'] .= $msg;
                            } else {
                                $elements = count($eventData);
                                // Find the right container to store our message in.
                                for ($i = 0; $i < $elements; $i++) {
                                    if ($eventData[$i]['id'] == $this->karmaId) {
                                        $eventData[$i]['add_footer'] .= $msg;
                                    }
                                }
                            }
                            break;
                        case 'voted':
                        default:
                            // If there's no data, there's no need to go on
                            if (!is_array($eventData)) {
                                return;
                            }
                            // Find out what the admin wants
                            $track_clicks = serendipity_db_bool($this->get_config('visits_active', true));
                            $track_karma = serendipity_db_bool($this->get_config('karma_active', true));
                            if (serendipity_db_bool($this->get_config('karma_active_registered', false))) {
                                if (!serendipity_userLoggedIn()) {
                                    $track_karma = false;
                                }
                            }
                            $track_exits = serendipity_db_bool($this->get_config('exits_active', true));
                            // Get the limits
                            $now = time();
                            $karmatime = $this->get_config('max_karmatime', 7);
                            $max_karmatime = $karmatime * 24 * 60 * 60;
                            // Accept infinite voting
                            if ($max_karmatime <= 0) {
                                $max_karmatime = $now;
                            }
                            //--TODO: Ensure that this works with the Custom Permalinks plugin
                            // (We've seen trouble; it votes correctly, but redirects to the front page)
                            $url = serendipity_currentURL(true);
                            // Voting is only allowed on entries.  Therefore voting URLs must be
                            // either single-entry URLs or summary URLs.  serendipity_currentURL
                            // converts them to an "ErrorDocument-URI", so we can focus on the
                            // query portion of the URI.
                            //
                            // Single-entry URLs should be well-defined.  They can be permalinks,
                            // of course; otherwise they're of the configured pattern.
                            //
                            // Summary URLs could be a little harder.  The summary pages that
                            // include entries are: frontpage, category, author, and archives.
                            // It's possible a plugin would show entries, but if that's the case
                            // we don't need to allow the user to vote on them.  Still, that's
                            // a lot of URLs to check for.
                            //
                            // Then there's the problem of the rest of the query.  It could
                            // include stuff we really want to keep around, like template
                            // overrides or something.  One can even add serendipity variables
                            // to the URL in extreme cases.
                            //
                            // It seems that canonicalizing the URL will be quite difficult.
                            // The only thing we can say for certain is that whatever the
                            // current URL is, it got us to this page, and we'd like to return
                            // to this page after we cast our vote.
                            // Remove any clutter from our previous voting activity
                            $url_parts = parse_url(serendipity_currentURL(true));
                            if (!empty($url_parts['query'])) {
                                $exclude = array('serendipity[karmaVote]', 'serendipity[karmaId]');
                                // I tried using parse_str, but it gave me very weird results
                                // with embedded arrays
                                //parse_str($url_parts['query'], $q_parts);
                                $q_parts = array();
                                // I don't know why this URL has been HTML encoded.  Oh well.
                                $pairs = explode('&amp;', $url_parts['query']);
                                foreach ($pairs as $pair) {
                                    $parts = explode('=', $pair);
                                    $q_parts[$parts[0]] = $parts[1];
                                }
                                foreach ($q_parts as $key => $value) {
                                    if (in_array($key, $exclude)) {
                                        $rm = preg_quote("{$key}={$value}");
                                        $url = preg_replace("@(&amp;|&)?{$rm}@", '', $url);
                                    }
                                }
                            }
                            if (substr($url, -1) != '?') {
                                $url .= '&amp;';
                            }
                            // Get the cookie data (past votes, etc)
                            $karma = isset($serendipity['COOKIE']['karmaVote']) ? unserialize($serendipity['COOKIE']['karmaVote']) : array();
                            // Get all required entry IDs, making keys match keys in eventData
                            $entries = array();
                            if ($addData['extended'] || $addData['preview']) {
                                // We're in extended or preview mode, we only need the current ID
                                $eventData[0]['exflag'] = 1;
                                $entries[0] = (int) $eventData[0]['id'];
                            } elseif (!serendipity_db_bool($this->get_config('extended_only', false))) {
                                // We're in overview mode, and we want rating bars for all the entry IDs
                                foreach (array_keys($eventData) as $key) {
                                    if (isset($eventData[$key]['id'])) {
                                        $entries[$key] = (int) $eventData[$key]['id'];
                                    }
                                }
                            }
                            // Fetch votes for all entry IDs. Store them in an array for later usage.
                            $q = 'SELECT k.entryid, SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits
                                    FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
                                   WHERE k.entryid IN (' . implode(', ', $entries) . ') GROUP BY k.entryid';
                            $sql = serendipity_db_query($q);
                            $rows = array();
                            if ($sql && is_array($sql)) {
                                foreach ($sql as $row) {
                                    $rows[$row['entryid']] = array('votes' => $row['votes'], 'points' => $row['points'], 'visits' => $row['visits']);
                                }
                            }
                            $this->prepareExits($entries);
                            // Add karma block to the footer of each entry
                            //
                            // The entries array was populated, above, so its keys match the eventData array,
                            // and overview entries are skipped if "extended only" is enabled
                            foreach (array_keys($entries) as $i) {
                                // Get the statistics
                                $entryid = $eventData[$i]['id'];
                                $votes = !empty($rows[$entryid]['votes']) ? $rows[$entryid]['votes'] : 0;
                                $points = !empty($rows[$entryid]['points']) ? $rows[$entryid]['points'] : 0;
                                $visits = !empty($rows[$entryid]['visits']) ? $rows[$entryid]['visits'] : 0;
                                $enough_votes = $track_karma && $votes >= $this->get_config('min_disp_votes', 0);
                                $enough_visits = $track_clicks && $visits >= $this->get_config('min_disp_visits', 0);
                                $textual_msg = true;
                                $textual_current = true;
                                $textual_visits = true;
                                if ($this->image_name != '0') {
                                    $textual_msg = $this->get_config('textual_msg', 'true');
                                    $textual_current = $this->get_config('textual_current', 'true');
                                    $textual_visits = $this->get_config('textual_visits', 'true');
                                }
                                // Where's the footer?  Normally it would be
                                // in eventData[n]['add_footer'] but if the
                                // cache plugin is used, it's in
                                // eventData[n]['properties']['ep_cache_add_footer'].
                                // This method retrieves it either way.
                                $footer =& $this->getFieldReference('add_footer', $eventData[$i]);
                                // Depending on what existed, $footer could
                                // be referencing the cached version, the
                                // uncached version, or even a new empty
                                // string.  In particular, if $eventData[$i]
                                // has no properties, and no 'add_footer' key,
                                // $footer is referencing a new empty string,
                                // so adding a karma bar to $footer would do
                                // nothing.
                                //
                                // We could be referencing an empty uncached
                                // 'add_footer', but empty cache entries are
                                // never returned.
                                //
                                // Reference a footer that will be printed
                                if (empty($footer) && !isset($eventData[$i]['add_footer']) && is_array($eventData[$i])) {
                                    $eventData[$i]['add_footer'] = '';
                                    $footer =& $eventData[$i]['add_footer'];
                                    // It's still empty, but it's referencing
                                    // the right place.
                                }
                                if ($track_exits) {
                                    $footer .= $this->getExits($entryid, true);
                                }
                                // Pick the appropriate intro msg and rating bar
                                // No msg or bar if karma is disabled
                                if ($track_karma) {
                                    if (isset($karma[$entryid])) {
                                        // We already voted for this one
                                        $msg = '<div class="serendipity_karmaSuccess">' . PLUGIN_KARMA_VOTED . '</div>';
                                        $myvote = $karma[$entryid];
                                        if ($this->get_config('rate_with_words', false)) {
                                            $myvote = $this->wordRating($myvote, 1);
                                        } elseif ($this->image_name != '0') {
                                            $myvote = $this->imageRating($myvote, 1);
                                        }
                                        // Just a current rating bar, if any
                                        $bar = $this->createRatingBar(null, $points, $votes);
                                    } elseif ($eventData[$i]['timestamp'] < $now - $max_karmatime) {
                                        // Too late to vote for this one
                                        $msg = '<div class="serendipity_karmaClosed">' . sprintf(PLUGIN_KARMA_CLOSED, $karmatime) . '</div>';
                                        // Just a current rating bar, if any
                                        $bar = $this->createRatingBar(null, $points, $votes);
                                    } else {
                                        // We can vote for this; make the whole voting block
                                        $rate_msg = $this->get_config('rate_msg', PLUGIN_KARMA_VOTETEXT);
                                        $msg = '<div class="serendipity_karmaVoting_text">' . $rate_msg . '</div>';
                                        // Full voting bar
                                        $bar = $this->createRatingBar($entryid, $points, $votes);
                                    }
                                }
                                // Create the karma block
                                $image_class = '';
                                if ($this->image_name != '0') {
                                    $image_class = ' serendipity_karmaVoting_images';
                                }
                                $karma_block = "<div class='serendipity_karmaVoting{$image_class}'><a id='karma_vote{$entryid}'></a>";
                                if ($textual_msg) {
                                    $karma_block .= $msg;
                                }
                                $karma_block .= $bar;
                                if ($enough_votes && $textual_current) {
                                    $curr_msg = $this->get_config('curr_msg', PLUGIN_KARMA_CURRENT);
                                    $karma_block .= '<span class="serendipity_karmaVoting_current">' . $curr_msg . '</span>';
                                }
                                if ($enough_visits && $textual_visits) {
                                    $karma_block .= '<span class="serendipity_karmaVoting_visits">' . PLUGIN_KARMA_VISITSCOUNT . '</span>';
                                }
                                $karma_block .= "\n</div>\n";
                                // Adjust rating points
                                if ($this->get_config('rate_with_words', false)) {
                                    $points = $this->wordRating($points, $votes);
                                } elseif ($this->image_name != '0') {
                                    $points = $this->imageRating($points, $votes);
                                }
                                /*
                                  print("<h3>--DEBUG: Karma block code:</h3>\n<pre>\n");
                                  print_r(htmlspecialchars($karma_block));
                                  print("\n</pre>\n");
                                */
                                // Substitute the % stuff and add it to the footer
                                $eventData[$i]['properties']['myvote'] = $myvote;
                                $eventData[$i]['properties']['points'] = $points;
                                $eventData[$i]['properties']['votes'] = $votes;
                                $eventData[$i]['properties']['visits'] = $visits;
                                $footer .= sprintf($karma_block, $myvote, $points, $votes, $visits, $url);
                            }
                            // foreach key in entries
                    }
                    // End switch on karma voting status
                    return true;
                    break;
                    // Display the Karma Log link on the sidebar
                // Display the Karma Log link on the sidebar
                case 'backend_sidebar_entries':
                    ?>
<li class="serendipitySideBarMenuLink serendipitySideBarMenuEntryLinks">
    <a href="?serendipity[adminModule]=event_display&amp;serendipity[adminAction]=karmalog">
        <?php 
                    echo PLUGIN_KARMA_DISPLAY_LOG;
                    ?>
    </a>
</li>
<?php 
                    return true;
                    break;
                    // Display the Karma Log!
                    //case 'external_plugin':
                // Display the Karma Log!
                //case 'external_plugin':
                case 'backend_sidebar_entries_event_display_karmalog':
                    // Print any stored messages
                    //foreach ($serendipity['karma_messages'] as $msg) {
                    //    print("<div class='serendipityAdminInfo'>$msg</div>\n");
                    //}
                    // Was I asked to process any votes?
                    if (($serendipity['POST']['delete_button'] || $serendipity['POST']['approve_button']) && sizeof($serendipity['POST']['delete']) != 0 && serendipity_checkFormToken()) {
                        foreach ($serendipity['POST']['delete'] as $d => $i) {
                            $kdata = $serendipity['POST']['karmalog' . $i];
                            // validate posted variables
                            // posted points
                            $ppoints = $kdata['points'];
                            if (!is_numeric($ppoints) || (int) $ppoints < -2 || (int) $ppoints > 2) {
                                print "<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_INVALID_INPUT . "</div>\n";
                                return false;
                            }
                            // posted id
                            $pid = $kdata['entryid'];
                            if (!is_numeric($pid)) {
                                print "<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_INVALID_INPUT . "</div>\n";
                                return false;
                            }
                            // posted IP
                            $pip = long2ip(ip2long($kdata['ip']));
                            if ($pip == -1 || $pip === FALSE) {
                                print "<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_INVALID_INPUT . "</div>\n";
                                return false;
                            }
                            // posted user agent (need a better validator, I think)
                            $puser_agent = $kdata['user_agent'];
                            if (serendipity_db_escape_string($puser_agent) != $puser_agent) {
                                print "<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_INVALID_INPUT . "</div>\n";
                                return false;
                            }
                            // posted vote time
                            $pvotetime = $kdata['votetime'];
                            $unixsecs = date('U', $kdata['votetime']);
                            if ($pvotetime != $unixsecs) {
                                print "<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_INVALID_INPUT . "</div>\n";
                                return false;
                            }
                            // Remove karma from entry?
                            if ($serendipity['POST']['delete_button']) {
                                // Fetch vote total for the entry IDs
                                $q = 'SELECT k.*
                                    FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
                                    WHERE k.entryid IN (' . $pid . ') GROUP BY k.entryid';
                                $sql = serendipity_db_query($q);
                                if (is_array($sql)) {
                                    $karma = $sql[0];
                                    $update = sprintf("UPDATE {$serendipity['dbPrefix']}karma\n                                        SET points   = %s,\n                                        votes    = %s\n                                        WHERE entryid  = %s", serendipity_db_escape_string($karma['points'] - $ppoints), serendipity_db_escape_string($karma['votes'] - 1), serendipity_db_escape_string($pid));
                                    $updated = serendipity_db_query($update);
                                    if ($updated != 1) {
                                        printf("<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_REMOVE_ERROR . "</div>\n", $pid);
                                        // Don't delete from karma log if we couldn't take away the points
                                        continue;
                                    }
                                } else {
                                    // This will only happen if someone is messing with the karma table or submit data
                                    printf("<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_UPDATE_ERROR . "</div>", $pid);
                                    continue;
                                }
                            }
                            // Remove vote from log (approved or deleted, doesn't matter)
                            $del = sprintf("DELETE FROM {$serendipity['dbPrefix']}karmalog\n                                WHERE entryid = %s AND ip = '%s' AND user_agent LIKE '%%%s%%' AND votetime = %s LIMIT 1", serendipity_db_escape_string($pid), serendipity_db_escape_string($pip), serendipity_db_escape_string($puser_agent), serendipity_db_escape_string($pvotetime));
                            $deleted = serendipity_db_query($del);
                            // User feedback
                            if ($deleted == 1) {
                                if ($serendipity['POST']['delete_button']) {
                                    printf("<div class='serendipityAdminMsgSuccess'>" . PLUGIN_KARMA_REMOVED_POINTS . "</div>\n", $ppoints, $pid);
                                } else {
                                    printf("<div class='serendipityAdminMsgSuccess'>" . PLUGIN_KARMA_APPROVED_POINTS . "</div>\n", $ppoints, $pid);
                                }
                            } else {
                                printf("<div class='serendipityAdminMsgError'>" . PLUGIN_KARMA_REMOVE_ERROR . "</div>\n", $pid);
                            }
                        }
                    }
                    // URL; expected to be event_display and karmalog, respectively
                    $url = '?serendipity[adminModule]=' . htmlspecialchars($serendipity['GET']['adminModule']) . '&serendipity[adminAction]=' . htmlspecialchars($serendipity['GET']['adminAction']);
                    // Filters
                    print "\n<form action='' method='get' name='karmafilters' id='karmafilters'>\n  <input type='hidden' name='serendipity[adminModule]' value='{$serendipity['GET']['adminModule']}' />\n  <input type='hidden' name='serendipity[adminAction]' value='{$serendipity['GET']['adminAction']}' />\n<table class='serendipity_admin_filters' width='100%'>\n<tr>\n  <td colspan='4' class='serendipity_admin_filters_headline'><strong>" . FILTERS . "</strong></td>\n</tr>\n<tr>\n  <td>User Agent:</td>\n  <td><input class='input_textbox' type='text' name='serendipity[filter][user_agent]' size='15' value='" . htmlspecialchars($serendipity['GET']['filter']['user_agent']) . "' /></td>\n  <td>" . IP . "</td>\n  <td><input class='input_textbox' type='text' name='serendipity[filter][ip]' size='15' value='" . htmlspecialchars($serendipity['GET']['filter']['ip']) . "' /></td>\n</tr>\n<tr>\n  <td>Entry ID:</td>\n  <td><input class='input_textbox' type='text' name='serendipity[filter][entryid]' size='15' value='" . htmlspecialchars($serendipity['GET']['filter']['entryid']) . "' /></td>\n  <td>Entry title:</td>\n  <td><input class='input_textbox' type='text' name='serendipity[filter][title]' size='30' value='" . htmlspecialchars($serendipity['GET']['filter']['title']) . "' /></td>\n</tr>\n</table>\n";
                    // Set all filters into $and and $searchString
                    if (!empty($serendipity['GET']['filter']['entryid'])) {
                        $val = $serendipity['GET']['filter']['entryid'];
                        $and .= "AND l.entryid = '" . serendipity_db_escape_string($val) . "'";
                        $searchString .= "&amp;serendipity['filter']['entryid']=" . htmlspecialchars($val);
                    }
                    if (!empty($serendipity['GET']['filter']['ip'])) {
                        $val = $serendipity['GET']['filter']['ip'];
                        $and .= "AND l.ip = '" . serendipity_db_escape_string($val) . "'";
                        $searchString .= "&amp;serendipity['filter']['ip']=" . htmlspecialchars($val);
                    }
                    if (!empty($serendipity['GET']['filter']['user_agent'])) {
                        $val = $serendipity['GET']['filter']['user_agent'];
                        $and .= "AND l.user_agent LIKE '%" . serendipity_db_escape_string($val) . "%'";
                        $searchString .= "&amp;serendipity['filter']['user_agent']=" . htmlspecialchars($val);
                    }
                    if (!empty($serendipity['GET']['filter']['title'])) {
                        $val = $serendipity['GET']['filter']['title'];
                        $and .= "AND e.title LIKE '%" . serendipity_db_escape_string($val) . "%'";
                        $searchString .= "&amp;serendipity['filter']['title']=" . htmlspecialchars($val);
                    }
                    // Sorting (controls go after filtering controls in form above)
                    $sort_order = array('votetime' => DATE, 'user_agent' => USER_AGENT, 'title' => TITLE, 'entryid' => 'ID');
                    if (empty($serendipity['GET']['sort']['ordermode']) || $serendipity['GET']['sort']['ordermode'] != 'ASC') {
                        $desc = true;
                        $serendipity['GET']['sort']['ordermode'] = 'DESC';
                    }
                    if (!empty($serendipity['GET']['sort']['order']) && !empty($sort_order[$serendipity['GET']['sort']['order']])) {
                        $curr_order = $serendipity['GET']['sort']['order'];
                        $orderby = serendipity_db_escape_string($curr_order . ' ' . $serendipity['GET']['sort']['ordermode']);
                    } else {
                        $curr_order = 'votetime';
                        $orderby = 'votetime ' . serendipity_db_escape_string($serendipity['GET']['sort']['ordermode']);
                    }
                    print "\n<div>" . SORT_BY . "\n<select name='serendipity[sort][order]'>\n";
                    foreach ($sort_order as $order => $val) {
                        print "\n  <option value='{$order}'" . ($curr_order == $order ? " selected='selected'" : '') . ">{$val}</option>\n";
                    }
                    print "\n</select>\n<select name='serendipity[sort][ordermode]'>\n  <option value='DESC'" . ($desc ? "selected='selected'" : '') . ">" . SORT_ORDER_DESC . "</option>\n  <option value='ASC'" . ($desc ? '' : "selected='selected'") . ">" . SORT_ORDER_ASC . "</option>\n</select>\n</div>\n<input type='submit' name='submit' value=' - " . GO . " - ' class='serendipityPrettyButton input_button' /> \n</form>\n";
                    // Paging (partly ripped from include/admin/comments.inc.php)
                    $commentsPerPage = (int) (!empty($serendipity['GET']['filter']['perpage']) ? $serendipity['GET']['filter']['perpage'] : 25);
                    $sql = serendipity_db_query("SELECT COUNT(*) AS total FROM {$serendipity['dbPrefix']}karmalog l WHERE 1 = 1 " . $and, true);
                    $totalVotes = $sql['total'];
                    $pages = $commentsPerPage == COMMENTS_FILTER_ALL ? 1 : ceil($totalVotes / (int) $commentsPerPage);
                    $page = (int) $serendipity['GET']['page'];
                    if ($page == 0 || $page > $pages) {
                        $page = 1;
                    }
                    if ($page > 1) {
                        $linkPrevious = $url . '&amp;serendipity[page]=' . ($page - 1) . $searchString;
                    }
                    if ($pages > $page) {
                        $linkNext = $url . '&amp;serendipity[page]=' . ($page + 1) . $searchString;
                    }
                    if ($commentsPerPage == COMMENTS_FILTER_ALL) {
                        $limit = '';
                    } else {
                        $limit = serendipity_db_limit_sql(serendipity_db_limit(($page - 1) * (int) $commentsPerPage, (int) $commentsPerPage));
                    }
                    // Variables for display
                    if ($linkPrevious) {
                        $linkPrevious = '<a href="' . $linkPrevious . '" class="serendipityIconLink"><img src="' . serendipity_getTemplateFile('admin/img/previous.png') . '" /></a>';
                    } else {
                        $linkPrevious = '&nbsp;';
                    }
                    if ($linkNext) {
                        $linkNext = '<a href="' . $linkNext . '" class="serendipityIconLinkRight"><img src="' . serendipity_getTemplateFile('admin/img/next.png') . '" /></a>';
                    } else {
                        $linkNext = '&nbsp;';
                    }
                    $paging = sprintf(PAGE_BROWSE_COMMENTS, $page, $pages, $totalVotes);
                    // Retrieve the next batch of karma votes
                    // [entryid, points, ip, user_agent, votetime]
                    $sql = serendipity_db_query("SELECT l.entryid AS entryid, l.points AS points, l.ip AS ip, l.user_agent AS user_agent, l.votetime AS votetime, e.title AS title FROM {$serendipity['dbPrefix']}karmalog l\n                        LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = l.entryid)\n                        WHERE 1 = 1 " . $and . "\n                        ORDER BY {$orderby} {$limit}");
                    // Start the form for display and deleting
                    if (is_array($sql)) {
                        print "<form action='' method='post' name='formMultiDelete' id='formMultiDelete'>\n" . serendipity_setFormToken() . "\n<script type='text/javascript'>\nfunction invertSelection() {\n    var f = document.formMultiDelete;\n    for (var i = 0; i < f.elements.length; i++) {\n        if( f.elements[i].type == 'checkbox' ) {\n            f.elements[i].checked = !(f.elements[i].checked);\n        }\n    }\n}\n</script>\n";
                        // Print the header paging table
                        print "\n<table width='100%' style='border-collapse: collapse;'>\n  <tr>\n  <td align='left'>{$linkPrevious}</td>\n  <td align='center'>{$paging}</td>\n  <td align='right'>{$linkNext}</td>\n  </tr>\n</table>\n";
                        // Start the vote table
                        print "\n<table class='karmalog' width='100%'>\n";
                        // Print each vote
                        $i = 0;
                        foreach ($sql as $vote) {
                            $i++;
                            // entryid, title, points, ip, user_agent, votetime
                            $entrylink = serendipity_archiveURL($vote['entryid'], $vote['title'], 'serendipityHTTPPath', true);
                            $entryFilterHtml = "<a class='serendipityIconLink' href='{$url}&serendipity[filter][entryid]={$vote['entryid']}'><img src='" . serendipity_getTemplateFile('admin/img/zoom.png') . "' /></a>";
                            $ipFilterHtml = "<a class='serendipityIconLink' href='{$url}&serendipity[filter][ip]={$vote['ip']}'><img src='" . serendipity_getTemplateFile('admin/img/zoom.png') . "' /></a>";
                            $timestr = strftime('%H:%M:%S<br />%n%a %b %d %Y', $vote['votetime']);
                            $cssClass = 'serendipity_admin_list_item serendipity_admin_list_item_';
                            $cssClass .= $i % 2 == 0 ? 'even' : 'uneven';
                            $barClass = str_replace(array('.', ' '), array('_', '_'), $this->image_name);
                            $barHtml = $this->createRatingBar(null, $vote['points'], 1, $barClass);
                            $barHtml = sprintf($barHtml, 'what', $vote['points'], '1');
                            print "\n  <tr class='{$cssClass}'>\n    <td rowspan='2' width='20' align='center'>\n      <input class='input_checkbox' type='checkbox' name='serendipity[delete][{$i}]' value='{$i}' tabindex='{$i}' />\n      <input type='hidden' name='serendipity[karmalog{$i}][points]' value='{$vote['points']}' />\n      <input type='hidden' name='serendipity[karmalog{$i}][entryid]' value='{$vote['entryid']}' />\n      <input type='hidden' name='serendipity[karmalog{$i}][votetime]' value='{$vote['votetime']}' />\n      <input type='hidden' name='serendipity[karmalog{$i}][ip]' value='{$vote['ip']}' />\n      <input type='hidden' name='serendipity[karmalog{$i}][user_agent]' value='{$vote['user_agent']}' />\n    </td>\n    <td>{$barHtml}</td>\n    <td colspan='2'><a href='{$entrylink}' title='{$vote['entryid']}' alt='{$vote['title']}'>{$vote['title']}</a> {$entryFilterHtml}</td>\n  </tr>\n  <tr class='{$cssClass}'>\n    <td>{$timestr}</td>\n    <td>{$vote['ip']} {$ipFilterHtml}</td>\n    <td>{$vote['user_agent']}</td>\n  </tr>\n";
                        }
                        // End the vote table
                        print "\n                            </table>\n                            ";
                        if (is_array($sql)) {
                            print "\n<input type='button' name='toggle' value='" . INVERT_SELECTIONS . "' onclick='invertSelection()' class='serendipityPrettyButton input_button' /> \n<input class='serendipityPrettyButton input_button' type='submit' value='" . PLUGIN_KARMA_DELETE_VOTES . "' name='serendipity[delete_button]' />\n<input class='serendipityPrettyButton input_button' type='submit' value='" . PLUGIN_KARMA_APPROVE_VOTES . "' name='serendipity[approve_button]' />\n</form>\n";
                        }
                        // Print the footer paging table
                        print "\n<table width='100%' style='border-collapse: collapse;'>\n  <tr>\n  <td align='left'>{$linkPrevious}</td>\n  <td align='center'>{$paging}</td>\n  <td align='right'>{$linkNext}</td>\n  </tr>\n</table>\n";
                    } else {
                        print "\n<div class='serendipityAdminMsgNotice'>No entries to display.</div>\n";
                    }
                    return true;
                    break;
                default:
                    return false;
            }
            // End switch on event hooks
        } else {
            return false;
        }
    }
 function getMyNotes($limited = true)
 {
     global $serendipity;
     $this->setupDB();
     $sql = "SELECT a.noteid, a.authorid, a.notetime, a.subject, a.body, a.notetype,\n                       ar.realname\n                  FROM {$serendipity['dbPrefix']}adminnotes\n                    AS a\n\n                  JOIN {$serendipity['dbPrefix']}adminnotes_to_groups\n                    AS atg\n                    ON atg.noteid = a.noteid\n\n                  JOIN {$serendipity['dbPrefix']}authorgroups\n                    AS ag\n                    ON (ag.groupid = atg.groupid AND ag.authorid = {$serendipity['authorid']})\n\n                  JOIN {$serendipity['dbPrefix']}authors\n                    AS axs\n                    ON axs.authorid = ag.authorid\n\n                  JOIN {$serendipity['dbPrefix']}authors\n                    AS ar\n                    ON ar.authorid = a.authorid\n                " . (is_int($limited) ? 'WHERE a.noteid = ' . (int) $limited : '') . "\n              GROUP BY a.noteid\n              ORDER BY a.notetime DESC";
     if ($limited) {
         $sql .= ' ' . serendipity_db_limit_sql($this->get_config('limit'));
     }
     return serendipity_db_query($sql, is_int($limited) ? true : false, 'assoc');
 }
 function getAllRecyclerComments($page = false)
 {
     global $serendipity;
     if ($page === false) {
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}spamblock_bayes_recycler ORDER BY id DESC";
     } else {
         $first = $page * 20;
         $amount = 21;
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}spamblock_bayes_recycler ORDER BY id DESC" . serendipity_db_limit_sql(sprintf("%d,%d", $first, $amount));
     }
     $comments = serendipity_db_query($sql, false, 'assoc');
     return $comments;
 }
Beispiel #11
0
$searchString .= '&amp;' . serendipity_setFormToken('url');
/* Paging */
$sql = serendipity_db_query("SELECT COUNT(*) AS total FROM {$serendipity['dbPrefix']}comments c WHERE 1 = 1 " . ($c_type !== null ? " AND c.type = '{$c_type}' " : '') . $and, true);
$totalComments = $sql['total'];
$pages = $commentsPerPage == COMMENTS_FILTER_ALL ? 1 : ceil($totalComments / (int) $commentsPerPage);
$page = (int) $serendipity['GET']['page'];
if ($page == 0 || $page > $pages) {
    $page = 1;
}
$linkPrevious = 'serendipity_admin.php?serendipity[adminModule]=comments&amp;serendipity[page]=' . ($page - 1) . $searchString;
$linkNext = 'serendipity_admin.php?serendipity[adminModule]=comments&amp;serendipity[page]=' . ($page + 1) . $searchString;
$filter_vals = array(10, 20, 50, COMMENTS_FILTER_ALL);
if ($commentsPerPage == COMMENTS_FILTER_ALL) {
    $limit = '';
} else {
    $limit = serendipity_db_limit_sql(serendipity_db_limit(($page - 1) * (int) $commentsPerPage, (int) $commentsPerPage));
}
$sql = serendipity_db_query("SELECT c.*, e.title FROM {$serendipity['dbPrefix']}comments c\n                                LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = c.entry_id)\n                                WHERE 1 = 1 " . ($c_type !== null ? " AND c.type = '{$c_type}' " : '') . $and . (!serendipity_checkPermission('adminEntriesMaintainOthers') ? 'AND e.authorid = ' . (int) $serendipity['authorid'] : '') . "\n                                ORDER BY c.id DESC {$limit}");
if (serendipity_checkPermission('adminComments')) {
    ob_start();
    # This event has to get send here so the spamblock-plugin can block an author now and the comment_page show that on this pageload
    serendipity_plugin_api::hook_event('backend_comments_top', $sql);
    $data['backend_comments_top'] = ob_get_contents();
    ob_end_clean();
}
$data['commentsPerPage'] = $commentsPerPage;
$data['totalComments'] = $totalComments;
$data['pages'] = $pages;
$data['page'] = $page;
$data['linkPrevious'] = $linkPrevious;
$data['linkNext'] = $linkNext;
function displayTopUrlList($list, $limit, $use_links = true, $filter_out = "", $daylimit = 7)
{
    global $serendipity;
    if ($limit) {
        $limit = serendipity_db_limit_sql($limit);
    }
    $filter_out_sql = !$filter_out ? "" : "host NOT LIKE '" . join("' AND host NOT LIKE '", explode(";", preg_replace('@^;|;$@', '', str_replace("*", "%", $filter_out)))) . "'";
    /* HACK */
    if (preg_match('/^mysqli?/', $serendipity['dbType'])) {
        if ($filter_out) {
            $filter_out_sql = "AND " . $filter_out_sql;
        }
        /* Nonportable SQL due to MySQL date functions,
         * but produces rolling 7 day totals, which is more
         * interesting
         */
        $query = "SELECT scheme, host, SUM(count) AS total\n                  FROM {$serendipity['dbPrefix']}{$list}\n                  WHERE " . ($daylimit > 0 ? "day > date_sub(current_date, interval " . (int) $daylimit . " day)" : "1 = 1") . "\n                  {$filter_out_sql}\n                  GROUP BY host\n                  ORDER BY total DESC, host\n                  {$limit}";
    } else {
        if ($filter_out) {
            $filter_out_sql = "WHERE " . $filter_out_sql;
        }
        /* Portable version of the same query */
        $query = "SELECT scheme, host, SUM(count) AS total\n                  FROM {$serendipity['dbPrefix']}{$list}\n                  {$filter_out_sql}\n                  GROUP BY scheme, host\n                  ORDER BY total DESC, host\n                  {$limit}";
    }
    $rows = serendipity_db_query($query);
    echo "<span class='serendipityReferer'>";
    if (is_array($rows)) {
        foreach ($rows as $row) {
            if ($use_links) {
                printf('<a href="%1$s://%2$s" title="%2$s" >%2$s</a> (%3$s)<br />', function_exists('serendipity_specialchars') ? serendipity_specialchars($row['scheme']) : htmlspecialchars($row['scheme'], ENT_COMPAT, LANG_CHARSET), function_exists('serendipity_specialchars') ? serendipity_specialchars($row['host']) : htmlspecialchars($row['host'], ENT_COMPAT, LANG_CHARSET), function_exists('serendipity_specialchars') ? serendipity_specialchars($row['total']) : htmlspecialchars($row['total'], ENT_COMPAT, LANG_CHARSET));
            } else {
                printf('%1$s (%2$s)<br />', function_exists('serendipity_specialchars') ? serendipity_specialchars($row['host']) : htmlspecialchars($row['host'], ENT_COMPAT, LANG_CHARSET), function_exists('serendipity_specialchars') ? serendipity_specialchars($row['total']) : htmlspecialchars($row['total'], ENT_COMPAT, LANG_CHARSET));
            }
        }
    }
    echo "</span>";
}
 /**
  * Guestbook Select entries
  *
  * @param  int   $cp   limit from
  * @param  int   $rp   limit to
  * @param  int   $ap   approved
  * @return mixed boolean/array $entries
  */
 function getEntriesDB($cp, $rp, $ap)
 {
     global $serendipity;
     $whe = serendipity_db_bool($this->get_config('showapp')) || serendipity_db_bool($this->get_config('automoderate')) ? "WHERE approved={$ap}" : '';
     // generate guestbook entries and send them to entries template
     $sql = "SELECT * FROM {$serendipity['dbPrefix']}guestbook {$whe} ORDER BY timestamp DESC ";
     $entries = serendipity_db_query($sql . serendipity_db_limit_sql(serendipity_db_limit($cp * $rp, $rp)), false, 'assoc');
     return is_array($entries) ? $entries : false;
 }
    function generate_content(&$title)
    {
        global $serendipity;
        $title = $this->get_config('title');
        $max_entries = $this->get_config('max_entries');
        $del_str = $this->get_config('delete');
        $submit_str = $this->get_config('submit');
        $timestamp = $this->get_config('timestamp');
        $show_tip = serendipity_db_bool($this->get_config('show_tip'));
        $is_public = serendipity_db_bool($this->get_config('is_public'));
        // Create table, if not yet existant
        if ($this->get_config('version') != '0.3') {
            $q = "CREATE TABLE {$serendipity['dbPrefix']}quicklink (\n                        id {AUTOINCREMENT} {PRIMARY},\n                        timestamp int(10) {UNSIGNED} NULL,\n                        link varchar(255),\n                        label varchar(255),\n                        description text\n                    )";
            @($sql = serendipity_db_schema_import($q));
            $this->set_config('version', '0.3');
        }
        //Put new link into the database if necessary
        if (($_SESSION['serendipityAuthedUser'] === true || $is_public === true) && !empty($_REQUEST['action']) && $_REQUEST['action'] == 'sendquicklink' && trim($_REQUEST['serendipity']['quicklink']) != '') {
            $sql = sprintf("INSERT INTO %squicklink (\n                            timestamp,\n                            link,\n                            label,\n                            description\n                       ) VALUES (\n                            %s,\n                            '%s',\n                            '%s',\n                            '%s'\n                       )", $serendipity['dbPrefix'], time(), serendipity_db_escape_string(trim($_REQUEST['serendipity']['quicklink'])), serendipity_db_escape_string(trim($_REQUEST['serendipity']['quicklinklabel'])), serendipity_db_escape_string(trim($_REQUEST['serendipity']['quicklinkdesc'])));
            serendipity_db_query($sql);
        }
        if (!$max_entries || !is_numeric($max_entries) || $max_entries < 1) {
            $max_entries = 15;
        }
        // if a delete link clicked!
        if (!empty($serendipity['GET']['action']) && $serendipity['GET']['action'] == 'quicklinkdelete' && $_SESSION['serendipityAuthedUser'] === true && $serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF) {
            $sql = sprintf("DELETE from %squicklink\n                              WHERE id = %d", $serendipity['dbPrefix'], (int) $serendipity['GET']['link_id']);
            serendipity_db_query($sql);
        }
        // if start is set
        if (!empty($serendipity['GET']['start'])) {
            $start = (int) $serendipity['GET']['start'];
        } else {
            $start = 0;
        }
        $next = $start + $max_entries;
        $prev = $start - $max_entries;
        // disable previous link if needed
        if ($prev < 0) {
            $prev = false;
        }
        $q = 'SELECT    count(*) AS count
                FROM    ' . $serendipity['dbPrefix'] . 'quicklink';
        $sql = serendipity_db_query($q);
        // disable next link if needed
        if ($next >= $sql[0]['count']) {
            $next = false;
        }
        if ($_SESSION['serendipityAuthedUser'] === true || $is_public === true) {
            ?>

       <form action="<?php 
            echo serendipity_currentURL();
            ?>
" method="post">
            <div>
                <input type="hidden" name="action" value="sendquicklink" />
                <input type="text" name="serendipity[quicklinklabel]" style="width: 90%" value="<?php 
            echo PLUGIN_QUICKLINK_LABEL;
            ?>
" onclick="if(this.value='<?php 
            echo PLUGIN_QUICKLINK_LABEL;
            ?>
') this.value=''" />
                <input type="text" name="serendipity[quicklink]" style="width: 90%" value="http://" dir="ltr" />
                <textarea name="serendipity[quicklinkdesc]" cols="15" rows="2" style="width: 90%"></textarea>
                <input name='submit' type='submit' value='<?php 
            echo $submit_str;
            ?>
' />
            </div>
        </form><br />
<?php 
        }
        ?>
<div id="quick_link_tip" style="position:absolute; visibility: hidden"></div>
<script language="JavaScript"><!--

var toolTipSTYLE="";
function initToolTips()
{
  toolTipSTYLE = document.getElementById("quick_link_tip").style;
  toolTipSTYLE.visibility = "visible";
  toolTipSTYLE.display = "none";
  document.onmousemove = moveToMouseLoc;
}
function toolTip(msg, bg)
{
  if(toolTip.arguments.length < 1) //hide
  {
	toolTipSTYLE.display = "none";
  }
  else // show
  {
    if(!bg) bg = "#FFFFFF";
    var content =
    '<table border="1" cellspacing="0" cellpadding="0" bgcolor="' + bg +
    '"><td><font size="-1">&nbsp\;' + msg +
    '&nbsp\;</font></td></table>';
    document.getElementById("quick_link_tip").innerHTML = content;
    toolTipSTYLE.display='block'
  }
}
function moveToMouseLoc(e)
{
  if (e && e.pageX) {
    x = e.pageX;
    y = e.pageY;
    toolTipSTYLE.left = x + 0 + 'px';
    toolTipSTYLE.top = y + 20 + 'px';
  }
  return true;
}
initToolTips();
//--></script>
<div style="margin: 0px; padding: 0px; text-align: left;">
<?php 
        $q = 'SELECT    s.description       AS description,
						s.link              AS link,
						s.label             AS label,
                        s.timestamp         AS stamp,
                        s.id                AS link_id
              FROM    ' . $serendipity['dbPrefix'] . 'quicklink AS s
              ORDER BY    s.timestamp DESC
              ' . serendipity_db_limit_sql(serendipity_db_limit($start, $max_entries));
        $sql = serendipity_db_query($q);
        if ($sql && is_array($sql)) {
            foreach ($sql as $key => $row) {
                if (!preg_match('@^https?://@', trim($row['link']))) {
                    $row['link'] = 'http://' . $row['link'];
                }
                $row['link'] = str_replace('javascript:', '', $row['link']);
                // create tool tip string
                $tip = '';
                if ($show_tip == 'true') {
                    $tip = function_exists('serendipity_specialchars') ? serendipity_specialchars(serendipity_strftime($timestamp, $row['stamp'])) : htmlspecialchars(serendipity_strftime($timestamp, $row['stamp']), ENT_COMPAT, LANG_CHARSET);
                    if (trim($row['description']) != '') {
                        $tip .= '<br />' . nl2br(function_exists('serendipity_specialchars') ? serendipity_specialchars($row['description']) : htmlspecialchars($row['description'], ENT_COMPAT, LANG_CHARSET));
                    }
                    $tip = ' onMouseOver="toolTip(\'' . $tip . '\')" onMouseOut="toolTip()"';
                }
                // create label of link
                if (trim($row['label']) == '' || $row['label'] == PLUGIN_QUICKLINK_LABEL) {
                    $label = $row['link'];
                } else {
                    $label = $row['label'];
                }
                // create link string
                $link = '<a href="' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($row['link']) : htmlspecialchars($row['link'], ENT_COMPAT, LANG_CHARSET)) . '"' . $tip . ' target="_blank">' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($label) : htmlspecialchars($label, ENT_COMPAT, LANG_CHARSET)) . '</a>';
                // create telete link string
                $deleteLink = '';
                if ($_SESSION['serendipityAuthedUser'] === true && $serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF) {
                    $deleteLink = ' | <a href="' . $serendipity['baseURL'] . $serendipity['indexFile'] . '?serendipity[action]=quicklinkdelete&amp;serendipity[link_id]=' . $row['link_id'] . '" onclick="return confirm(\'' . PLUGIN_QUICKLINK_ALERT . '\');">' . $del_str . '</a>';
                }
                $entry = array('link' => $link);
                serendipity_plugin_api::hook_event('frontend_display', $entry);
                echo $entry['link'] . $deleteLink . '<br />' . "\n\n";
            }
        }
        if ($prev !== false || $next !== false) {
            if ($prev !== false) {
                echo '<br /><div align="center"><a href="' . $serendipity['baseURL'] . $serendipity['indexFile'] . '?serendipity[start]=' . $prev . '">' . PREVIOUS . '</a> | ';
            } else {
                echo '<br /><div align="center">' . PREVIOUS . ' | ';
            }
            if ($next !== false) {
                echo '<a href="' . $serendipity['baseURL'] . $serendipity['indexFile'] . '?serendipity[start]=' . $next . '">' . NEXT . '</a></div><br />' . "\n";
            } else {
                echo NEXT . '</div><br />' . "\n";
            }
        }
        ?>
</div>
<?php 
    }
 function generate_content(&$title)
 {
     global $serendipity;
     $number = $this->get_config('number');
     $category = $this->get_config('category', 'none');
     $title = $this->get_config('title', $this->title);
     $number_from_sw = $this->get_config('number_from');
     if ($category == '_cur') {
         $category = $serendipity['GET']['category'];
     }
     $sql_join = '';
     $sql_where = '';
     if ($category != 'none' && is_numeric($category)) {
         $sql_join = 'LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'entrycat AS ec ON e.id = ec.entryid
                      LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'category AS c  ON ec.categoryid = c.categoryid';
         $sql_where = ' AND (c.category_left BETWEEN ' . implode(' AND ', serendipity_fetchCategoryRange($category)) . ')';
     }
     if (!$number || !is_numeric($number) || $number < 1) {
         $number = 10;
     }
     $sql_number = $number;
     switch ($number_from_sw) {
         case 'skip':
             $sql_number = serendipity_db_limit_sql(serendipity_db_limit($serendipity['fetchLimit'], $sql_number));
             break;
         default:
             $sql_number = serendipity_db_limit_sql(serendipity_db_limit(0, $sql_number));
             break;
     }
     $sortby = $this->get_config('sortby', 'comments');
     switch ($sortby) {
         case 'comments':
             $entries_query = "SELECT e.id,\n                                         e.title,\n                                         e.comments AS points,\n                                         e.timestamp\n                                    FROM {$serendipity['dbPrefix']}entries AS e\n                                         {$sql_join}\n                                   WHERE e.isdraft = 'false' AND e.timestamp <= " . time() . "\n                                         {$sql_where}\n                                ORDER BY e.comments DESC\n                                   {$sql_number}";
             break;
         case 'commentors':
             $entries_query = "SELECT c.author, count(c.id) AS points\n                                    FROM {$serendipity['dbPrefix']}entries AS e\n                                    JOIN {$serendipity['dbPrefix']}comments AS c\n                                         ON c.entry_id = e.id\n                                         {$sql_join}\n                                   WHERE e.isdraft = 'false' AND e.timestamp <= " . time() . "\n                                     AND c.status = 'approved'\n                                         {$sql_where}\n                                GROUP BY c.author\n                                ORDER BY points DESC\n                                   {$sql_number}";
             break;
         case 'karma':
             $entries_query = "SELECT e.id,\n                                         e.title,\n                                         e.comments,\n                                         e.timestamp,\n                                         k.points AS points\n                                    FROM {$serendipity['dbPrefix']}entries AS e\n                                         {$sql_join}\n                         LEFT OUTER JOIN {$serendipity['dbPrefix']}karma AS k\n                                      ON k.entryid = e.id\n                                   WHERE e.isdraft = 'false' AND e.timestamp <= " . time() . "\n                                         {$sql_where}\n                                GROUP BY e.id, e.title, e.comments, e.timestamp, k.visits\n                                ORDER BY k.points DESC\n                                    {$sql_number}";
             break;
         case 'visits':
             $entries_query = "SELECT e.id,\n                                         e.title,\n                                         e.comments,\n                                         e.timestamp,\n                                         k.visits AS points\n                                    FROM {$serendipity['dbPrefix']}entries AS e\n                                         {$sql_join}\n                         LEFT OUTER JOIN {$serendipity['dbPrefix']}karma AS k\n                                      ON k.entryid = e.id\n                                   WHERE e.isdraft = 'false' AND e.timestamp <= " . time() . "\n                                         {$sql_where}\n                                GROUP BY e.id, e.title, e.comments, e.timestamp, k.visits\n                                ORDER BY k.visits DESC\n                                    {$sql_number}";
             break;
         case 'lowvisits':
             $entries_query = "SELECT e.id,\n                                         e.title,\n                                         e.comments,\n                                         e.timestamp,\n                                         k.visits AS points\n                                    FROM {$serendipity['dbPrefix']}entries AS e\n                                         {$sql_join}\n                         LEFT OUTER JOIN {$serendipity['dbPrefix']}karma AS k\n                                      ON k.entryid = e.id\n                                   WHERE e.isdraft = 'false' AND e.timestamp <= " . time() . "\n                                         {$sql_where}\n                                GROUP BY e.id, e.title, e.comments, e.timestamp, k.visits         \n                                ORDER BY k.visits ASC\n                    {$sql_number}";
             break;
         case 'exits':
             $entries_query = "SELECT e.id,\n                                         e.title,\n                                         e.comments,\n                                         e.timestamp,\n                                         SUM(ex.count) AS points\n                                    FROM {$serendipity['dbPrefix']}entries AS e\n                                         {$sql_join}\n                         LEFT OUTER JOIN {$serendipity['dbPrefix']}exits AS ex\n                                      ON ex.entry_id = e.id\n                                   WHERE e.isdraft = 'false' AND e.timestamp <= " . time() . "\n                                         {$sql_where}\n                                GROUP BY ex.entry_id\n                                ORDER BY points DESC\n                                    {$sql_number}";
             break;
     }
     $entries = serendipity_db_query($entries_query);
     $hidden = explode(',', trim($this->get_config('commentors_hide')));
     echo '<ul class="plainList">';
     if (isset($entries) && is_array($entries)) {
         foreach ($entries as $k => $entry) {
             if ($sortby == 'commentors') {
                 if (in_array($entry['author'], $hidden)) {
                     continue;
                 }
                 $entryLink = $serendipity['serendipityHTTPPath'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . PATH_COMMENTS . '/' . urlencode($entry['author']);
                 echo '<li><a href="' . $entryLink . '" title="' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($entry['author']) : htmlspecialchars($entry['author'], ENT_COMPAT, LANG_CHARSET)) . '">' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($entry['author']) : htmlspecialchars($entry['author'], ENT_COMPAT, LANG_CHARSET)) . '</a>';
                 echo ' <span class="serendipitySideBarDate">(' . (!empty($entry['points']) ? function_exists('serendipity_specialchars') ? serendipity_specialchars($entry['points']) : htmlspecialchars($entry['points'], ENT_COMPAT, LANG_CHARSET) : 0) . ')</span></li>';
             } else {
                 $entryLink = serendipity_archiveURL($entry['id'], $entry['title'], 'serendipityHTTPPath', true, array('timestamp' => $entry['timestamp']));
                 echo '<li><a href="' . $entryLink . '" title="' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($entry['title']) : htmlspecialchars($entry['title'], ENT_COMPAT, LANG_CHARSET)) . '">' . $entry['title'] . '</a>';
                 echo ' <span class="serendipitySideBarDate">(' . (!empty($entry['points']) ? function_exists('serendipity_specialchars') ? serendipity_specialchars($entry['points']) : htmlspecialchars($entry['points'], ENT_COMPAT, LANG_CHARSET) : 0) . ')</span></li>';
             }
         }
     }
     echo '</ul>';
 }
 function showForum()
 {
     global $serendipity;
     if (!headers_sent()) {
         header('HTTP/1.0 200');
         header('Status: 200 OK');
     }
     $ERRORMSG = "";
     $THREAD_UNREAD_ANNOUNCEMENT = "<img src=\"" . $this->DMA_forum_getRelPath() . "/img/thread_unread_announce.png\" width=\"20\" height=\"20\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_READ . "\" title=\"" . PLUGIN_FORUM_ALT_READ . "\" />";
     $THREAD_READ_ANNOUNCEMENT = "<img src=\"" . $this->DMA_forum_getRelPath() . "/img/thread_read_announce.png\" width=\"20\" height=\"20\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_READ . "\" title=\"" . PLUGIN_FORUM_ALT_READ . "\" />";
     $THREAD_UNREAD = "<img src=\"" . $this->DMA_forum_getRelPath() . "/img/thread_unread.png\" width=\"20\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_UNREAD . "\" title=\"" . PLUGIN_FORUM_ALT_UNREAD . "\" />";
     $THREAD_HUGE_UNREAD = "<img src=\"" . $this->DMA_forum_getRelPath() . "/img/thread_huge_unread.png\" width=\"20\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_UNREAD . "\" title=\"" . PLUGIN_FORUM_ALT_UNREAD . "\" />";
     $THREAD_READ = "<img src=\"" . $this->DMA_forum_getRelPath() . "/img/thread_read.png\" width=\"20\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_READ . "\" title=\"" . PLUGIN_FORUM_ALT_READ . "\" />";
     $THREAD_HUGE_READ = "<img src=\"" . $this->DMA_forum_getRelPath() . "/img/thread_huge_read.png\" width=\"20\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_READ . "\" title=\"" . PLUGIN_FORUM_ALT_READ . "\" />";
     $DEL_FILE_BUTTON = "<img src=\"" . serendipity_getTemplateFile('admin/img/delete.png') . "\" width=\"18\" height=\"18\" border=\"0\" alt=\"" . DELETE . "\" title=\"" . DELETE . "\" />";
     if (!isset($_SESSION['forum_visited']) || intval($_SESSION['forum_visited']) <= 0) {
         if (serendipity_userLoggedIn()) {
             $sql = "SELECT visits, lastvisit FROM {$serendipity['dbPrefix']}dma_forum_users WHERE authorid = '" . intval($serendipity['authorid']) . "'";
             $visits = serendipity_db_query($sql);
             if (is_array($visits) && count($visits) >= 1) {
                 $q = "UPDATE {$serendipity['dbPrefix']}dma_forum_users SET visits = visits+1, lastvisit = '" . time() . "' WHERE authorid = '" . intval($serendipity['authorid']) . "'";
                 serendipity_db_query($q);
             } else {
                 $q = "INSERT INTO {$serendipity['dbPrefix']}dma_forum_users (authorid, visits, lastvisit) VALUES ('" . intval($serendipity['authorid']) . "', '1', '" . time() . "')";
                 serendipity_db_query($q);
             }
             $_SESSION['forum_visited'] = 1;
         }
     }
     if (is_array($_COOKIE) && trim($_COOKIE['s9yread']) != "") {
         $READARRAY = unserialize(stripslashes(trim($_COOKIE['s9yread'])));
     } else {
         $READARRAY = array();
     }
     // POST part
     if (isset($serendipity['POST']['action']) && trim($serendipity['POST']['action']) == "reply") {
         if (!isset($serendipity['POST']['authorname']) || trim($serendipity['POST']['authorname']) == "") {
             if (serendipity_userLoggedIn()) {
                 $serendipity['POST']['authorname'] = $serendipity['serendipityUser'];
             } else {
                 $serendipity['POST']['authorname'] = PLUGIN_FORUM_GUEST;
             }
         }
         if ($this->get_config('use_captchas')) {
             // Fake call to spamblock and other comment plugins.
             $ca = array('id' => 0, 'allow_comments' => 'true', 'moderate_comments' => false, 'last_modified' => 1, 'timestamp' => 1);
             $commentInfo = array('type' => 'NORMAL', 'source' => 'commentform', 'name' => $serendipity['POST']['authorname'], 'url' => '', 'comment' => $serendipity['POST']['comment'], 'email' => '');
             serendipity_plugin_api::hook_event('frontend_saveComment', $ca, $commentInfo);
         } else {
             $ca['allow_comments'] = true;
         }
         if ($ca['allow_comments'] === false) {
             $ERRORMSG = PLUGIN_FORUM_ERR_WRONG_CAPTCHA_STRING;
         } else {
             $serendipity['POST']['title'] = trim($serendipity['POST']['title']);
             $serendipity['POST']['comment'] = trim($serendipity['POST']['comment']);
             $serendipity['POST']['authorname'] = trim($serendipity['POST']['authorname']);
             if (!isset($serendipity['POST']['comment']) || strlen(trim($serendipity['POST']['comment'])) <= 3) {
                 $ERRORMSG = PLUGIN_FORUM_ERR_MISSING_MESSAGE;
             } else {
                 $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE threadid='" . intval($serendipity['POST']['threadid']) . "'";
                 $thread = serendipity_db_query($sql);
                 if ($thread[0]['flag'] == 1) {
                     $ERRORMSG = PLUGIN_FORUM_ERR_THREAD_CLOSED;
                 } else {
                     if (trim($serendipity['POST']['comment']) == $_SESSION['lastposttext']) {
                         $ERRORMSG = PLUGIN_FORUM_ERR_DOUBLE_POST;
                     } elseif ($_SESSION['lastposttime'] >= time() - 10) {
                         $ERRORMSG = PLUGIN_FORUM_ERR_POST_INTERVAL;
                     } else {
                         $now = time();
                         $postid = DMA_forum_InsertReply(intval($serendipity['POST']['boardid']), intval($serendipity['POST']['threadid']), intval($serendipity['POST']['replyto']), trim($serendipity['POST']['authorname']), trim($serendipity['POST']['title']), trim($serendipity['POST']['comment']), $this->get_config('itemsperpage'), $this->get_config('notifymail_from'), $this->get_config('notifymail_name'), $this->get_config('pageurl'), $this->get_config('admin_notify'));
                         if (serendipity_userLoggedIn() && $this->get_config('fileupload_reguser') || $this->get_config('fileupload_guest')) {
                             DMA_forum_uploadFiles($postid, $this->get_config('uploaddir'));
                             if ($this->SUCCESS <= 0) {
                                 if (count($this->UPLOAD_TOOBIG) >= 1) {
                                     $ERRORMSG = PLUGIN_FORUM_ERR_FILE_TOO_BIG;
                                 } elseif (count($this->UPLOAD_NOTCOPIED) >= 1) {
                                     $ERRORMSG = PLUGIN_FORUM_ERR_FILE_NOT_COPIED;
                                 }
                             }
                         }
                     }
                 }
             }
         }
         if (serendipity_userLoggedIn()) {
             $POST_AUTHORNAME = $serendipity['serendipityUser'];
         } else {
             $POST_AUTHORNAME = trim($serendipity['POST']['authorname']);
         }
         $POST_TITLE = trim($serendipity['POST']['title']);
         $POST_MESSAGE = trim($serendipity['POST']['comment']);
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $_GET['boardid'] = intval($serendipity['POST']['boardid']);
             $_GET['threadid'] = intval($serendipity['POST']['threadid']);
             $_GET['replyto'] = intval($serendipity['POST']['replyto']);
             $_GET['quote'] = 0;
         }
     } elseif (isset($serendipity['POST']['action']) && trim($serendipity['POST']['action']) == "edit") {
         if (!isset($serendipity['POST']['authorname']) || trim($serendipity['POST']['authorname']) == "") {
             if (serendipity_userLoggedIn()) {
                 $serendipity['POST']['authorname'] = $serendipity['serendipityUser'];
             } else {
                 $serendipity['POST']['authorname'] = PLUGIN_FORUM_GUEST;
             }
         }
         $serendipity['POST']['title'] = trim($serendipity['POST']['title']);
         $serendipity['POST']['comment'] = trim($serendipity['POST']['comment']);
         $serendipity['POST']['authorname'] = trim($serendipity['POST']['authorname']);
         if (!isset($serendipity['POST']['comment']) || strlen(trim($serendipity['POST']['comment'])) <= 3) {
             $ERRORMSG = PLUGIN_FORUM_ERR_MISSING_MESSAGE;
         } else {
             $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE postid='" . intval($serendipity['POST']['edit']) . "'";
             $post = serendipity_db_query($sql);
             if (serendipity_userLoggedIn() && ($serendipity['serendipityUser'] == $post[0]['authorname'] && $serendipity['authorid'] == $post[0]['authorid'] || $serendipity['serendipityUserlevel'] == 255)) {
                 if (serendipity_userLoggedIn() && $serendipity['serendipityUserlevel'] == USERLEVEL_ADMIN) {
                     if (isset($serendipity['POST']['announcement']) && intval($serendipity['POST']['announcement']) == 1) {
                         $announce = 1;
                     } else {
                         $announce = 0;
                     }
                 } else {
                     $announce = 0;
                 }
                 DMA_forum_EditReply(intval($serendipity['POST']['boardid']), intval($serendipity['POST']['threadid']), intval($serendipity['POST']['edit']), trim($serendipity['POST']['authorname']), trim($serendipity['POST']['title']), trim($serendipity['POST']['comment']), intval($serendipity['POST']['page']), $announce);
                 if (serendipity_userLoggedIn() && $this->get_config('fileupload_reguser') || $this->get_config('fileupload_guest')) {
                     DMA_forum_uploadFiles(intval($serendipity['POST']['edit']), $this->get_config('uploaddir'));
                     if ($this->SUCCESS <= 0) {
                         if (count($this->UPLOAD_TOOBIG) >= 1) {
                             $ERRORMSG = PLUGIN_FORUM_ERR_FILE_TOO_BIG;
                         } elseif (count($this->UPLOAD_NOTCOPIED) >= 1) {
                             $ERRORMSG = PLUGIN_FORUM_ERR_FILE_NOT_COPIED;
                         }
                     }
                 }
             } else {
                 $ERRORMSG = PLUGIN_FORUM_ERR_EDIT_NOT_ALLOWED;
             }
         }
         if (serendipity_userLoggedIn()) {
             $POST_AUTHORNAME = $serendipity['serendipityUser'];
         } else {
             $POST_AUTHORNAME = trim($serendipity['POST']['authorname']);
         }
         $POST_TITLE = trim($serendipity['POST']['title']);
         $POST_MESSAGE = trim($serendipity['POST']['comment']);
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $_GET['boardid'] = intval($serendipity['POST']['boardid']);
             $_GET['threadid'] = intval($serendipity['POST']['threadid']);
             $_GET['edit'] = intval($serendipity['POST']['edit']);
         }
     } elseif (isset($serendipity['POST']['action']) && trim($serendipity['POST']['action']) == "delete") {
         if (!isset($serendipity['POST']['no']) || trim($serendipity['POST']['no']) == "") {
             if (!isset($serendipity['serendipityUserlevel']) || $serendipity['serendipityUserlevel'] != 255) {
                 $ERRORMSG = PLUGIN_FORUM_ERR_DELETE_NOT_ALLOWED;
             } else {
                 DMA_forum_DeletePost(intval($serendipity['POST']['boardid']), intval($serendipity['POST']['threadid']), intval($serendipity['POST']['delete']), intval($serendipity['POST']['page']), $this->get_config('uploaddir'), $this->get_config('itemsperpage'));
             }
         }
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $_GET['boardid'] = intval($serendipity['POST']['boardid']);
             $_GET['threadid'] = intval($serendipity['POST']['threadid']);
         }
     } elseif (isset($serendipity['POST']['action']) && trim($serendipity['POST']['action']) == "newthread") {
         if (!isset($serendipity['POST']['authorname']) || trim($serendipity['POST']['authorname']) == "") {
             if (serendipity_userLoggedIn()) {
                 $serendipity['POST']['authorname'] = $serendipity['serendipityUser'];
             } else {
                 $serendipity['POST']['authorname'] = PLUGIN_FORUM_GUEST;
             }
         }
         if ($this->get_config('use_captchas')) {
             // Fake call to spamblock and other comment plugins.
             $ca = array('id' => 0, 'allow_comments' => 'true', 'moderate_comments' => false, 'last_modified' => 1, 'timestamp' => 1);
             $commentInfo = array('type' => 'NORMAL', 'source' => 'commentform', 'name' => $serendipity['POST']['authorname'], 'url' => '', 'comment' => $serendipity['POST']['comment'], 'email' => '');
             serendipity_plugin_api::hook_event('frontend_saveComment', $ca, $commentInfo);
         } else {
             $ca['allow_comments'] = true;
         }
         if ($ca['allow_comments'] === false) {
             $ERRORMSG = PLUGIN_FORUM_ERR_WRONG_CAPTCHA_STRING;
         } else {
             $serendipity['POST']['title'] = trim($serendipity['POST']['title']);
             $serendipity['POST']['comment'] = trim($serendipity['POST']['comment']);
             $serendipity['POST']['authorname'] = trim($serendipity['POST']['authorname']);
             if (!isset($serendipity['POST']['title']) || strlen(trim($serendipity['POST']['title'])) <= 3) {
                 $ERRORMSG = PLUGIN_FORUM_ERR_MISSING_THREADTITLE;
             } elseif (!isset($serendipity['POST']['comment']) || strlen(trim($serendipity['POST']['comment'])) <= 3) {
                 $ERRORMSG = PLUGIN_FORUM_ERR_MISSING_MESSAGE;
             } else {
                 if (trim($serendipity['POST']['comment']) == $_SESSION['lastthreadtext']) {
                     $ERRORMSG = PLUGIN_FORUM_ERR_DOUBLE_THREAD;
                 } elseif ($_SESSION['lastposttime'] >= time() - 10) {
                     $ERRORMSG = PLUGIN_FORUM_ERR_POST_INTERVAL;
                 } else {
                     $now = time();
                     if (serendipity_userLoggedIn() && $serendipity['serendipityUserlevel'] == USERLEVEL_ADMIN) {
                         if (isset($serendipity['POST']['announcement']) && intval($serendipity['POST']['announcement']) == 1) {
                             $announce = 1;
                         } else {
                             $announce = 0;
                         }
                     } else {
                         $announce = 0;
                     }
                     $postid = DMA_forum_InsertThread(intval($serendipity['POST']['boardid']), trim($serendipity['POST']['authorname']), trim($serendipity['POST']['title']), trim($serendipity['POST']['comment']), $announce, $this->get_config('notifymail_from'), $this->get_config('notifymail_name'), $this->get_config('pageurl'), $this->get_config('admin_notify'));
                     if (serendipity_userLoggedIn() && $this->get_config('fileupload_reguser') || $this->get_config('fileupload_guest')) {
                         DMA_forum_uploadFiles($postid, $this->get_config('uploaddir'));
                         if ($this->SUCCESS <= 0) {
                             if (count($this->UPLOAD_TOOBIG) >= 1) {
                                 $ERRORMSG = PLUGIN_FORUM_ERR_FILE_TOO_BIG;
                             } elseif (count($this->UPLOAD_NOTCOPIED) >= 1) {
                                 $ERRORMSG = PLUGIN_FORUM_ERR_FILE_NOT_COPIED;
                             }
                         }
                     }
                 }
             }
         }
         if (serendipity_userLoggedIn()) {
             $POST_AUTHORNAME = $serendipity['serendipityUser'];
         } else {
             $POST_AUTHORNAME = trim($serendipity['POST']['authorname']);
         }
         $POST_TITLE = trim($serendipity['POST']['title']);
         $POST_MESSAGE = trim($serendipity['POST']['comment']);
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $_GET['boardid'] = intval($serendipity['POST']['boardid']);
             $_GET['action'] = "newthread";
         } else {
             $_GET['boardid'] = intval($serendipity['POST']['boardid']);
             unset($_GET['action']);
         }
     }
     // GET part
     if (isset($_GET['replyto']) && !isset($_GET['edit']) && !isset($_GET['delete']) && (isset($_GET['boardid']) && intval($_GET['boardid']) >= 1) && (isset($_GET['threadid']) && intval($_GET['threadid']) >= 1)) {
         // replyform
         $filename = 'templates/replyform.tpl';
         if (!is_object($serendipity['smarty'])) {
             serendipity_smarty_init();
         }
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $serendipity['smarty']->assign('ERRORMSG', $ERRORMSG);
         }
         if (isset($_GET['quote']) && intval($_GET['quote']) >= 1) {
             $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE postid='" . intval($_GET['replyto']) . "'";
             $post = serendipity_db_query($sql);
         }
         if (!isset($POST_MESSAGE) || trim($POST_MESSAGE) == "") {
             if (isset($_GET['quote']) && intval($_GET['quote']) >= 1) {
                 $POST_MESSAGE = "[quote=" . stripslashes($post[0]['authorname']) . "]" . stripslashes($post[0]['message']) . "[/quote]\n\n";
             }
         }
         if (!isset($POST_TITLE) || trim($POST_TITLE) == "") {
             if (isset($_GET['quote']) && intval($_GET['quote']) >= 1) {
                 $POST_TITLE = "Re: " . stripslashes($post[0]['title']);
             }
         }
         if (serendipity_userLoggedIn()) {
             $POST_AUTHORNAME = $serendipity['serendipityUser'];
         }
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE threadid='" . intval($_GET['threadid']) . "'";
         $thread = serendipity_db_query($sql);
         $serendipity['smarty']->assign(array('pagetitle' => $this->get_config('pagetitle'), 'headline' => $this->get_config('headline'), 'threadtitle' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($thread[0]['title']))) : htmlspecialchars(stripslashes(trim($thread[0]['title'])), ENT_COMPAT, LANG_CHARSET), 'bgcolor2' => $this->get_config('bgcolor2'), 'ACTUALURL' => $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']), 'boardid' => intval($_GET['boardid']), 'threadid' => intval($_GET['threadid']), 'replyto' => intval($_GET['replyto']), 'relpath' => $this->DMA_forum_getRelPath(), 'POST_AUTHORNAME' => function_exists('serendipity_specialchars') ? serendipity_specialchars($POST_AUTHORNAME) : htmlspecialchars($POST_AUTHORNAME, ENT_COMPAT, LANG_CHARSET), 'POST_TITLE' => function_exists('serendipity_specialchars') ? serendipity_specialchars($POST_TITLE) : htmlspecialchars($POST_TITLE, ENT_COMPAT, LANG_CHARSET), 'POST_MESSAGE' => function_exists('serendipity_specialchars') ? serendipity_specialchars($POST_MESSAGE) : htmlspecialchars($POST_MESSAGE, ENT_COMPAT, LANG_CHARSET)));
         $serendipity['smarty']->assign('bbcode', BBCODE);
         if (serendipity_userLoggedIn() && $this->get_config('fileupload_reguser') || $this->get_config('fileupload_guest')) {
             $upload_max_filesize = ini_get('upload_max_filesize');
             $upload_max_filesize = preg_replace('/M/', '000000', $upload_max_filesize);
             $MAX_FILE_SIZE = intval($upload_max_filesize);
             $MAX_SIZE_PER_FILE = $MAX_FILE_SIZE / 1000000 . " MB";
             $max_possible = intval($this->get_config('max_simultaneous_fileuploads'));
             if ($max_possible >= intval($this->get_config('max_files_per_post'))) {
                 $max_possible = intval($this->get_config('max_files_per_post'));
             }
             if (serendipity_userLoggedIn()) {
                 $authorid = intval($serendipity['authorid']);
             } else {
                 $authorid = 0;
             }
             $sql = "SELECT COUNT(*) FROM {$serendipity['dbPrefix']}dma_forum_uploads WHERE authorid = '" . $authorid . "'";
             $uploadnum = serendipity_db_query($sql);
             $uploaduserrest = intval($this->get_config('max_files_per_user')) - intval($uploadnum[0][0]);
             if ($max_possible >= $uploaduserrest) {
                 $max_possible = $uploaduserrest;
             }
             $uploads = array();
             for ($x = 0; $x < $max_possible; $x++) {
                 $uploads[] = $x + 1;
             }
             $serendipity['smarty']->assign(array('uploadform' => true, 'MAX_FILE_SIZE' => $MAX_FILE_SIZE, 'MAX_SIZE_PER_FILE' => $MAX_SIZE_PER_FILE, 'uploads' => $uploads, 'uploads_post_left' => intval($this->get_config('max_files_per_post')), 'uploads_user_left' => $uploaduserrest));
         }
         if ($this->get_config('use_captchas')) {
             $serendipity['smarty']->assign('commentform_entry', array('timestamp' => 1));
         }
     } elseif (!isset($_GET['replyto']) && isset($_GET['edit']) && !isset($_GET['delete']) && (isset($_GET['boardid']) && intval($_GET['boardid']) >= 1) && (isset($_GET['threadid']) && intval($_GET['threadid']) >= 1)) {
         // editform
         $filename = 'templates/editform.tpl';
         if (!is_object($serendipity['smarty'])) {
             serendipity_smarty_init();
         }
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE threadid='" . intval($_GET['threadid']) . "'";
         $thread = serendipity_db_query($sql);
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE postid='" . intval($_GET['edit']) . "'";
         $post = serendipity_db_query($sql);
         if (serendipity_userLoggedIn() && ($serendipity['serendipityUser'] == $post[0]['authorname'] && $serendipity['authorid'] == $post[0]['authorid'] || $serendipity['serendipityUserlevel'] == 255)) {
             $serendipity['smarty']->assign('CANEDIT', true);
         } else {
             $ERRORMSG = PLUGIN_FORUM_ERR_EDIT_NOT_ALLOWED;
         }
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $serendipity['smarty']->assign('ERRORMSG', $ERRORMSG);
         }
         $serendipity['smarty']->assign(array('pagetitle' => $this->get_config('pagetitle'), 'headline' => $this->get_config('headline'), 'threadtitle' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($thread[0]['title']))) : htmlspecialchars(stripslashes(trim($thread[0]['title'])), ENT_COMPAT, LANG_CHARSET), 'bgcolor2' => $this->get_config('bgcolor2'), 'ACTUALURL' => $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;page=" . intval($_GET['page']), 'boardid' => intval($_GET['boardid']), 'threadid' => intval($_GET['threadid']), 'relpath' => $this->DMA_forum_getRelPath(), 'page' => intval($_GET['page']), 'edit' => intval($_GET['edit']), 'POST_AUTHORNAME' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($post[0]['authorname']))) : htmlspecialchars(stripslashes(trim($post[0]['authorname'])), ENT_COMPAT, LANG_CHARSET), 'POST_TITLE' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($post[0]['title']))) : htmlspecialchars(stripslashes(trim($post[0]['title'])), ENT_COMPAT, LANG_CHARSET), 'POST_MESSAGE' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($post[0]['message']))) : htmlspecialchars(stripslashes(trim($post[0]['message'])), ENT_COMPAT, LANG_CHARSET)));
         $serendipity['smarty']->assign('bbcode', BBCODE);
         if (serendipity_userLoggedIn() && $serendipity['serendipityUserlevel'] == USERLEVEL_ADMIN) {
             $serendipity['smarty']->assign('announcement', true);
             if (intval($thread[0]['announce']) == 1) {
                 $serendipity['smarty']->assign('checked', " checked");
             } else {
                 $serendipity['smarty']->assign('checked', "");
             }
         }
         if (serendipity_userLoggedIn() && $this->get_config('fileupload_reguser') || $this->get_config('fileupload_guest')) {
             $upload_max_filesize = ini_get('upload_max_filesize');
             $upload_max_filesize = preg_replace('/M/', '000000', $upload_max_filesize);
             $MAX_FILE_SIZE = intval($upload_max_filesize);
             $MAX_SIZE_PER_FILE = $MAX_FILE_SIZE / 1000000 . " MB";
             $max_possible = intval($this->get_config('max_simultaneous_fileuploads'));
             if ($max_possible >= intval($this->get_config('max_files_per_post'))) {
                 $max_possible = intval($this->get_config('max_files_per_post'));
             }
             if (serendipity_userLoggedIn()) {
                 $authorid = intval($serendipity['authorid']);
             } else {
                 $authorid = 0;
             }
             $sql = "SELECT COUNT(*) FROM {$serendipity['dbPrefix']}dma_forum_uploads WHERE authorid = '" . $authorid . "'";
             $uploadnum = serendipity_db_query($sql);
             $uploaduserrest = intval($this->get_config('max_files_per_user')) - intval($uploadnum[0][0]);
             if ($max_possible >= $uploaduserrest) {
                 $max_possible = $uploaduserrest;
             }
             $sql = "SELECT COUNT(*) FROM {$serendipity['dbPrefix']}dma_forum_uploads WHERE postid = '" . intval($_GET['edit']) . "'";
             $postuploadnum = serendipity_db_query($sql);
             $uploadpostrest = intval($this->get_config('max_files_per_post')) - intval($postuploadnum[0][0]);
             if ($max_possible >= $uploadpostrest) {
                 $max_possible = $uploadpostrest;
             }
             $uploads = array();
             for ($x = 0; $x < $max_possible; $x++) {
                 $uploads[] = $x + 1;
             }
             $serendipity['smarty']->assign(array('uploadform' => true, 'MAX_FILE_SIZE' => $MAX_FILE_SIZE, 'MAX_SIZE_PER_FILE' => $MAX_SIZE_PER_FILE, 'uploads' => $uploads, 'uploads_post_left' => $uploadpostrest, 'uploads_user_left' => $uploaduserrest));
         }
     } elseif (!isset($_GET['replyto']) && !isset($_GET['edit']) && isset($_GET['delete']) && (isset($_GET['boardid']) && intval($_GET['boardid']) >= 1) && (isset($_GET['threadid']) && intval($_GET['threadid']) >= 1)) {
         // deleteform
         $filename = 'templates/deleteform.tpl';
         if (!is_object($serendipity['smarty'])) {
             serendipity_smarty_init();
         }
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE threadid='" . intval($_GET['threadid']) . "'";
         $thread = serendipity_db_query($sql);
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE postid='" . intval($_GET['delete']) . "'";
         $post = serendipity_db_query($sql);
         if (serendipity_userLoggedIn() && $serendipity['serendipityUserlevel'] == 255) {
             $serendipity['smarty']->assign('CANDELETE', true);
         } else {
             $ERRORMSG = PLUGIN_FORUM_ERR_DELETE_NOT_ALLOWED;
         }
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $serendipity['smarty']->assign('ERRORMSG', $ERRORMSG);
         }
         if ($this->get_config('apply_markup')) {
             $temp_array = array('body' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($post[0]['message']))) : htmlspecialchars(stripslashes(trim($post[0]['message'])), ENT_COMPAT, LANG_CHARSET));
             serendipity_plugin_api::hook_event('frontend_display', $temp_array);
             $post['message'] = trim($temp_array['body']);
         } else {
             $post['message'] = nl2br(function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($post[0]['message']))) : htmlspecialchars(stripslashes(trim($post[0]['message'])), ENT_COMPAT, LANG_CHARSET));
         }
         $serendipity['smarty']->assign(array('pagetitle' => $this->get_config('pagetitle'), 'headline' => $this->get_config('headline'), 'threadtitle' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($thread[0]['title']))) : htmlspecialchars(stripslashes(trim($thread[0]['title'])), ENT_COMPAT, LANG_CHARSET), 'bgcolor1' => $this->get_config('bgcolor1'), 'bgcolor2' => $this->get_config('bgcolor2'), 'ACTUALURL' => $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;page=" . intval($_GET['page']), 'boardid' => intval($_GET['boardid']), 'threadid' => intval($_GET['threadid']), 'page' => intval($_GET['page']), 'delete' => intval($_GET['delete']), 'POST_AUTHORNAME' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($post[0]['authorname']))) : htmlspecialchars(stripslashes(trim($post[0]['authorname'])), ENT_COMPAT, LANG_CHARSET), 'POST_DATE' => date($this->get_config('dateformat') . " " . $this->get_config('timeformat'), $post[0]['postdate']), 'POST_TITLE' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($post[0]['title']))) : htmlspecialchars(stripslashes(trim($post[0]['title'])), ENT_COMPAT, LANG_CHARSET), 'POST_MESSAGE' => $post['message'], 'relpath' => $this->DMA_forum_getRelPath()));
     } elseif (isset($_GET['action']) && trim($_GET['action']) == "close") {
         $sql = "UPDATE {$serendipity['dbPrefix']}dma_forum_threads SET\n                            flag = '1'\n                    WHERE    threadid = '" . intval($_GET['threadid']) . "'";
         serendipity_db_query($sql);
     } elseif (isset($_GET['action']) && trim($_GET['action']) == "reopen") {
         $sql = "UPDATE {$serendipity['dbPrefix']}dma_forum_threads SET\n                            flag = '0'\n                    WHERE    threadid = '" . intval($_GET['threadid']) . "'";
         serendipity_db_query($sql);
     }
     if (isset($_GET['delfile']) && intval($_GET['delfile']) >= 1) {
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_uploads WHERE uploadid = '" . intval($_GET['delfile']) . "'";
         $upload = serendipity_db_query($sql);
         if (serendipity_userLoggedIn() && ($serendipity['serendipityUserlevel'] == USERLEVEL_ADMIN || intval($upload[0]['authorid']) == intval($serendipity['authorid']))) {
             @unlink($this->get_config('uploaddir') . "/" . $upload[0]['sysfilename']);
             $q = "DELETE FROM {$serendipity['dbPrefix']}dma_forum_uploads WHERE uploadid = '" . intval($_GET['delfile']) . "'";
             $sql = serendipity_db_query($q);
         }
     }
     if (isset($_GET['subscribe']) && intval($_GET['subscribe']) == 1 && isset($_GET['threadid'])) {
         if (serendipity_userLoggedIn()) {
             $sql = "SELECT notifymails FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE threadid='" . intval($_GET['threadid']) . "'";
             $notifymails = serendipity_db_query($sql);
             if (trim($thread[0]['notifymails']) != "") {
                 $NOTIFYARRAY = unserialize(stripslashes(trim($thread[0]['notifymails'])));
             } else {
                 $NOTIFYARRAY = array();
             }
             $NOTIFYARRAY[] = trim($serendipity['email']);
             $updatearray = trim(serialize($NOTIFYARRAY));
             $sql = "UPDATE {$serendipity['dbPrefix']}dma_forum_threads SET notifymails = '" . $updatearray . "' WHERE threadid='" . intval($_GET['threadid']) . "'";
             serendipity_db_query($sql);
         }
     } elseif (isset($_GET['unsubscribe']) && intval($_GET['unsubscribe']) == 1 && isset($_GET['threadid'])) {
         if (serendipity_userLoggedIn()) {
             $sql = "SELECT notifymails FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE threadid='" . intval($_GET['threadid']) . "'";
             $notifymails = serendipity_db_query($sql);
             if (trim($thread[0]['notifymails']) != "") {
                 $NOTIFYARRAY = unserialize(stripslashes(trim($thread[0]['notifymails'])));
             } else {
                 $NOTIFYARRAY = array();
             }
             $newarray = DMA_forum_array_remove($NOTIFYARRAY, trim($serendipity['email']));
             if (count($newarray) <= 0) {
                 $updatearray = "";
             } else {
                 $updatearray = trim(serialize($NOTIFYARRAY));
             }
             $sql = "UPDATE {$serendipity['dbPrefix']}dma_forum_threads SET notifymails = '" . $updatearray . "' WHERE threadid='" . intval($_GET['threadid']) . "'";
             serendipity_db_query($sql);
         }
     }
     /** Jahr des getrigen Tages */
     $yesterday_year = intval(date("Y", time() - 86400));
     /** Monat des getrigen Tages */
     $yesterday_month = intval(date("n", time() - 86400));
     /** Tageszahl des getrigen Tages */
     $yesterday_day = intval(date("j", time() - 86400));
     /** Letzter Timestamp des getrigen Tages (23:59:59 Uhr) */
     $yesterday_lasttstamp = mktime(23, 59, 59, $yesterday_month, $yesterday_day, $yesterday_year);
     /** Erster Timestamp des getrigen Tages (00:00:00 Uhr) */
     $yesterday_firsttstamp = mktime(0, 0, 0, $yesterday_month, $yesterday_day, $yesterday_year);
     if ((!isset($_GET['boardid']) || intval($_GET['boardid']) <= 0) && (!isset($_GET['replyto']) && !isset($_GET['edit']) && !isset($_GET['delete']) && !isset($_GET['quote']))) {
         // BOARDLIST
         $filename = 'templates/boardlist.tpl';
         if (!is_object($serendipity['smarty'])) {
             serendipity_smarty_init();
         }
         $serendipity['smarty']->assign('pagetitle', $this->get_config('pagetitle'));
         $serendipity['smarty']->assign('headline', $this->get_config('headline'));
         $BOARDLIST = "";
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_boards ORDER BY sortorder";
         $boards = serendipity_db_query($sql);
         $mainpage_link = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "\">" . $this->get_config('pagetitle') . "</a>";
         $serendipity['smarty']->assign('MAINPAGE', $mainpage_link);
         if (is_array($boards) && count($boards) >= 1) {
             $serendipity['smarty']->assign('bgcolor_head', $this->get_config('bgcolor_head'));
             for ($a = 0, $b = count($boards); $a < $b; $a++) {
                 if (intval($boards[$a]['threads']) >= 1) {
                     if (intval($boards[$a]['lastposttime']) >= intval($yesterday_lasttstamp) + 1) {
                         $lastpost = "<span style=\"color:" . $this->get_config('color_today') . ";font-weight:bolder\">" . PLUGIN_FORUM_TODAY . " " . date($this->get_config('timeformat'), $boards[$a]['lastposttime']) . "</span><br />";
                     } elseif (intval($boards[$a]['lastposttime']) <= intval($yesterday_lasttstamp) && intval($boards[$a]['lastposttime']) >= intval($yesterday_firsttstamp)) {
                         $lastpost = "<span style=\"color:" . $this->get_config('color_yesterday') . "\">" . PLUGIN_FORUM_YESTERDAY . " " . date($this->get_config('timeformat'), $boards[$a]['lastposttime']) . "</span><br />";
                     } else {
                         $lastpost = date($this->get_config('dateformat') . " " . $this->get_config('timeformat'), $boards[$a]['lastposttime']) . "<br />";
                     }
                     $lastpost .= (function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes($boards[$a]['lastauthorname'])) : htmlspecialchars(stripslashes($boards[$a]['lastauthorname']), ENT_COMPAT, LANG_CHARSET)) . " ";
                     $sql = "SELECT COUNT(*) FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE threadid='" . intval($boards[$a]['lastthreadid']) . "'";
                     $postnum = serendipity_db_query($sql);
                     $page = ceil(intval($postnum[0][0]) / intval($this->get_config('itemsperpage')));
                     $lastpost .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($boards[$a]['boardid']) . "&amp;threadid=" . intval($boards[$a]['lastthreadid']) . "&amp;page=" . $page . "#" . intval($boards[$a]['lastpostid']) . "\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/icon_latest_reply.gif\" width=\"18\" height=\"9\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_DIRECTGOTOPOST . "\" title=\"" . PLUGIN_FORUM_ALT_DIRECTGOTOPOST . "\" /></a>";
                     $boards[$a]['lastpost'] = $lastpost;
                 } else {
                     $boards[$a]['lastpost'] = PLUGIN_FORUM_NO_ENTRIES;
                 }
                 if ($thiscolor == $this->get_config('bgcolor2')) {
                     $thiscolor = $this->get_config('bgcolor1');
                 } else {
                     $thiscolor = $this->get_config('bgcolor2');
                 }
                 $boards[$a]['color'] = $thiscolor;
                 $boards[$a]['name'] = function_exists('serendipity_specialchars') ? serendipity_specialchars($boards[$a]['name']) : htmlspecialchars($boards[$a]['name'], ENT_COMPAT, LANG_CHARSET);
                 $temp_array = array('body' => function_exists('serendipity_specialchars') ? serendipity_specialchars(trim(stripslashes($boards[$a]['description']))) : htmlspecialchars(trim(stripslashes($boards[$a]['description'])), ENT_COMPAT, LANG_CHARSET));
                 serendipity_plugin_api::hook_event('frontend_display', $temp_array);
                 $boards[$a]['description'] = trim($temp_array['body']);
             }
             $serendipity['smarty']->assign(array('pagetitle' => $this->get_config('pagetitle'), 'headline' => $this->get_config('headline'), 'pageurl' => $this->get_config('pageurl'), 'boards' => $boards));
         } else {
             $noboards .= PLUGIN_FORUM_NO_BOARDS;
             $serendipity['smarty']->assign('noboards', $noboards);
         }
     } elseif (intval($_GET['boardid']) >= 1 && (!isset($_GET['threadid']) || intval($_GET['threadid']) <= 0) && (!isset($_GET['replyto']) && !isset($_GET['edit']) && !isset($_GET['delete']) && !isset($_GET['quote']))) {
         // New thread
         if (isset($_GET['action']) && trim($_GET['action']) == "newthread") {
             $filename = 'templates/newthread.tpl';
             if (!is_object($serendipity['smarty'])) {
                 serendipity_smarty_init();
             }
             $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_boards WHERE boardid='" . intval($_GET['boardid']) . "'";
             $board = serendipity_db_query($sql);
             if (serendipity_userLoggedIn()) {
                 $POST_AUTHORNAME = $serendipity['serendipityUser'];
             }
             if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
                 $serendipity['smarty']->assign('ERRORMSG', $ERRORMSG);
             }
             $serendipity['smarty']->assign('bbcode', BBCODE);
             $serendipity['smarty']->assign(array('pagetitle' => $this->get_config('pagetitle'), 'headline' => $this->get_config('headline'), 'bgcolor2' => $this->get_config('bgcolor2'), 'ACTUALURL' => $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']), 'boardid' => intval($_GET['boardid']), 'POST_AUTHORNAME' => function_exists('serendipity_specialchars') ? serendipity_specialchars($POST_AUTHORNAME) : htmlspecialchars($POST_AUTHORNAME, ENT_COMPAT, LANG_CHARSET), 'POST_TITLE' => function_exists('serendipity_specialchars') ? serendipity_specialchars($POST_TITLE) : htmlspecialchars($POST_TITLE, ENT_COMPAT, LANG_CHARSET), 'POST_MESSAGE' => function_exists('serendipity_specialchars') ? serendipity_specialchars($POST_MESSAGE) : htmlspecialchars($POST_MESSAGE, ENT_COMPAT, LANG_CHARSET), 'relpath' => $this->DMA_forum_getRelPath(), 'newthreadurl' => $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;action=newthread&amp;boardid=" . intval($_GET['boardid']), 'boardname' => function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes(trim($board[0]['name']))) : htmlspecialchars(stripslashes(trim($board[0]['name'])), ENT_COMPAT, LANG_CHARSET)));
             if (serendipity_userLoggedIn() && $serendipity['serendipityUserlevel'] == USERLEVEL_ADMIN) {
                 $serendipity['smarty']->assign('announcement', true);
             }
             if (serendipity_userLoggedIn() && $this->get_config('fileupload_reguser') || $this->get_config('fileupload_guest')) {
                 $upload_max_filesize = ini_get('upload_max_filesize');
                 $upload_max_filesize = preg_replace('/M/', '000000', $upload_max_filesize);
                 $MAX_FILE_SIZE = intval($upload_max_filesize);
                 $MAX_SIZE_PER_FILE = $MAX_FILE_SIZE / 1000000 . " MB";
                 $max_possible = intval($this->get_config('max_simultaneous_fileuploads'));
                 if ($max_possible >= intval($this->get_config('max_files_per_post'))) {
                     $max_possible = intval($this->get_config('max_files_per_post'));
                 }
                 if (serendipity_userLoggedIn()) {
                     $authorid = intval($serendipity['authorid']);
                 } else {
                     $authorid = 0;
                 }
                 $sql = "SELECT COUNT(*) FROM {$serendipity['dbPrefix']}dma_forum_uploads WHERE authorid = '" . $authorid . "'";
                 $uploadnum = serendipity_db_query($sql);
                 $uploaduserrest = intval($this->get_config('max_files_per_user')) - intval($uploadnum[0][0]);
                 if ($max_possible >= $uploaduserrest) {
                     $max_possible = $uploaduserrest;
                 }
                 $uploads = array();
                 for ($x = 0; $x < $max_possible; $x++) {
                     $uploads[] = $x + 1;
                 }
                 $serendipity['smarty']->assign(array('uploadform' => true, 'MAX_FILE_SIZE' => $MAX_FILE_SIZE, 'MAX_SIZE_PER_FILE' => $MAX_SIZE_PER_FILE, 'uploads' => $uploads, 'uploads_post_left' => intval($this->get_config('max_files_per_post')), 'uploads_user_left' => $uploaduserrest));
             }
             if ($this->get_config('use_captchas')) {
                 $serendipity['smarty']->assign('commentform_entry', array('timestamp' => 1));
             }
         } else {
             // THREADLIST
             $filename = 'templates/threadlist.tpl';
             if (!is_object($serendipity['smarty'])) {
                 serendipity_smarty_init();
             }
             $serendipity['smarty']->assign('pagetitle', $this->get_config('pagetitle'));
             $serendipity['smarty']->assign('headline', $this->get_config('headline'));
             $serendipity['smarty']->assign('relpath', $this->DMA_forum_getRelPath());
             $serendipity['smarty']->assign('newthreadurl', $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;action=newthread&amp;boardid=" . intval($_GET['boardid']));
             $THREADLIST = "";
             $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_boards WHERE boardid='" . intval($_GET['boardid']) . "'";
             $board = serendipity_db_query($sql);
             // paging
             if (isset($_GET['page']) && intval($_GET['page']) >= 1) {
                 $page = intval($_GET['page']);
             } else {
                 $page = 1;
             }
             $postnum = intval($board[0]['threads']);
             $maxpages = ceil($postnum / intval($this->get_config('itemsperpage')));
             if ($maxpages >= 2) {
                 if (!isset($page) or trim($page) == "" or $page <= 0) {
                     $page = 1;
                 }
                 if ($page > $maxpages) {
                     $page = $maxpages;
                 }
                 $multiplicator = $page * intval($this->get_config('itemsperpage')) - intval($this->get_config('itemsperpage'));
                 if (!isset($page) or $page == 1) {
                     $LIMIT = serendipity_db_limit(0, intval($this->get_config('itemsperpage')));
                 } else {
                     $LIMIT = serendipity_db_limit($multiplicator, intval($this->get_config('itemsperpage')));
                 }
                 $LIMIT = serendipity_db_limit_sql($LIMIT);
                 $paging = "";
                 if ($page > 1) {
                     $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;page=1\">1</a>&nbsp;";
                     $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;page=" . ($page - 10) . "\">&lt;&lt;</a>&nbsp;";
                     $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;page=" . ($page - 1) . "\">&lt;</a>&nbsp;&nbsp;";
                 } elseif ($page == 1) {
                     $paging .= "[&nbsp;1&nbsp;]&nbsp;";
                 }
                 if ($maxpages >= 2) {
                     for ($b = $page - 5; $b <= $page + 5; $b++) {
                         if ($b > 1 and $b < $maxpages) {
                             if ($b == $page) {
                                 $paging .= "[&nbsp;" . $b . "&nbsp;]&nbsp;";
                             } elseif ($b >= $maxpages) {
                             } else {
                                 $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;page=" . $b . "\">" . $b . "</a>&nbsp;";
                             }
                         }
                     }
                 }
                 if ($page < $maxpages) {
                     $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;page=" . ($page + 1) . "\">&gt;</a>&nbsp;";
                     $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;page=" . ($page + 10) . "\">&gt;&gt;</a>&nbsp;";
                     $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;page=" . $maxpages . "\">" . $maxpages . "</a>&nbsp;";
                 } elseif ($page == $maxpages and $page != 1) {
                     $paging .= "[&nbsp;" . $maxpages . "&nbsp;]";
                 }
                 if (isset($paging) && trim($paging) != "") {
                     $serendipity['smarty']->assign('paging', $paging);
                 }
             } else {
                 $LIMIT = "";
             }
             $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE boardid='" . intval($_GET['boardid']) . "' ORDER BY announce DESC, lastposttime DESC" . $LIMIT;
             $threads = serendipity_db_query($sql);
             $mainpage_link = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "\">" . $this->get_config('pagetitle') . "</a>";
             $threadlist_link = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "\">" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($board[0]['name']) : htmlspecialchars($board[0]['name'], ENT_COMPAT, LANG_CHARSET)) . "</a>";
             $serendipity['smarty']->assign('MAINPAGE', $mainpage_link);
             $serendipity['smarty']->assign('THREADLIST', $threadlist_link);
             if (is_array($threads) && count($threads) >= 1) {
                 $serendipity['smarty']->assign('bgcolor_head', $this->get_config('bgcolor_head'));
                 for ($a = 0, $b = count($threads); $a < $b; $a++) {
                     if (intval($threads[$a]['lastpostid']) >= 1) {
                         if (intval($threads[$a]['lastposttime']) >= intval($yesterday_lasttstamp) + 1) {
                             $lastpost = "<span style=\"color:" . $this->get_config('color_today') . ";font-weight:bolder\">" . PLUGIN_FORUM_TODAY . " " . date($this->get_config('timeformat'), $threads[$a]['lastposttime']) . "</span><br />";
                         } elseif (intval($threads[$a]['lastposttime']) <= intval($yesterday_lasttstamp) && intval($threads[$a]['lastposttime']) >= intval($yesterday_firsttstamp)) {
                             $lastpost = "<span style=\"color:" . $this->get_config('color_yesterday') . "\">" . PLUGIN_FORUM_YESTERDAY . " " . date($this->get_config('timeformat'), $threads[$a]['lastposttime']) . "</span><br />";
                         } else {
                             $lastpost = date($this->get_config('dateformat') . " " . $this->get_config('timeformat'), $threads[$a]['lastposttime']) . "<br />";
                         }
                         $lastpost .= (function_exists('serendipity_specialchars') ? serendipity_specialchars(stripslashes($threads[$a]['lastauthorname'])) : htmlspecialchars(stripslashes($threads[$a]['lastauthorname']), ENT_COMPAT, LANG_CHARSET)) . " ";
                         $sql = "SELECT COUNT(*) FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE threadid='" . intval($threads[$a]['threadid']) . "'";
                         $postnum = serendipity_db_query($sql);
                         $page = ceil(intval($postnum[0][0]) / intval($this->get_config('itemsperpage')));
                         $lastpost .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($threads[$a]['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=" . $page . "#" . intval($threads[$a]['lastpostid']) . "\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/icon_latest_reply.gif\" width=\"18\" height=\"9\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_DIRECTGOTOPOST . "\" title=\"" . PLUGIN_FORUM_ALT_DIRECTGOTOPOST . "\" /></a>";
                     } else {
                         $lastpost = PLUGIN_FORUM_NO_REPLIES;
                     }
                     $threads[$a]['lastpost'] = $lastpost;
                     if ($thiscolor == $this->get_config('bgcolor2')) {
                         $thiscolor = $this->get_config('bgcolor1');
                     } else {
                         $thiscolor = $this->get_config('bgcolor2');
                     }
                     $threads[$a]['color'] = $thiscolor;
                     $threads[$a]['title'] = function_exists('serendipity_specialchars') ? serendipity_specialchars($threads[$a]['title']) : htmlspecialchars($threads[$a]['title'], ENT_COMPAT, LANG_CHARSET);
                     if (intval($threads[$a]['announce']) == 1 && intval($threads[$a + 1]['announce']) != 1) {
                         $threads[$a]['trenner'] = true;
                     } else {
                         $threads[$a]['trenner'] = false;
                     }
                     if (intval($threads[$a]['announce']) == 1) {
                         $threads[$a]['icon'] = $THREAD_UNREAD_ANNOUNCEMENT;
                         if (isset($READARRAY[intval($threads[$a]['threadid'])]) && intval($READARRAY[intval($threads[$a]['threadid'])]) >= intval($threads[$a]['lastposttime'])) {
                             $threads[$a]['icon'] = $THREAD_READ_ANNOUNCEMENT;
                         }
                     } else {
                         if (intval($threads[$a]['replies']) >= 15) {
                             $threads[$a]['icon'] = $THREAD_HUGE_UNREAD;
                         } else {
                             $threads[$a]['icon'] = $THREAD_UNREAD;
                         }
                         if (isset($READARRAY[intval($threads[$a]['threadid'])]) && intval($READARRAY[intval($threads[$a]['threadid'])]) >= intval($threads[$a]['lastposttime'])) {
                             if (intval($threads[$a]['replies']) >= 15) {
                                 $threads[$a]['icon'] = $THREAD_HUGE_READ;
                             } else {
                                 $threads[$a]['icon'] = $THREAD_READ;
                             }
                         }
                     }
                     $paging = "";
                     $sql = "SELECT COUNT(*) FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE threadid='" . intval($threads[$a]['threadid']) . "'";
                     $postnum = serendipity_db_query($sql);
                     $maxpages = ceil(intval($postnum[0][0]) / intval($this->get_config('itemsperpage')));
                     if ($maxpages >= 2) {
                         $paging = PLUGIN_FORUM_PAGES . ": ";
                         if ($maxpages <= 10) {
                             $pages = "";
                             for ($c = 0; $c < $maxpages; $c++) {
                                 if ($pages != "") {
                                     $pages .= ",&nbsp;";
                                 }
                                 $pages .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=" . ($c + 1) . "\">" . ($c + 1) . "</a>";
                             }
                             $paging .= $pages;
                         } elseif ($maxpages <= 20) {
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=1\">1</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=2\">2</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=3\">3</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=4\">4</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=5\">5</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=10\">10</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=" . $maxpages . "\">" . $maxpages . "</a>";
                         } elseif ($maxpages <= 50) {
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=1\">1</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=2\">2</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=3\">3</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=4\">4</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=10\">10</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=20\">20</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=" . $maxpages . "\">" . $maxpages . "</a>";
                         } else {
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=1\">1</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=2\">2</a>,&nbsp;";
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=3\">3</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=10\">10</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=20\">20</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=50\">50</a>";
                             $paging .= "... <a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($threads[$a]['threadid']) . "&amp;page=" . $maxpages . "\">" . $maxpages . "</a>";
                         }
                     }
                     if ($paging != "") {
                         $threads[$a]['paging'] = $paging;
                     }
                 }
                 $serendipity['smarty']->assign(array('pagetitle' => $this->get_config('pagetitle'), 'headline' => $this->get_config('headline'), 'pageurl' => $this->get_config('pageurl'), 'threads' => $threads));
             } else {
                 $nothreads .= PLUGIN_FORUM_NO_THREADS;
                 $serendipity['smarty']->assign('nothreads', $nothreads);
             }
         }
     } elseif (intval($_GET['boardid']) >= 1 && intval($_GET['threadid']) >= 1 && (!isset($_GET['replyto']) && !isset($_GET['edit']) && !isset($_GET['delete']) && !isset($_GET['quote']))) {
         // POSTS
         $filename = 'templates/postlist.tpl';
         if (!is_object($serendipity['smarty'])) {
             serendipity_smarty_init();
         }
         $serendipity['smarty']->assign('pagetitle', $this->get_config('pagetitle'));
         $serendipity['smarty']->assign('headline', $this->get_config('headline'));
         if (isset($ERRORMSG) && trim($ERRORMSG) != "") {
             $serendipity['smarty']->assign('ERRORMSG', $ERRORMSG);
         }
         $q = "UPDATE {$serendipity['dbPrefix']}dma_forum_threads SET views = views+1 WHERE threadid = '" . intval($_GET['threadid']) . "'";
         serendipity_db_query($q);
         // Set the cookie for threadicon (read/unread)
         $cookie = array('setthreadcookie' => intval($_GET['threadid']));
         serendipity_plugin_api::hook_event('external_plugin', $cookie);
         $POSTLIST = "";
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_boards WHERE boardid='" . intval($_GET['boardid']) . "'";
         $board = serendipity_db_query($sql);
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_threads WHERE threadid='" . intval($_GET['threadid']) . "'";
         $thread = serendipity_db_query($sql);
         $mainpage_link = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "\">" . $this->get_config('pagetitle') . "</a>";
         $threadlist_link = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "\">" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($board[0]['name']) : htmlspecialchars($board[0]['name'], ENT_COMPAT, LANG_CHARSET)) . "</a>";
         $posts_link = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "\">" . (function_exists('serendipity_specialchars') ? serendipity_specialchars($thread[0]['title']) : htmlspecialchars($thread[0]['title'], ENT_COMPAT, LANG_CHARSET)) . "</a>";
         $serendipity['smarty']->assign('MAINPAGE', $mainpage_link);
         $serendipity['smarty']->assign('THREADLIST', $threadlist_link);
         $serendipity['smarty']->assign('POSTS', $posts_link);
         // paging
         if (isset($_GET['page']) && intval($_GET['page']) >= 1) {
             $page = intval($_GET['page']);
         } else {
             $page = 1;
         }
         $postnum = intval($thread[0]['replies']) + 1;
         $maxpages = ceil($postnum / intval($this->get_config('itemsperpage')));
         if ($maxpages >= 2) {
             if (!isset($page) or trim($page) == "" or $page <= 0) {
                 $page = 1;
             }
             if ($page > $maxpages) {
                 $page = $maxpages;
             }
             $multiplicator = $page * intval($this->get_config('itemsperpage')) - intval($this->get_config('itemsperpage'));
             if (!isset($page) or $page == 1) {
                 $LIMIT = serendipity_db_limit(0, intval($this->get_config('itemsperpage')));
             } else {
                 $LIMIT = serendipity_db_limit($multiplicator, intval($this->get_config('itemsperpage')));
             }
             $LIMIT = serendipity_db_limit_sql($LIMIT);
             $paging = "";
             if ($page > 1) {
                 $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "&amp;page=1\">1</a>&nbsp;";
                 $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "&amp;page=" . ($page - 10) . "\">&lt;&lt;</a>&nbsp;";
                 $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "&amp;page=" . ($page - 1) . "\">&lt;</a>&nbsp;&nbsp;";
             } elseif ($page == 1) {
                 $paging .= "[&nbsp;1&nbsp;]&nbsp;";
             }
             if ($maxpages >= 2) {
                 for ($b = $page - 5; $b <= $page + 5; $b++) {
                     if ($b > 1 and $b < $maxpages) {
                         if ($b == $page) {
                             $paging .= "[&nbsp;" . $b . "&nbsp;]&nbsp;";
                         } elseif ($b >= $maxpages) {
                         } else {
                             $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "&amp;page=" . $b . "\">" . $b . "</a>&nbsp;";
                         }
                     }
                 }
             }
             if ($page < $maxpages) {
                 $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "&amp;page=" . ($page + 1) . "\">&gt;</a>&nbsp;";
                 $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "&amp;page=" . ($page + 10) . "\">&gt;&gt;</a>&nbsp;";
                 $paging .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($thread[0]['threadid']) . "&amp;page=" . $maxpages . "\">" . $maxpages . "</a>&nbsp;";
             } elseif ($page == $maxpages and $page != 1) {
                 $paging .= "[&nbsp;" . $maxpages . "&nbsp;]";
             }
             if (isset($paging) && trim($paging) != "") {
                 $serendipity['smarty']->assign('paging', $paging);
             }
         } else {
             $LIMIT = "";
         }
         $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_posts WHERE threadid='" . intval($_GET['threadid']) . "' ORDER BY postdate ASC" . $LIMIT;
         $posts = serendipity_db_query($sql);
         if (is_array($posts) && count($posts) >= 1) {
             $serendipity['smarty']->assign('threadtitle', function_exists('serendipity_specialchars') ? serendipity_specialchars($thread[0]['title']) : htmlspecialchars($thread[0]['title'], ENT_COMPAT, LANG_CHARSET));
             $serendipity['smarty']->assign('bgcolor_head', $this->get_config('bgcolor_head'));
             for ($a = 0, $b = count($posts); $a < $b; $a++) {
                 if ($thiscolor == $this->get_config('bgcolor2')) {
                     $thiscolor = $this->get_config('bgcolor1');
                 } else {
                     $thiscolor = $this->get_config('bgcolor2');
                 }
                 $posts[$a]['color'] = $thiscolor;
                 if ($this->get_config('apply_markup')) {
                     if ($this->get_config('unreg_nomarkups') && (!isset($posts[$a]['authorid']) || intval($posts[$a]['authorid']) <= 0)) {
                         $posts[$a]['message'] = nl2br(function_exists('serendipity_specialchars') ? serendipity_specialchars(trim(stripslashes($posts[$a]['message']))) : htmlspecialchars(trim(stripslashes($posts[$a]['message'])), ENT_COMPAT, LANG_CHARSET));
                     } else {
                         $temp_array = array('body' => function_exists('serendipity_specialchars') ? serendipity_specialchars(trim(stripslashes($posts[$a]['message']))) : htmlspecialchars(trim(stripslashes($posts[$a]['message'])), ENT_COMPAT, LANG_CHARSET));
                         serendipity_plugin_api::hook_event('frontend_display', $temp_array);
                         $posts[$a]['message'] = trim($temp_array['body']);
                     }
                 } else {
                     $posts[$a]['message'] = nl2br(function_exists('serendipity_specialchars') ? serendipity_specialchars(trim(stripslashes($posts[$a]['message']))) : htmlspecialchars(trim(stripslashes($posts[$a]['message'])), ENT_COMPAT, LANG_CHARSET));
                 }
                 unset($email);
                 unset($gravatar_array);
                 unset($posts[$a]['gravatar']);
                 $authorid = intval(trim($posts[$a]['authorid']));
                 if ($authorid >= 1) {
                     $sql = "SELECT email FROM {$serendipity['dbPrefix']}authors WHERE authorid = '" . $authorid . "'";
                     $email = serendipity_db_query($sql);
                     $gravatar_array = array('comment' => "", 'email' => trim($email[0][0]));
                     serendipity_plugin_api::hook_event('frontend_display', $gravatar_array);
                     if (isset($gravatar_array['comment']) && trim($gravatar_array['comment']) != "") {
                         $posts[$a]['gravatar'] = $gravatar_array['comment'];
                     }
                 }
                 $POSTBUTTONS = "";
                 if ($thread[0]['flag'] != 1) {
                     $POSTBUTTONS = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;replyto=" . $posts[$a]['postid'] . "&amp;quote=0\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/reply.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_REPLY . "\" title=\"" . PLUGIN_FORUM_ALT_REPLY . "\" /></a> &nbsp; ";
                     $POSTBUTTONS .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;replyto=" . $posts[$a]['postid'] . "&amp;quote=1\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/quote.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_QUOTE . "\" title=\"" . PLUGIN_FORUM_ALT_QUOTE . "\" /></a> &nbsp; ";
                 }
                 if (serendipity_userLoggedIn() && ($serendipity['serendipityUser'] == $posts[$a]['authorname'] && $serendipity['authorid'] == $posts[$a]['authorid'] || $serendipity['serendipityUserlevel'] == 255)) {
                     $POSTBUTTONS .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;page=" . $page . "&amp;edit=" . $posts[$a]['postid'] . "\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/edit.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_EDIT . "\" title=\"" . PLUGIN_FORUM_ALT_EDIT . "\" /></a> &nbsp; ";
                 }
                 if (serendipity_userLoggedIn() && $serendipity['serendipityUserlevel'] == 255) {
                     $POSTBUTTONS .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;page=" . $page . "&amp;delete=" . $posts[$a]['postid'] . "\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/delete.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_DELETE_POST . "\" title=\"" . PLUGIN_FORUM_ALT_DELETE_POST . "\" /></a> &nbsp; ";
                 }
                 $posts[$a]['postbuttons'] = $POSTBUTTONS;
                 $AUTHORDETAILS = "";
                 if (isset($posts[$a]['authorid']) && intval($posts[$a]['authorid']) >= 1) {
                     $AUTHORDETAILS .= "<b>" . PLUGIN_FORUM_REG_USER . "</b><br />";
                     $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_users WHERE authorid = '" . intval($posts[$a]['authorid']) . "'";
                     $userdetails = serendipity_db_query($sql);
                     if (is_array($userdetails) && count($userdetails) >= 1) {
                         $AUTHORDETAILS .= PLUGIN_FORUM_POSTS . ": " . intval($userdetails[0]['posts']) . "<br />";
                         $AUTHORDETAILS .= PLUGIN_FORUM_VISITS . ": " . intval($userdetails[0]['visits']) . "<br />";
                     } else {
                         $AUTHORDETAILS .= PLUGIN_FORUM_POSTS . ": 0<br />";
                         $AUTHORDETAILS .= PLUGIN_FORUM_VISITS . ": 0<br />";
                     }
                 }
                 $sql = "SELECT * FROM {$serendipity['dbPrefix']}dma_forum_uploads WHERE postid = '" . $posts[$a]['postid'] . "'";
                 $uploads = serendipity_db_query($sql);
                 if (is_array($uploads) && count($uploads) >= 1) {
                     $posts[$a]['uploads'] = true;
                     for ($y = 0, $z = count($uploads); $y < $z; $y++) {
                         $filesize = DMA_forum_calcFilesize($uploads[$y]['filesize']);
                         $mime = DMA_forum_getMime(function_exists('serendipity_specialchars') ? serendipity_specialchars(basename($uploads[$y]['realfilename'])) : htmlspecialchars(basename($uploads[$y]['realfilename']), ENT_COMPAT, LANG_CHARSET), $this->DMA_forum_getRelPath());
                         $fileicon = "<img src=\"" . $mime['ICON'] . "\" width=\"18\" height=\"20\" border=\"0\" />";
                         $content_type = $mime['TYPE'];
                         $posts[$a]['upload'][$y]['filename'] = "<a href=\"" . $serendipity['baseURL'] . ($serendipity['rewrite'] == "none" ? $serendipity['indexFile'] . "?/" : "") . "plugin/forumdl_" . intval($uploads[$y]['uploadid']) . "\">" . (function_exists('serendipity_specialchars') ? serendipity_specialchars(basename($uploads[$y]['realfilename'])) : htmlspecialchars(basename($uploads[$y]['realfilename']), ENT_COMPAT, LANG_CHARSET)) . "</a>";
                         $posts[$a]['upload'][$y]['filesize'] = $filesize;
                         $posts[$a]['upload'][$y]['fileicon'] = $fileicon;
                         $posts[$a]['upload'][$y]['filetype'] = $content_type;
                         $posts[$a]['upload'][$y]['dlcount'] = intval($uploads[$y]['dlcount']);
                         if (serendipity_userLoggedIn() && ($serendipity['serendipityUserlevel'] == USERLEVEL_ADMIN || intval($uploads[$y]['authorid']) == intval($serendipity['authorid']))) {
                             $posts[$a]['upload'][$y]['delbutton'] = "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;page=" . $page . "&amp;delfile=" . intval($uploads[$y]['uploadid']) . "#" . intval($posts[$a]['postid']) . "\">" . $DEL_FILE_BUTTON . "</a>";
                         }
                     }
                 } else {
                     $posts[$a]['uploads'] = false;
                 }
                 $posts[$a]['authordetails'] = $AUTHORDETAILS;
                 $posts[$a]['title'] = function_exists('serendipity_specialchars') ? serendipity_specialchars($posts[$a]['title']) : htmlspecialchars($posts[$a]['title'], ENT_COMPAT, LANG_CHARSET);
                 $posts[$a]['authorname'] = function_exists('serendipity_specialchars') ? serendipity_specialchars($posts[$a]['authorname']) : htmlspecialchars($posts[$a]['authorname'], ENT_COMPAT, LANG_CHARSET);
                 if (intval($posts[$a]['postdate']) >= intval($yesterday_lasttstamp) + 1) {
                     $posts[$a]['postdate'] = "<span style=\"color:" . $this->get_config('color_today') . ";font-weight:bolder\">" . PLUGIN_FORUM_TODAY . " " . date($this->get_config('timeformat'), $posts[$a]['postdate']) . "</span>";
                 } elseif (intval($posts[$a]['postdate']) <= intval($yesterday_lasttstamp) && intval($posts[$a]['postdate']) >= intval($yesterday_firsttstamp)) {
                     $posts[$a]['postdate'] = "<span style=\"color:" . $this->get_config('color_yesterday') . "\">" . PLUGIN_FORUM_YESTERDAY . " " . date($this->get_config('timeformat'), $posts[$a]['postdate']) . "</span>";
                 } else {
                     $posts[$a]['postdate'] = date($this->get_config('dateformat') . " " . $this->get_config('timeformat'), $posts[$a]['postdate']);
                 }
             }
             if (serendipity_userLoggedIn()) {
                 if (trim($thread[0]['notifymails']) != "") {
                     $NOTIFYARRAY = unserialize(stripslashes(trim($thread[0]['notifymails'])));
                 } else {
                     $NOTIFYARRAY = array();
                 }
                 if (in_array($serendipity['email'], $NOTIFYARRAY)) {
                     $serendipity['smarty']->assign('notify', 2);
                 } else {
                     $serendipity['smarty']->assign('notify', 1);
                 }
                 $subscribeurl = $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;page=" . $page . "&amp;subscribe=1";
                 $unsubscribeurl = $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;page=" . $page . "&amp;unsubscribe=1";
                 $serendipity['smarty']->assign('subscribeurl', $subscribeurl);
                 $serendipity['smarty']->assign('unsubscribeurl', $unsubscribeurl);
             }
             $serendipity['smarty']->assign(array('pagetitle' => $this->get_config('pagetitle'), 'headline' => $this->get_config('headline'), 'pageurl' => $this->get_config('pageurl'), 'posts' => $posts));
         } else {
             $noposts = PLUGIN_FORUM_NO_POSTS;
             $serendipity['smarty']->assign('noposts', $noposts);
         }
         // Display thread buttons regardless of number of posts
         $THREADBUTTONS = "";
         if (serendipity_userLoggedIn() && $serendipity['serendipityUserlevel'] == 255) {
             if ($thread[0]['flag'] == 1) {
                 $THREADBUTTONS .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;action=reopen\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/reopen.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_REOPEN . "\" title=\"" . PLUGIN_FORUM_ALT_REOPEN . "\" /></a> &nbsp; ";
             } else {
                 $THREADBUTTONS .= "<a href=\"" . $serendipity['baseURL'] . "index.php?serendipity[subpage]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;action=close\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/close.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_CLOSE . "\" title=\"" . PLUGIN_FORUM_ALT_CLOSE . "\" /></a> &nbsp; ";
             }
             $THREADBUTTONS .= "<a href=\"" . $serendipity['baseURL'] . "serendipity_admin.php?serendipity[adminModule]=event_display&serendipity[adminAction]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;action=move\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/move.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_MOVE . "\" title=\"" . PLUGIN_FORUM_ALT_MOVE . "\" /></a> &nbsp; ";
             $THREADBUTTONS .= "<a href=\"" . $serendipity['baseURL'] . "serendipity_admin.php?serendipity[adminModule]=event_display&serendipity[adminAction]=" . $this->get_config('pageurl') . "&amp;boardid=" . intval($_GET['boardid']) . "&amp;threadid=" . intval($_GET['threadid']) . "&amp;action=delete\"><img src=\"" . $this->DMA_forum_getRelPath() . "/img/delete.png\" width=\"60\" height=\"18\" border=\"0\" alt=\"" . PLUGIN_FORUM_ALT_DELETE . "\" title=\"" . PLUGIN_FORUM_ALT_DELETE . "\" /></a>";
         }
         $serendipity['smarty']->assign('THREADBUTTONS', $THREADBUTTONS);
     }
     $serendipity['smarty']->assign('plugin_eventforum_not20', $serendipity['version'][0] < 2 ? true : false);
     $filename = $filename;
     $tfile = serendipity_getTemplateFile($filename, 'serendipityPath');
     if (!$tfile || $tfile == $filename) {
         $tfile = dirname(__FILE__) . '/' . $filename;
     }
     $inclusion = $serendipity['smarty']->security_settings[INCLUDE_ANY];
     $serendipity['smarty']->security_settings[INCLUDE_ANY] = true;
     $content = $serendipity['smarty']->fetch('file:' . $tfile);
     $serendipity['smarty']->security_settings[INCLUDE_ANY] = $inclusion;
     echo $content;
 }