Example #1
0
                                        // printf('<div class="serendipity_msg_important">' . DOCUMENT_NOT_FOUND . '</div>', $uri);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
if ($track_referer) {
    serendipity_track_referrer();
}
if (!defined('NO_EXIT')) {
    $raw_data = ob_get_contents();
    ob_end_clean();
    $serendipity['smarty']->assignByRef('raw_data', $raw_data);
    if (empty($serendipity['smarty_file'])) {
        $serendipity['smarty_file'] = '404.tpl';
        $serendipity['viewtype'] = '404_5';
    }
    serendipity_gzCompression();
    $serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath'));
}
if ($global_debug) {
    /* TODO: Remove (hide) this debug */
    echo '<div id="s9y_debug" style="text-align: center; color: red; font-size: 10pt; font-weight: bold; padding: 10px">Page delivered in ' . round(microtime_float() - $time_start, 6) . ' seconds, ' . sizeof(get_included_files()) . ' files included</div>';
    echo '</div>';
}
/* vim: set sts=4 ts=4 expandtab : */
 /**
  * event hook: external_plugin
  *
  * @param   array   GET parameters
  * @param   boolean config var
  */
 function displayExternalTaglist($param, $ctaglist = false)
 {
     global $serendipity;
     $tagged_as_list = false;
     // Manually added (last) parameter 'taglist' to view tags by list for certain taglinks eg.: example.org/plugin/tag/Serendipity/Blog/Plums/taglist - both need a modified entries.tpl
     if ($ctaglist && in_array('taglist', $serendipity['uriArguments'])) {
         $param = array_map('urldecode', $param);
         $param = array_map('urldecode', $param);
         // for doubled encoded tag umlauts via searchengine backlinks
         $param = is_array($param) ? array_map('strip_tags', $param) : strip_tags($param);
         $param = array_filter($param);
         // filter out all left BOOL, NULL and EMPTY elements, which still are possible by removing XSS with strip_tags
         if (!is_object($serendipity['smarty'])) {
             serendipity_smarty_init();
         }
         if (false === serendipity_db_bool($this->get_config('show_tagcloud', 'true'))) {
             // Since this is extra stuff, we need to regular assign the subtitle header and not use $serendipity['head_subtitle'] !
             if (count($param) > 1) {
                 if (function_exists('serendipity_specialchars')) {
                     $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, implode(', ', array_map('serendipity_specialchars', $param))));
                 } else {
                     $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, implode(', ', array_map('self::callback_map', $param))));
                 }
             } else {
                 $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, self::specialchars_mapper($param[0])));
             }
         }
         $serendipity['smarty']->assign('taglist', true);
         foreach ($serendipity['uriArguments'] as $uak => $uav) {
             if ($uav == 'taglist') {
                 unset($serendipity['uriArguments'][$uak]);
             }
         }
         $tagged_as_list = true;
     }
     /* Attempt to locate hidden variables within the URI */
     foreach ($serendipity['uriArguments'] as $k => $v) {
         if ($v[0] == 'P') {
             /* Page */
             $page = substr($v, 1);
             if (is_numeric($page)) {
                 $serendipity['GET']['page'] = $page;
                 unset($serendipity['uriArguments'][$k]);
                 if ($param[count($param) - 1] == "P{$page}.html") {
                     array_pop($param);
                     // knock it off of the param array as well
                 }
             }
         }
     }
     if (count($param) == 0 || empty($param[0])) {
         $serendipity['head_subtitle'] = PLUGIN_EVENT_FREETAG_ALLTAGS;
         $this->displayTag = true;
         $param = null;
     } else {
         if (count($param) == 1) {
             $param = urldecode($param[0]);
             $param = urldecode($param);
             // for doubled encoded tag umlauts via searchengine backlinks
             $param = strip_tags($param);
             $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, self::specialchars_mapper($param));
             $emit_404 = true;
         } else {
             if (!$tagged_as_list) {
                 $param = array_map('urldecode', $param);
                 $param = array_map('urldecode', $param);
                 // for doubled encoded tag umlauts via searchengine backlinks in sprintf
             }
             $param = array_map('strip_tags', $param);
             $param = array_filter($param);
             // filter out all left BOOL, NULL and EMPTY elements, which still are possible by removing XSS with strip_tags
             if (function_exists('serendipity_specialchars')) {
                 $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, implode(', ', array_map('serendipity_specialchars', $param)));
             } else {
                 $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, implode(', ', array_map('self::callback_map', $param)));
             }
             $emit_404 = true;
         }
     }
     // for XSS secureness, while using doubled decode
     $param = is_array($param) ? array_map('strip_tags', $param) : strip_tags($param);
     if (is_array($param)) {
         array_filter($param);
         // filter out all left BOOL, NULL and EMPTY elements, which still are possible by removing XSS with strip_tags
     }
     if (function_exists('serendipity_specialchars')) {
         $param = is_array($param) ? array_map('serendipity_specialchars', $param) : serendipity_specialchars($param);
     } else {
         $param = is_array($param) ? array_map('self::callback_map', $param) : htmlspecialchars($param, ENT_COMPAT, LANG_CHARSET);
     }
     $this->tags['show'] = $param;
     $serendipity['plugin_vars']['tag'] = $param;
     if (is_array($param)) {
         @define('PLUGIN_VARS_TAG', implode(',', $param));
     } else {
         @define('PLUGIN_VARS_TAG', $param);
     }
     $serendipity['GET']['subpage'] = $eventData;
     unset($serendipity['GET']['category']);
     // No restriction should be enforced here.
     if ($tagged_as_list) {
         $serendipity['fetchLimit'] = 99;
         // do not use frontend entries pagination if count < 100 entries
     }
     include_once S9Y_INCLUDE_PATH . 'include/genpage.inc.php';
     if ($emit_404 && $this->taggedEntries !== null && $this->taggedEntries < 1) {
         @header('HTTP/1.0 404 Not found');
         @header('Status: 404 Not found');
         if (serendipity_db_bool($this->get_config('send_http_header', 'true'))) {
             @header('X-FreeTag: not found');
         }
     } else {
         if (serendipity_db_bool($this->get_config('send_http_header', 'true'))) {
             @header('X-FreeTag: ' . $this->taggedEntries);
         }
     }
     $raw_data = ob_get_contents();
     ob_end_clean();
     // the "missing" ob_start() is defined in serendipity roots index.php file
     $serendipity['smarty']->assign('raw_data', $raw_data);
     if (serendipity_db_bool($this->get_config('show_tagcloud', 'true'))) {
         $serendipity['smarty']->assign('istagcloud', true);
         // allows to remove a sidebar with a tag cloud, when using an entry cloud
         // @see changeLog - needs to change your template index.tpl sidebar condition(s), eg. {if !$istagcloud}
     }
     serendipity_gzCompression();
     $serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath'));
     @define('NO_EXIT', true);
     // RQ: Why did or do we (still) need this? (see index.php file change in 2.1-alpha2) - with 2.1 obsolet!
 }
    function event_hook($event, &$bag, &$eventData, $addData = null)
    {
        global $serendipity;
        $hooks =& $bag->get('event_hooks');
        if (isset($hooks[$event])) {
            switch ($event) {
                case 'backend_delete_entry':
                    $this->deleteTagsForEntry((int) $eventData);
                    return true;
                case 'frontend_header':
                    if (serendipity_db_bool($this->get_config('use_flash'))) {
                        echo '<script type="text/javascript" src="';
                        echo $serendipity['serendipityHTTPPath'];
                        echo 'plugins/serendipity_event_freetag/swfobject.js"></script>' . "\n";
                        echo '<script type="text/javascript">' . "\n";
                        echo 'swfobject.registerObject("tagcloud", "9.0.0", "expressInstall.swf");' . "\n";
                        echo '</script>' . "\n";
                    }
                    $this->displayMetaKeywords($serendipity['GET']['id'], $this->displayTag);
                    return true;
                case 'frontend_display:rss-2.0:per_entry':
                case 'frontend_display:rss-0.91:per_entry':
                    $eventData['display_dat'] .= $this->getFeedXmlForTags('category', $eventData['properties']['freetag_tags']);
                    return true;
                case 'frontend_display:rss-1.0:per_entry':
                case 'frontend_display:rss-0.91:per_entry':
                case 'frontend_display:atom-0.3:per_entry':
                case 'frontend_display:atom-1.0:per_entry':
                    $eventData['display_dat'] .= $this->getFeedXmlForTags('dc:subject', $eventData['properties']['freetag_tags']);
                    return true;
                case 'external_plugin':
                    $uri_parts = explode('?', str_replace(array('&amp;', '%FF'), array('&', '.'), $eventData));
                    $taglist = serendipity_db_bool($this->get_config('taglist', false));
                    $param = $taglist ? explode('/', str_replace('/taglist', '', $uri_parts[0])) : explode('/', $uri_parts[0]);
                    $plugincode = array_shift($param);
                    $tagged_as_list = false;
                    // By option or manually added blogdomain.com/plugin/taglist/Serendipity/Blog/Plums - see below
                    if ($plugincode == "taglist") {
                        $plugincode = "tags";
                    }
                    if ($plugincode == "tag" || $plugincode == "tags" || $plugincode == "freetag") {
                        // Manually added (last) parameter 'taglist" to view tags by list for certain taglinks eg. blogdomain.com/plugin/tag/Serendipity/Blog/Plums/taglist - both need a modified entries.tpl
                        if ($taglist && in_array('taglist', $serendipity['uriArguments'])) {
                            $param = array_map('urldecode', $param);
                            $param = array_map('urldecode', $param);
                            // for doubled encoded tag umlauts via searchengines backlinks
                            $param = is_array($param) ? array_map('strip_tags', $param) : strip_tags($param);
                            $param = array_filter($param);
                            // empty removed XSS by strip_tags
                            if (!is_object($serendipity['smarty'])) {
                                serendipity_smarty_init();
                                // to avoid member function assign() on a non-object error, start Smarty templating
                            }
                            if (false === serendipity_db_bool($this->get_config('show_tagcloud', true))) {
                                // Since this is extra stuff, we need to regular assign the subtitle header and not use $serendipity['head_subtitle'] !
                                if (count($param) > 1) {
                                    if (function_exists('serendipity_specialchars')) {
                                        $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('serendipity_specialchars', $param))));
                                    } else {
                                        $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('htmlspecialchars', $param))));
                                    }
                                } else {
                                    $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, function_exists('serendipity_specialchars') ? serendipity_specialchars($param[0]) : htmlspecialchars($param[0], ENT_COMPAT, LANG_CHARSET)));
                                }
                            }
                            $serendipity['smarty']->assign('taglist', true);
                            foreach ($serendipity['uriArguments'] as $uak => $uav) {
                                if ($uav == 'taglist') {
                                    unset($serendipity['uriArguments'][$uak]);
                                }
                            }
                            $tagged_as_list = true;
                        }
                        /* Attempt to locate hidden variables within the URI */
                        foreach ($serendipity['uriArguments'] as $k => $v) {
                            if ($v[0] == 'P') {
                                /* Page */
                                $page = substr($v, 1);
                                if (is_numeric($page)) {
                                    $serendipity['GET']['page'] = $page;
                                    unset($serendipity['uriArguments'][$k]);
                                    if ($param[count($param) - 1] == "P{$page}.html") {
                                        array_pop($param);
                                        // knock it off of the param array as well
                                    }
                                }
                            }
                        }
                        if (count($param) == 0 || empty($param[0])) {
                            $serendipity['head_subtitle'] = PLUGIN_EVENT_FREETAG_ALLTAGS;
                            $this->displayTag = true;
                            $param = null;
                        } else {
                            if (count($param) == 1) {
                                $param = urldecode($param[0]);
                                $param = urldecode($param);
                                // for doubled encoded tag umlauts via searchengines backlinks
                                $param = strip_tags($param);
                                $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, function_exists('serendipity_specialchars') ? serendipity_specialchars($param) : htmlspecialchars($param, ENT_COMPAT, LANG_CHARSET));
                                $emit_404 = true;
                            } else {
                                if (!$tagged_as_list) {
                                    $param = array_map('urldecode', $param);
                                    $param = array_map('urldecode', $param);
                                    // for doubled encoded tag umlauts via searchengines backlinks in sprintf
                                }
                                $param = array_map('strip_tags', $param);
                                $param = array_filter($param);
                                // empty removed XSS by strip_tags
                                if (function_exists('serendipity_specialchars')) {
                                    $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('serendipity_specialchars', $param)));
                                } else {
                                    $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('htmlspecialchars', $param)));
                                }
                                $emit_404 = true;
                            }
                        }
                        // for XSS secureness, while using doubled decode
                        $param = is_array($param) ? array_map('strip_tags', $param) : strip_tags($param);
                        if (is_array($param)) {
                            array_filter($param);
                            // empty removed XSS by strip_tags
                        }
                        if (function_exists('serendipity_specialchars')) {
                            $param = is_array($param) ? array_map('serendipity_specialchars', $param) : serendipity_specialchars($param);
                        } else {
                            $param = is_array($param) ? array_map('htmlspecialchars', $param) : htmlspecialchars($param, ENT_COMPAT, LANG_CHARSET);
                        }
                        $this->tags['show'] = $param;
                        $serendipity['plugin_vars']['tag'] = $param;
                        if (is_array($param)) {
                            @define('PLUGIN_VARS_TAG', implode(',', $param));
                        } else {
                            @define('PLUGIN_VARS_TAG', $param);
                        }
                        $serendipity['GET']['subpage'] = $eventData;
                        unset($serendipity['GET']['category']);
                        // No restriction should be enforced here.
                        include_once S9Y_INCLUDE_PATH . 'include/genpage.inc.php';
                        if ($emit_404 && $this->TaggedEntries !== null && $this->TaggedEntries < 1) {
                            @header('HTTP/1.0 404 Not found');
                            @header('Status: 404 Not found');
                            if (serendipity_db_bool($this->get_config('send_http_header', true))) {
                                @header('X-FreeTag: not found');
                            }
                        } else {
                            if (serendipity_db_bool($this->get_config('send_http_header', true))) {
                                @header('X-FreeTag: ' . $this->TaggedEntries);
                            }
                        }
                        $raw_data = ob_get_contents();
                        ob_end_clean();
                        $serendipity['smarty']->assign('raw_data', $raw_data);
                        serendipity_gzCompression();
                        $serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath'));
                        @define('NO_EXIT', true);
                    }
                    break;
                case 'backend_sidebar_entries':
                    if ($serendipity['version'][0] < 2) {
                        ?>
                            <li class="serendipitySideBarMenuLink serendipitySideBarMenuEntryLinks"><a href="?serendipity[adminModule]=event_display&amp;serendipity[adminAction]=managetags"><?php 
                        echo PLUGIN_EVENT_FREETAG_MANAGETAGS;
                        ?>
</a></li>
<?php 
                    } else {
                        ?>
                            <li><a href="?serendipity[adminModule]=event_display&amp;serendipity[adminAction]=managetags"><?php 
                        echo PLUGIN_EVENT_FREETAG_MANAGETAGS;
                        ?>
</a></li>
<?php 
                    }
                    return true;
                    break;
                case 'backend_sidebar_entries_event_display_managetags':
                    $this->eventData = $eventData;
                    $this->displayManageTags($event, $bag, $eventData, $addData);
                    return true;
                    break;
                case 'backend_publish':
                case 'backend_save':
                    if (function_exists('mb_internal_encoding')) {
                        mb_internal_encoding(LANG_CHARSET);
                    }
                    if (!isset($eventData['id'])) {
                        return true;
                    }
                    $to_lower = serendipity_db_bool($this->get_config('lowercase_tags'));
                    $keylist = serendipity_db_query("SELECT tag, keywords FROM {$serendipity['dbPrefix']}tagkeywords", false, 'assoc');
                    $automatted = array(array());
                    if (is_array($keylist)) {
                        foreach ($keylist as $key) {
                            $keywords = explode(',', $key['keywords']);
                            foreach ($keywords as $keyword) {
                                $automatted[trim($keyword)][$key['tag']] = true;
                            }
                        }
                    }
                    // When this variable is not set, the entry might be saved i.e. by recreating cache or automatted trackback.
                    // Do not loose such tags. :)
                    if (!isset($serendipity['POST']['properties']['freetag_tagList'])) {
                        $serendipity['POST']['properties']['freetag_tagList'] = implode(',', $this->getTagsForEntry($eventData['id']));
                    }
                    $tags = $this->makeTagsFromTagList($serendipity['POST']['properties']['freetag_tagList']);
                    if (serendipity_db_bool($this->get_config('keyword2tag'))) {
                        $searchtext = strip_tags($eventData['body'] . $eventData['extended']);
                        foreach ($automatted as $keyword => $ktags) {
                            $keyword = trim($keyword);
                            if (empty($keyword)) {
                                continue;
                            }
                            if (!is_array($ktags) || count($ktags) < 1) {
                                continue;
                            }
                            $regex = sprintf("/((\\s+|[\\(\\[-]+)%s([-\\/,\\.\\?!'\";\\)\\]]*+|[\\/-]+))/i", $keyword);
                            if (preg_match($regex, $searchtext) > 0) {
                                foreach ($ktags as $tag => $is_assigned) {
                                    if (!is_array($tags) || !in_array(strtolower($tag), $tags) && !in_array($tag, $tags)) {
                                        if ($to_lower) {
                                            if (function_exists("mb_strtolower")) {
                                                $tag = mb_strtolower($tag);
                                            } else {
                                                $tag = strtolower($tag);
                                            }
                                        }
                                        $tags[] = $tag;
                                        printf(PLUGIN_EVENT_FREETAG_KEYWORDS_ADD, function_exists('serendipity_specialchars') ? serendipity_specialchars($keyword) : htmlspecialchars($keyword, ENT_COMPAT, LANG_CHARSET), function_exists('serendipity_specialchars') ? serendipity_specialchars($tag) : htmlspecialchars($tag, ENT_COMPAT, LANG_CHARSET));
                                    }
                                }
                            }
                        }
                    }
                    if (empty($tags)) {
                        $tags = array();
                    }
                    if (serendipity_db_bool($this->get_config('cat2tag'))) {
                        if (is_array($cats = serendipity_fetchCategories())) {
                            $cats = serendipity_walkRecursive($cats, 'categoryid', 'parentid', VIEWMODE_THREADED);
                            foreach ($cats as $cat) {
                                if ($to_lower) {
                                    if (function_exists("mb_strtolower")) {
                                        $cat['category_name'] = mb_strtolower($cat['category_name']);
                                    } else {
                                        $cat['category_name'] = strtolower($cat['category_name']);
                                    }
                                }
                                $names = explode(',', $cat['category_name']);
                                foreach ($names as $name) {
                                    $name = trim($name);
                                    if (is_array($eventData['categories']) && in_array($cat['categoryid'], $eventData['categories']) && !in_array($name, $tags)) {
                                        $tags[] = $name;
                                    }
                                }
                            }
                        }
                    }
                    $serendipity['POST']['properties']['freetag_tagList'] = implode(',', $tags);
                    $this->deleteTagsForEntry($eventData['id']);
                    $this->addTagsToEntry($eventData['id'], $tags);
                    if ($serendipity['POST']['properties']['freetag_kill']) {
                        $this->deleteTagsForEntry($eventData['id']);
                    }
                    return true;
                    break;
                case 'css_backend':
                    if ($serendipity['version'][0] > 1) {
                        ?>

.freetagMenu li {
    display: block;
    margin: 0 0 .5em;
}

.freetags_manage {
    border: 1px solid #aaa;
    border-bottom: 0 none;
    width: 100%;
}

.freetags_manage thead tr {
    background-color: #eee;
}

.freetags_manage tr {
    border-bottom: 1px solid #aaa;
}

.freetags_manage th,
.freetags_manage td {
    padding: .125em .25em;
}

.freetags_list li {
    margin: 0 0 .25em;
}

@media only screen and (min-width: 768px) {
    .freetagMenu li {
        display: inline-block;
        margin: 0 .25em .5em 0;
    }
}

<?php 
                    }
                    return true;
                    break;
                case 'js_backend':
                    // autocomplete with serendipity 2.0
                    if ($this->get_config('admin_ftayt')) {
                        echo '
function enableAutocomplete() {
    if (typeof(tags) != "undefined") {
        $("#properties_freetag_tagList").autocomplete(tags, {
            minChars: 0,
            multiple: true,
            scrollHeight: 200,
            matchContains: "word",
            autoFill: false
        });
    }
};

addLoadEvent(enableAutocomplete);

';
                    }
                    break;
                case 'backend_display':
                    if (function_exists('mb_internal_encoding')) {
                        mb_internal_encoding(LANG_CHARSET);
                    }
                    if (!empty($serendipity['POST']['properties']['freetag_tagList'])) {
                        $tagList = $serendipity['POST']['properties']['freetag_tagList'];
                    } else {
                        if (isset($eventData['id'])) {
                            $tagList = implode(',', $this->getTagsForEntry($eventData['id']));
                        } else {
                            $tagList = '';
                        }
                    }
                    if (serendipity_db_bool($this->get_config('lowercase_tags', true))) {
                        if (function_exists("mb_strtolower")) {
                            $tagList = mb_strtolower($tagList);
                        } else {
                            $tagList = strtolower($tagList);
                        }
                    }
                    $freetags = $this->makeTagsFromTagList($tagList);
                    if (!empty($freetags)) {
                        $tagList = implode(',', $freetags);
                    }
                    $taglist = (array) $this->getAllTags();
                    if ($this->get_config('admin_ftayt')) {
                        foreach ($taglist as $k => $v) {
                            $wicktags[] = '\'' . addslashes($k) . '\'';
                        }
                        // jQuery Migrate is used due to $.browser of autocomplete plugin not being available in jquery 1.9+
                        echo '
                        ' . ($serendipity['version'][0] < 2 ? '<script src="' . $serendipity['baseURL'] . 'plugins/serendipity_event_freetag/jquery-1.11.1.min.js" type="text/javascript"></script>' : '') . '
                        <link rel="stylesheet" type="text/css" href="' . $serendipity['baseURL'] . 'plugins/serendipity_event_freetag/jquery.autocomplete.css" />
                        <script src="' . $serendipity['baseURL'] . 'plugins/serendipity_event_freetag/jquery-migrate-1.2.1.min.js"></script>
                        <script type="text/javascript" src="' . $serendipity['baseURL'] . 'plugins/serendipity_event_freetag/jquery.autocomplete.min.js"></script>
                        <script type="text/javascript">
                        var tags = [' . implode(',', $wicktags) . '];
                         ' . ($serendipity['version'][0] < 2 ? '
                        function enableAutocomplete() {
                            $("#properties_freetag_tagList").autocomplete(tags, {
                                        minChars: 0,
                                        multiple: true,
                                        scrollHeight: 200,
                                        matchContains: "word",
                                        autoFill: false
                                    })};
                            addLoadEvent(enableAutocomplete);
                         ' : '') . '
                        </script>';
                    }
                    if ($this->get_config('admin_show_taglist')) {
                        ?>
                        <script type="text/javascript">
                        function addTag(addTag)
                        {
                            var freetags = document.getElementById("properties_freetag_tagList").value.split(',');

                            inList = false;
                            for (var freetag = 0; freetag < freetags.length; freetag++) {
                                if (freetags[freetag] && trim(freetags[freetag].toLowerCase()) == addTag.toLowerCase()) {
                                    inList = true;
                                }
                            }

                            if (!inList) {
                                if (document.getElementById("properties_freetag_tagList").value.lastIndexOf(',') == (document.getElementById("properties_freetag_tagList").value.length-1)) {
                                    sepChar = '';
                                } else {
                                    sepChar = ',';
                                }

                                document.getElementById("properties_freetag_tagList").value = document.getElementById("properties_freetag_tagList").value + sepChar + addTag;
                            }
                        }

                        function trim(str)
                        {
                            if (str) return str.replace(/^\s*|\s*$/g,"");
                             else return '';
                        }
                        </script>
<?php 
                    }
                    if ($serendipity['version'][0] < 2) {
                        ?>
                        <fieldset style="margin: 5px">
                            <legend><?php 
                        echo PLUGIN_EVENT_FREETAG_TITLE;
                        ?>
</legend>
                            <label for="serendipity[properties][freetag_tagList]" title="<?php 
                        echo PLUGIN_EVENT_FREETAG_TITLE;
                        ?>
"><?php 
                        echo PLUGIN_EVENT_FREETAG_ENTERDESC;
                        ?>
:</label><br/>
                            <input type="text" name="serendipity[properties][freetag_tagList]" id="properties_freetag_tagList" class="wickEnabled input_textbox" value="<?php 
                        echo function_exists('serendipity_specialchars') ? serendipity_specialchars($tagList) : htmlspecialchars($tagList, ENT_COMPAT, LANG_CHARSET);
                        ?>
" style="width: 100%" />

                            <input type="checkbox" name="serendipity[properties][freetag_kill]" id="properties_freetag_kill" class="input_checkbox" />
                            <label for="serendipity[properties][freetag_kill]" title="<?php 
                        echo PLUGIN_EVENT_FREETAG_KILL;
                        ?>
"><?php 
                        echo PLUGIN_EVENT_FREETAG_KILL;
                        ?>
</label><br/>
<?php 
                        if ($this->get_config('admin_show_taglist')) {
                            ?>
                            <a name="tagListAnchor"></a>
                            <div id="backend_freetag_list" style="margin: 5px; border: 1px dotted #000; padding: 5px; font-size: 9px;">
<?php 
                        }
                    } else {
                        ?>
                        <fieldset id="edit_entry_freetags" class="entryproperties_freetag">
                            <span class="wrap_legend"><legend><?php 
                        echo PLUGIN_EVENT_FREETAG_TITLE;
                        ?>
</legend></span>
                            <div class="form_field">
                                <label for="properties_freetag_tagList" class="block_level"><?php 
                        echo PLUGIN_EVENT_FREETAG_ENTERDESC;
                        ?>
:</label>
                                <input id="properties_freetag_tagList" type="text" name="serendipity[properties][freetag_tagList]" class="wickEnabled" value="<?php 
                        echo function_exists('serendipity_specialchars') ? serendipity_specialchars($tagList) : htmlspecialchars($tagList, ENT_COMPAT, LANG_CHARSET);
                        ?>
">
                            </div>
                            <div class="form_check">
                                <input id="properties_freetag_kill" type="checkbox" name="serendipity[properties][freetag_kill]">
                                <label for="properties_freetag_kill"><?php 
                        echo PLUGIN_EVENT_FREETAG_KILL;
                        ?>
</label>
                            </div>
<?php 
                        if ($this->get_config('admin_show_taglist')) {
                            ?>
                            <a name="tagListAnchor"></a>
                            <div id="backend_freetag_list">
<?php 
                        }
                    }
                    if ($this->get_config('admin_show_taglist')) {
                        $lastletter = '';
                        foreach ($taglist as $tag => $count) {
                            if (function_exists('mb_strtoupper')) {
                                $upc = mb_strtoupper(mb_substr($tag, 0, 1, LANG_CHARSET), LANG_CHARSET);
                            } else {
                                $upc = strtoupper(substr($tag, 0, 1));
                            }
                            if ($upc != $lastletter) {
                                if ($serendipity['version'][0] < 2) {
                                    echo " <b>|" . $upc . ':</b> ';
                                }
                            }
                            if ($serendipity['version'][0] < 2) {
                                echo "<a href=\"#tagListAnchor\" style=\"text-decoration: none\" onClick=\"addTag('{$tag}')\">{$tag}</a>, ";
                            } else {
                                echo "<a href=\"#tagListAnchor\" onClick=\"addTag('{$tag}')\">{$tag}</a> ";
                            }
                            $lastletter = $upc;
                        }
                        echo "</div>";
                    }
                    ?>
                        </fieldset>
