function generate_content(&$title)
 {
     global $serendipity;
     $title = $this->get_config('title', $this->title);
     $max_entries = $this->get_config('max_entries');
     $max_chars = $this->get_config('max_chars');
     $wordwrap = $this->get_config('wordwrap');
     $dateformat = $this->get_config('dateformat');
     if (!$max_entries || !is_numeric($max_entries) || $max_entries < 1) {
         $max_entries = 15;
     }
     if (!$max_chars || !is_numeric($max_chars) || $max_chars < 1) {
         $max_chars = 120;
     }
     if (!$wordwrap || !is_numeric($wordwrap) || $wordwrap < 1) {
         $wordwrap = 30;
     }
     if (!$dateformat || strlen($dateformat) < 1) {
         $dateformat = '%a, %d.%m.%Y %H:%M';
     }
     $viewtype = '';
     if ($this->get_config('viewmode') == 'comments') {
         $viewtype .= ' AND co.type = \'NORMAL\'';
     } elseif ($this->get_config('viewmode') == 'trackbacks') {
         $viewtype .= ' AND (co.type = \'TRACKBACK\' OR co.type = \'PINGBACK\')';
     }
     $cond = array();
     $cond['and'] = ' AND e.isdraft = \'false\' ';
     if ($this->get_config('authorid') == 'login') {
         serendipity_ACL_SQL($cond, true);
         serendipity_plugin_api::hook_event('frontend_fetchentries', $cond, array('source' => 'entries'));
     }
     $q = 'SELECT    co.body              AS comment,
                     co.timestamp         AS stamp,
                     co.author            AS user,
                     e.title              AS subject,
                     e.timestamp          AS entrystamp,
                     e.id                 AS entry_id,
                     co.id                AS comment_id,
                     co.type              AS comment_type,
                     co.url               AS comment_url,
                     co.title             AS comment_title,
                     co.email             AS comment_email
             FROM    ' . $serendipity['dbPrefix'] . 'comments AS co,
                     ' . $serendipity['dbPrefix'] . 'entries  AS e
                     ' . $cond['joins'] . '
            WHERE    e.id = co.entry_id
              AND    NOT (co.type = \'TRACKBACK\' AND co.author = \'' . serendipity_db_escape_string($serendipity['blogTitle']) . '\' AND co.title != \'\')
              AND    co.status = \'approved\'
                     ' . $viewtype . '
                     ' . $cond['and'] . '
         ORDER BY    co.timestamp DESC
         LIMIT ' . $max_entries;
     $sql = serendipity_db_query($q);
     // echo $q;
     if ($sql && is_array($sql)) {
         foreach ($sql as $key => $row) {
             if (function_exists('mb_strimwidth')) {
                 $comment = mb_strimwidth(strip_tags($row['comment']), 0, $max_chars, " [...]", LANG_CHARSET);
             } else {
                 $comments = wordwrap(strip_tags($row['comment']), $max_chars, '@@@', 1);
                 $aComment = explode('@@@', $comments);
                 $comment = $aComment[0];
                 if (count($aComment) > 1) {
                     $comment .= ' [...]';
                 }
             }
             $showurls = $this->get_config('showurls', 'trackbacks');
             $isTrackBack = $row['comment_type'] == 'TRACKBACK' || $row['comment_type'] == 'PINGBACK';
             if ($row['comment_url'] != '' && ($isTrackBack && ($showurls == 'trackbacks' || $showurls == 'all') || !$isTrackBack && ($showurls == 'comments' || $showurls == 'all'))) {
                 /* Fix invalid cases in protocoll part */
                 $row['comment_url'] = preg_replace('@^http://@i', 'http://', $row['comment_url']);
                 $row['comment_url'] = preg_replace('@^https://@i', 'https://', $row['comment_url']);
                 if (substr($row['comment_url'], 0, 7) != 'http://' && substr($row['comment_url'], 0, 8) != 'https://') {
                     $row['comment_url'] = 'http://' . $row['comment_url'];
                 }
                 $user = '******' . htmlspecialchars(strip_tags($row['comment_url'])) . '" title="' . htmlspecialchars(strip_tags($row['comment_title'])) . '">' . htmlspecialchars(strip_tags($row['user'])) . '</a>';
             } else {
                 $user = htmlspecialchars(strip_tags($row['user']));
             }
             $user = trim($user);
             if (empty($user)) {
                 $user = PLUGIN_COMMENTS_ANONYMOUS;
             }
             if (function_exists('mb_strimwidth')) {
                 $pos = 0;
                 $parts = array();
                 $enc = LANG_CHARSET;
                 $comment_len = mb_strlen($comment, $enc);
                 while ($pos < $comment_len) {
                     $part = mb_strimwidth($comment, $pos, $wordwrap, '', $enc);
                     $pos += mb_strlen($part, $enc);
                     $parts[] = $part;
                 }
                 $comment = implode("\n", $parts);
             } else {
                 $comment = wordwrap($comment, $wordwrap, "\n", 1);
             }
             $entry = array('comment' => $comment, 'email' => $row['comment_email'], 'url' => $row['comment_url'], 'author' => $row['user']);
             // Let's help the BBCOde plugin a bit:
             if (class_exists('serendipity_event_bbcode')) {
                 $entry['comment'] = preg_replace('@((\\[.*)[\\n\\r]+(.*\\]))+@imsU', '\\2\\3', $entry['comment']);
                 $entry['comment'] = preg_replace('@((\\[.+\\].*)[\\r\\n]+(.*\\[/.+\\]))+@imsU', '\\2\\3', $entry['comment']);
             }
             $addData = array('from' => 'serendipity_plugin_comments:generate_content');
             serendipity_plugin_api::hook_event('frontend_display', $entry, $addData);
             printf('<div class="plugin_comment_wrap">' . PLUGIN_COMMENTS_ABOUT . '</div>', '<div class="plugin_comment_subject"><span class="plugin_comment_author">' . $user . '</span>', ' <a class="highlight" href="' . serendipity_archiveURL($row['entry_id'], $row['subject'], 'baseURL', true, array('timestamp' => $row['entrystamp'])) . '#c' . $row['comment_id'] . '" title="' . htmlspecialchars($row['subject']) . '">' . htmlspecialchars($row['subject']) . '</a></div>' . "\n" . '<div class="plugin_comment_date">' . htmlspecialchars(serendipity_strftime($dateformat, $row['stamp'])) . '</div>' . "\n" . '<div class="plugin_comment_body">' . strip_tags($entry['comment'], '<br /><img><a>') . '</div>' . "\n\n");
         }
     }
 }
/**
 * Check all existing thumbnails if they are the right size, insert missing thumbnails
 *
 * LONG
 *
 * @access public
 * @return  int     Number of updated thumbnails
 */
function serendipity_syncThumbs($deleteThumbs = false)
{
    global $serendipity;
    $i = 0;
    $files = serendipity_fetchImages();
    $fcount = count($files);
    for ($x = 0; $x < $fcount; $x++) {
        $update = array();
        $f = serendipity_parseFileName($files[$x]);
        if (empty($f[1]) || $f[1] == $files[$x]) {
            // No extension means bad file most probably. Skip it.
            printf(SKIPPING_FILE_EXTENSION . '<br />', $files[$x]);
            continue;
        }
        $ffull = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $files[$x];
        $fthumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $f[0] . '.' . $serendipity['thumbSuffix'] . '.' . $f[1];
        $sThumb = $f[0] . '.' . $serendipity['thumbSuffix'] . '.' . $f[1];
        $fbase = basename($f[0]);
        $fdir = dirname($f[0]) . '/';
        if ($fdir == './') {
            $fdir = '';
        }
        if (!is_readable($ffull) || filesize($ffull) == 0) {
            printf(SKIPPING_FILE_UNREADABLE . '<br />', $files[$x]);
            continue;
        }
        $ft_mime = serendipity_guessMime($f[1]);
        $fdim = serendipity_getimagesize($ffull, $ft_mime);
        // If we're supposed to delete thumbs, this is the easiest place.
        if (is_readable($fthumb)) {
            if ($deleteThumbs === true) {
                if (@unlink($fthumb)) {
                    printf(DELETE_THUMBNAIL . "<br />\n", $sThumb);
                    $i++;
                }
            } else {
                if ($deleteThumbs == 'checksize') {
                    // Find existing thumbnail dimensions
                    $tdim = serendipity_getimagesize($fthumb);
                    if ($tdim['noimage']) {
                        // Delete it so it can be regenerated
                        if (@unlink($fthumb)) {
                            printf(DELETE_THUMBNAIL . "<br />\n", $sthumb);
                            $i++;
                        }
                    } else {
                        // Calculate correct thumbnail size from original image
                        $expect = serendipity_calculate_aspect_size($fdim[0], $fdim[1], $serendipity['thumbSize'], $serendipity['thumbConstraint']);
                        // Check actual thumbnail size
                        if ($tdim[0] != $expect[0] || $tdim[1] != $expect[1]) {
                            // This thumbnail is incorrect; delete it so
                            // it can be regenerated
                            if (@unlink($fthumb)) {
                                printf(DELETE_THUMBNAIL . "<br />\n", $sthumb);
                                $i++;
                            }
                        }
                    }
                }
            }
            // else the option is to keep all existing thumbs; do nothing.
        }
        // end if thumb exists
        $cond = array('and' => "WHERE name = '" . serendipity_db_escape_string($fbase) . "'\n                            " . ($fdir != '' ? "AND path = '" . serendipity_db_escape_string($fdir) . "'" : '') . "\n                            AND mime = '" . serendipity_db_escape_string($fdim['mime']) . "'");
        serendipity_ACL_SQL($cond, false, 'directory');
        $rs = serendipity_db_query("SELECT *\n                                      FROM {$serendipity['dbPrefix']}images AS i\n                                           {$cond['joins']}\n\n                                           {$cond['and']}", true, 'assoc');
        if (is_array($rs)) {
            // This image is in the database.  Check our calculated data against the database data.
            $update = array();
            // Is the width correct?
            if (isset($fdim[0]) && $rs['dimensions_width'] != $fdim[0]) {
                $update['dimensions_width'] = $fdim[0];
            }
            // Is the height correct?
            if (isset($fdim[1]) && $rs['dimensions_height'] != $fdim[1]) {
                $update['dimensions_height'] = $fdim[1];
            }
            // Is the image size correct?
            if ($rs['size'] != filesize($ffull)) {
                $update['size'] = filesize($ffull);
            }
            // Has the thumbnail suffix changed?
            $checkfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $rs['path'] . $rs['name'] . '.' . $rs['thumbnail_name'] . '.' . $rs['extension'];
            if (!file_exists($checkfile) && file_exists($fthumb)) {
                $update['thumbnail_name'] = $serendipity['thumbSuffix'];
            }
            /* Do the database update, if needed */
            if (sizeof($update) != 0) {
                printf(FOUND_FILE . '<br />', $files[$x]);
                serendipity_updateImageInDatabase($update, $rs['id']);
                $i++;
            }
        } else {
            printf(FOUND_FILE . '<br />', $files[$x]);
            serendipity_insertImageInDatabase($fbase . '.' . $f[1], $fdir, 0, filemtime($ffull));
            $i++;
        }
    }
    return $i;
}
 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";
     }
 }
/**
 * 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;
}