<?php 
                    return true;
                    break;
                case 'frontend_entryproperties':
                    $this->importEntryTagsIntoProperties($eventData, $addData);
                    return true;
                    break;
                case 'frontend_fetchentries':
                case 'frontend_fetchentry':
                    if (!empty($this->tags['show'])) {
                        if (is_array($this->tags['show'])) {
                            $showtag = array_map('serendipity_db_escape_string', $this->tags['show']);
                        } else {
                            $showtag = serendipity_db_escape_string($this->tags['show']);
                        }
                    } else {
                        if (!empty($serendipity['GET']['tag'])) {
                            $showtag = serendipity_db_escape_string(urldecode($serendipity['GET']['tag']));
                        }
                    }
                    if (is_array($showtag)) {
                        $arr_showtag = $showtag;
                    } else {
                        $arr_showtag = explode(';', $showtag);
                    }
                    $multimode = 'and';
                    if (count($arr_showtag) > 1) {
                        $showtag = $arr_showtag;
                        $multimode = 'or';
                    }
                    if (!empty($show_tag) && is_string($show_tag) && serendipity_db_bool($this->get_config('lowercase_tags', true))) {
                        if (function_exists("mb_strtolower")) {
                            if (function_exists('mb_internal_encoding')) {
                                mb_internal_encoding(LANG_CHARSET);
                            }
                            $showtag = mb_strtolower($showtag);
                        } else {
                            $showtag = strtolower($showtag);
                        }
                    }
                    $coll_target = $this->get_config('collation', '');
                    if (empty($coll_target) && stristr($serendipity['dbType'], 'mysql')) {
                        $cd = serendipity_db_query("SHOW FULL COLUMNS FROM {$serendipity['dbPrefix']}entrytags LIKE 'tag'");
                        if (!empty($cd[0]['Collation'])) {
                            $coll_target = $cd[0]['Collation'];
                            $this->set_config('collation', $coll_target);
                        }
                    }
                    if (!empty($showtag)) {
                        if (LANG_CHARSET == 'UTF-8' && stristr($serendipity['dbType'], 'mysql') && !stristr($coll_target, 'utf8')) {
                            $collate = "COLLATE utf8_general_ci";
                            $collateP = '_utf8 ';
                        } else {
                            $collate = $collateP = "";
                        }
                        $cond = $join = '';
                        if (is_string($showtag)) {
                            $join = "INNER JOIN {$serendipity['dbPrefix']}entrytags AS entrytags ON (e.id = entrytags.entryid) ";
                            $cond = "entrytags.tag = {$collateP} '{$showtag}' {$collate}";
                        } else {
                            if (is_array($showtag)) {
                                $_taglist = array();
                                $cond = '(1=2 ';
                                foreach ($showtag as $_showtag) {
                                    $_taglist[] = serendipity_db_escape_string($_showtag);
                                    $cond .= " OR entrytags.tag = {$collateP} '" . serendipity_db_escape_string($_showtag) . "' {$collate} ";
                                }
                                $cond .= ' ) ';
                                $total = count($showtag);
                                $join = "INNER JOIN {$serendipity['dbPrefix']}entrytags AS entrytags " . "ON e.id = entrytags.entryid ";
                                if ($multimode == 'and') {
                                    $eventData['having'] = " HAVING count(entrytags.tag) = {$total}";
                                }
                            }
                        }
                        if (empty($eventData['and'])) {
                            $eventData['and'] = " WHERE {$cond} ";
                        } else {
                            $eventData['and'] .= " AND {$cond} ";
                        }
                        if (empty($eventData['joins'])) {
                            $eventData['joins'] = $join;
                        } else {
                            $eventData['joins'] .= $join;
                        }
                        $this->displayTag = $showtag;
                        $serendipity['plugin_vars']['displayTag'] = $showtag;
                        @define('PLUGIN_VARS_DISPLAYTAG', $showtag);
                    }
                    return true;
                    break;
                case 'frontend_rss':
                    if (!empty($this->displayTag)) {
                        $eventData['title'] .= serendipity_utf8_encode(function_exists('serendipity_specialchars') ? serendipity_specialchars(' (' . sprintf(PLUGIN_EVENT_FREETAG_USING, $this->displayTag) . ')') : htmlspecialchars(' (' . sprintf(PLUGIN_EVENT_FREETAG_USING, $this->displayTag) . ')', ENT_COMPAT, LANG_CHARSET));
                    }
                    return true;
                    break;
                case 'entries_header':
                    if (isset($eventData['plugin_vars']['tag']) && serendipity_db_bool($this->get_config('show_tagcloud'))) {
                        $this->displayTagCloud($eventData['plugin_vars']['tag']);
                    }
                    return true;
                    break;
                case 'css':
                    if (strpos($eventData, '.serendipity_freeTag')) {
                        // class exists in CSS, so a user has customized it and we don't need default
                        return true;
                    }
                    $this->addToCSS($eventData);
                    return true;
                    break;
                case 'entry_display':
                    // Don't display entries if we are getting a full tag list
                    if (is_array($eventData)) {
                        $this->TaggedEntries = count($eventData);
                        if (serendipity_db_bool($this->get_config('send_http_header', true))) {
                            @header('X-FreeTag-Count: Array');
                        }
                    } else {
                        if (serendipity_db_bool($this->get_config('send_http_header', true))) {
                            @header('X-FreeTag-Count: Empty');
                        }
                        $this->TaggedEntries = 0;
                    }
                    if ($this->displayTag === true) {
                        $eventData['clean_page'] = true;
                        return true;
                    }
                    $this->displayEntry($eventData, $addData);
                    return true;
                    break;
                case 'xmlrpc_updertEntry':
                    if (isset($eventData['id']) && isset($eventData['mt_keywords'])) {
                        //XMLRPC call
                        $tags = $this->makeTagsFromTagList($eventData['mt_keywords']);
                        if (!empty($tags)) {
                            $this->deleteTagsForEntry($eventData['id']);
                            $this->addTagsToEntry($eventData['id'], $tags);
                        }
                    }
                    return true;
                    break;
                case 'xmlrpc_fetchEntry':
                    $eventData['mt_keywords'] = implode(',', $this->getTagsForEntry($eventData['id']));
                    return true;
                    break;
                case 'xmlrpc_deleteEntry':
                    if (isset($eventData["id"])) {
                        $this->deleteTagsForEntry($eventData["id"]);
                    }
                    return true;
                    break;
                default:
                    return false;
                    break;
            }
        } else {
            return false;
        }
    }
    function event_hook($event, &$bag, &$eventData, $addData = null)
    {
        global $serendipity;
        $hooks =& $bag->get('event_hooks');
        $links = array();
        if (isset($hooks[$event])) {
            $sort_order = array('timestamp' => DATE, 'isdraft' => PUBLISH . '/' . DRAFT, 'a.realname' => AUTHOR, 'category_name' => CATEGORY, 'last_modified' => LAST_UPDATED, 'title' => TITLE);
            $per_page_max = 50;
            $per_page = array('12', '16', '25', $per_page_max);
            switch ($event) {
                case 'frontend_fetchentries':
                    if ($this->fetchLimit > 0) {
                        $serendipity['fetchLimit'] = $this->fetchLimit;
                    }
                    break;
                case 'frontend_configure':
                    $_SERVER['REQUEST_URI'] = str_replace('%2Fplugin%2Ffilter%2F', '/plugin/filter/', $_SERVER['REQUEST_URI']);
                    break;
                case 'entries_footer':
                    $link = $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/filter/';
                    ?>
<div id="filter_entries_container">
    <br />
    <hr />
    <form action="<?php 
                    echo $link;
                    ?>
" method="get">

    <?php 
                    if ($serendipity['rewrite'] == 'none') {
                        ?>
    <input type="hidden" name="/plugin/filter/" value="" />
    <?php 
                    }
                    ?>
    <table width="100%">
        <tr>
            <td colspan="6" style="text-align: left"><strong><?php 
                    echo FILTERS;
                    ?>
</strong> - <?php 
                    echo FIND_ENTRIES;
                    ?>
</td>
        </tr>
        <tr>
            <td width="80"><?php 
                    echo AUTHOR;
                    ?>
</td>
            <td>
                <select name="filter[author]">
                    <option value="">--</option>
<?php 
                    $users = serendipity_fetchUsers();
                    if (is_array($users)) {
                        foreach ($users as $user) {
                            echo '<option value="' . $user['authorid'] . '" ' . (isset($_SESSION['filter']['author']) && $_SESSION['filter']['author'] == $user['authorid'] ? 'selected="selected"' : '') . '>' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($user['realname']) : htmlspecialchars($user['realname'], ENT_COMPAT, LANG_CHARSET)) . '</option>' . "\n";
                        }
                    }
                    ?>
              </select>
            </td>
            <td width="80"><?php 
                    echo CATEGORY;
                    ?>
</td>
            <td>
                <select name="filter[category]">
                    <option value="">--</option>
<?php 
                    $categories = serendipity_fetchCategories();
                    $categories = serendipity_walkRecursive($categories, 'categoryid', 'parentid', VIEWMODE_THREADED);
                    foreach ($categories as $cat) {
                        echo '<option value="' . $cat['categoryid'] . '"' . ($_SESSION['filter']['category'] == $cat['categoryid'] ? ' selected="selected"' : '') . '>' . str_repeat('&nbsp;', $cat['depth']) . $cat['category_name'] . '</option>' . "\n";
                    }
                    ?>
              </select>
            </td>
            <td width="80"><?php 
                    echo CONTENT;
                    ?>
</td>
            <td><input size="10" type="text" name="filter[body]" value="<?php 
                    echo isset($_SESSION['filter']['body']) ? function_exists('serendipity_specialchars') ? serendipity_specialchars($_SESSION['filter']['body']) : htmlspecialchars($_SESSION['filter']['body'], ENT_COMPAT, LANG_CHARSET) : '';
                    ?>
" /></td>
        </tr>
        <tr>
            <td colspan="6" style="text-align: left"><strong><?php 
                    echo SORT_ORDER;
                    ?>
</strong></td>
        </tr>
        <tr>
            <td><?php 
                    echo SORT_BY;
                    ?>
</td>
            <td>
                <select name="sort[order]">
<?php 
                    foreach ($sort_order as $so_key => $so_val) {
                        echo '<option value="' . $so_key . '" ' . (isset($_SESSION['sort']['order']) && $_SESSION['sort']['order'] == $so_key ? 'selected="selected"' : '') . '>' . $so_val . '</option>' . "\n";
                    }
                    ?>
              </select>
            </td>
            <td><?php 
                    echo SORT_ORDER;
                    ?>
</td>
            <td>
                <select name="sort[ordermode]">
                    <option value="DESC" <?php 
                    echo isset($_SESSION['sort']['ordermode']) && $_SESSION['sort']['ordermode'] == 'DESC' ? 'selected="selected"' : '';
                    ?>
><?php 
                    echo SORT_ORDER_DESC;
                    ?>
</option>
                    <option value="ASC" <?php 
                    echo isset($_SESSION['sort']['ordermode']) && $_SESSION['sort']['ordermode'] == 'ASC' ? 'selected="selected"' : '';
                    ?>
><?php 
                    echo SORT_ORDER_ASC;
                    ?>
</option>
                </select>
            </td>
            <td><?php 
                    echo ENTRIES_PER_PAGE;
                    ?>
</td>
            <td>
                <select name="sort[perPage]">
<?php 
                    foreach ($per_page as $per_page_nr) {
                        echo '<option value="' . $per_page_nr . '"   ' . (isset($_SESSION['sort']['perPage']) && $_SESSION['sort']['perPage'] == $per_page_nr ? 'selected="selected"' : '') . '>' . $per_page_nr . '</option>' . "\n";
                    }
                    ?>
                </select>
            </td>
        </tr>
        <tr>
            <td align="right" colspan="6"><input type="submit" name="go" value="<?php 
                    echo GO;
                    ?>
" class="serendipityPrettyButton" /></td>
        </tr>
    </table>
</form>
</div>
<?php 
                    return true;
                    break;
                case 'external_plugin':
                    $uri_parts = explode('?', str_replace('&amp;', '&', $eventData));
                    $parts = explode('/', $uri_parts[0]);
                    $plugincode = $parts[0];
                    unset($parts[0]);
                    $uri = $_SERVER['REQUEST_URI'];
                    $puri = parse_url($uri);
                    $queries = explode('&', str_replace(array('%5B', '%5D'), array('[', ']'), $puri['query']));
                    foreach ($queries as $query_part) {
                        $query = explode('=', $query_part);
                        switch ($query[0]) {
                            case 'filter[author]':
                                $_GET['filter']['author'] = urldecode($query[1]);
                                break;
                            case 'filter[category]':
                                $_GET['filter']['category'] = urldecode($query[1]);
                                break;
                            case 'filter[body]':
                                $_GET['filter']['body'] = urldecode($query[1]);
                                break;
                            case 'sort[order]':
                                $_GET['sort']['order'] = urldecode($query[1]);
                                break;
                            case 'sort[ordermode]':
                                $_GET['sort']['ordermode'] = urldecode($query[1]);
                                break;
                            case 'sort[perPage]':
                                $_GET['sort']['perPage'] = urldecode($query[1]);
                                break;
                        }
                    }
                    if (is_array($_GET['filter'])) {
                        $_SESSION['filter'] = $_GET['filter'];
                    }
                    if (is_array($_GET['sort'])) {
                        $_SESSION['sort'] = $_GET['sort'];
                    }
                    /* Attempt to locate hidden variables within the URI */
                    foreach ($serendipity['uriArguments'] as $k => $v) {
                        if ($v[0] == 'P') {
                            /* Page */
                            $page = substr($v, 1);
                            if (is_numeric($page)) {
                                $serendipity['GET']['page'] = $page;
                                unset($serendipity['uriArguments'][$k]);
                            }
                        }
                    }
                    switch ($plugincode) {
                        case 'filter':
                            $perPage = (int) (!empty($_SESSION['sort']['perPage']) ? $_SESSION['sort']['perPage'] : $per_page[0]);
                            if ($perPage > $per_page_max) {
                                $perPage = $per_page_max;
                            }
                            $serendipity['fetchLimit'] = $perPage;
                            $this->fetchLimit = $perPage;
                            $page = (int) $serendipity['GET']['page'];
                            if ($page == 0) {
                                $page = 1;
                            }
                            $offSet = $perPage * ($page - 1);
                            if (empty($_SESSION['sort']['ordermode']) || $_SESSION['sort']['ordermode'] != 'ASC') {
                                $_SESSION['sort']['ordermode'] = 'DESC';
                            }
                            if (!empty($_SESSION['sort']['order']) && !empty($sort_order[$_SESSION['sort']['order']])) {
                                $orderby = serendipity_db_escape_string($_SESSION['sort']['order'] . ' ' . $_SESSION['sort']['ordermode']);
                            } else {
                                $orderby = 'timestamp ' . serendipity_db_escape_string($_SESSION['sort']['ordermode']);
                            }
                            $filter = array();
                            if (!empty($_SESSION['filter']['author'])) {
                                $filter[] = "e.authorid = '" . serendipity_db_escape_string($_SESSION['filter']['author']) . "'";
                            }
                            if (!empty($_SESSION['filter']['category'])) {
                                $filter[] = "ec.categoryid = '" . serendipity_db_escape_string($_SESSION['filter']['category']) . "'";
                            }
                            if (!empty($_SESSION['filter']['body'])) {
                                if ($serendipity['dbType'] == 'mysql') {
                                    $filter[] = "MATCH (title,body,extended) AGAINST ('" . serendipity_db_escape_string($_SESSION['filter']['body']) . "')";
                                    $full = true;
                                }
                            }
                            $filter_sql = implode(' AND ', $filter);
                            // Fetch the entries
                            $entries = serendipity_fetchEntries(false, false, serendipity_db_limit($offSet, $perPage), true, false, $orderby, $filter_sql);
                            $serendipity['smarty_raw_mode'] = true;
                            include_once S9Y_INCLUDE_PATH . 'include/genpage.inc.php';
                            serendipity_printEntries($entries);
                            $raw_data = ob_get_contents();
                            ob_end_clean();
                            $serendipity['smarty']->assign('CONTENT', $raw_data);
                            $serendipity['smarty']->assign('is_raw_mode', false);
                            serendipity_gzCompression();
                            $serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath'));
                            break;
                    }
                    return true;
                    break;
                default:
                    return false;
                    break;
            }
        } else {
            return false;
        }
    }