function event_hook($event, &$bag, &$eventData)
 {
     global $serendipity;
     $hooks =& $bag->get('event_hooks');
     if (isset($hooks[$event])) {
         switch ($event) {
             case 'frontend_configure':
                 if (isset($serendipity['COOKIE']['user_template']) && !isset($_REQUEST['user_template'])) {
                     $_REQUEST['user_template'] = $serendipity['COOKIE']['user_template'];
                 }
                 if (isset($_REQUEST['user_template']) && in_array($_REQUEST['user_template'], serendipity_fetchTemplates())) {
                     $_SESSION['serendipityUseTemplate'] = $_REQUEST['user_template'];
                     serendipity_setCookie('user_template', $_REQUEST['user_template'], false);
                 }
                 if (isset($_SESSION['serendipityUseTemplate'])) {
                     $templateInfo = serendipity_fetchTemplateInfo($_SESSION['serendipityUseTemplate']);
                     $eventData['template'] = $_SESSION['serendipityUseTemplate'];
                     $eventData['template_engine'] = isset($templateInfo['engine']) ? $templateInfo['engine'] : $serendipity['defaultTemplate'];
                     $serendipity['smarty_vars']['head_link_stylesheet'] = $serendipity['baseURL'] . 'serendipity.css.php?switch=' . $_REQUEST['user_template'];
                 }
                 return true;
                 break;
             default:
                 return false;
         }
     } else {
         return false;
     }
 }
 function generate_content(&$title)
 {
     global $serendipity;
     $title = $this->get_config('title', $this->title);
     $url = serendipity_currentURL(true);
     echo '<form id="theme_chooser" action="' . $url . '" method="post">';
     echo '<select name="user_template" onchange="document.getElementById(\'theme_chooser\').submit();">';
     foreach (serendipity_fetchTemplates() as $template) {
         $templateInfo = serendipity_fetchTemplateInfo($template);
         echo '<option value="' . $template . '" ' . (serendipity_get_config_var('template', 'default') == $template ? 'selected="selected"' : '') . '>' . substr($templateInfo['name'], 0, 25) . '</option>';
     }
     echo '</select>';
     if ($this->get_config('show_submit', 'false') == 'true') {
         echo '<input type="submit" name="submit" value="' . GO . '" size="4" />';
     }
     echo '</form>';
 }
 function event_hook($event, &$bag, &$eventData, $addData = null)
 {
     global $serendipity;
     $hooks =& $bag->get('event_hooks');
     if (isset($hooks[$event])) {
         switch ($event) {
             case 'frontend_configure':
                 if (defined('IN_serendipity_admin') && IN_serendipity_admin) {
                     // Admin shall not have switchable themes.
                     return true;
                 }
                 if (isset($serendipity['COOKIE']['user_template']) && !isset($_REQUEST['user_template'])) {
                     $_REQUEST['user_template'] = $serendipity['COOKIE']['user_template'];
                 }
                 if (isset($_REQUEST['user_template']) && in_array($_REQUEST['user_template'], serendipity_fetchTemplates())) {
                     # Specific themes can be blacklisted for viewing. Enter the names of those, one per line.
                     $blacklisted = $has_blacklist = false;
                     if (file_exists(dirname(__FILE__) . '/blacklist.txt')) {
                         $_blacklist = explode("\n", file_get_contents(dirname(__FILE__) . '/blacklist.txt'));
                         $blacklist = array();
                         $has_blacklist = true;
                         foreach ($_blacklist as $idx => $blackline) {
                             $blackline = trim($blackline);
                             if (empty($blackline)) {
                                 continue;
                             }
                             if ($blackline[0] == '#') {
                                 continue;
                             }
                             $blacklist[$blackline] = true;
                             if (preg_match('/' . preg_quote($blackline) . '$/i', $_REQUEST['user_template'])) {
                                 header('X-Theme-Blacklisted: ' . urlencode($blackline));
                                 $blacklisted = true;
                             }
                         }
                     }
                     if (!$blacklisted) {
                         $_SESSION['serendipityUseTemplate'] = $_REQUEST['user_template'];
                         # When blacklisting occurs, the cookie to remember template selection will be removed by closing the browser.
                         serendipity_setCookie('user_template', $_REQUEST['user_template'], false, $has_blacklist ? 0 : false);
                     }
                 }
                 // If the requested template is the same as the current default template,
                 // we will not set this variable. This is important so that templates/plugins
                 // which detect serendipityUseTemplate can use reasonable defaults in case
                 // template configuration options do not exist. Guess nobody understands
                 // this explanation anyways, and who reads this stuff, heh?
                 if ($_SESSION['serendipityUseTemplate'] == $eventData['template']) {
                     unset($_SESSION['serendipityUseTemplate']);
                 }
                 if (isset($_SESSION['serendipityUseTemplate'])) {
                     $templateInfo = serendipity_fetchTemplateInfo($_SESSION['serendipityUseTemplate']);
                     $eventData['template'] = $_SESSION['serendipityUseTemplate'];
                     // NOTE: Bulletproof uses diverse options, but since they are not configured by default, we cannot output fallback templates using bulletproof. So we need to use "default" for now.
                     $eventData['template_engine'] = isset($templateInfo['engine']) ? $templateInfo['engine'] : 'default';
                     $serendipity['smarty_vars']['head_link_stylesheet'] = $serendipity['baseURL'] . 'serendipity.css.php?switch=' . $_REQUEST['user_template'];
                 }
                 return true;
                 break;
             default:
                 return false;
         }
     } else {
         return false;
     }
 }
    /**
     * The meat of the plugin, called for each registered hook.  
     * @param string event The name of the hook being called
     * @param mixed bag An array of configuration options for this plugin
     * @param mixed eventData An array containing parameters for the hook
     * @param mixed addData Additional hook data, if any
     * @return true
     */
    function event_hook($event, &$bag, &$eventData, $addData = null)
    {
        global $serendipity;
        $hooks =& $bag->get('event_hooks');
        if (isset($hooks[$event])) {
            // Update the database on first run if changed.
            $ver = $this->get_config('dbversion', 0);
            if ($ver != CATEGORYTEMPLATE_DB_VERSION) {
                $this->checkScheme($ver);
            }
            switch ($event) {
                // When changing category options, display the new extended
                // options, such as template, future entries, limit, and order
                case 'backend_category_showForm':
                    // The $eventData is the category ID
                    $clang = $this->fetchLang($eventData, '');
                    $cfuture = $this->fetchFuture($eventData, '');
                    $styles = serendipity_fetchTemplates();
                    $template = $this->fetchTemplate($eventData, '');
                    $hide_rss = serendipity_db_query("SELECT hide_rss FROM {$serendipity['dbPrefix']}categorytemplates AS t WHERE t.categoryid = {$eventData}", true);
                    if ($hide_rss !== false) {
                        $hide_rss = serendipity_db_bool($hide_rss['hide_rss']);
                    }
                    ?>
    <tr>
        <td valign="top"><label for="template"><?php 
                    echo SELECT_TEMPLATE;
                    ?>
</label></td>
        <td><input class="input_textbox" id="template" type="text" name="serendipity[cat][template]" value="<?php 
                    echo $template;
                    ?>
" /><br />
            - <?php 
                    echo WORD_OR;
                    ?>
 -<br />
            <select name="serendipity[cat][drop_template]">
                <option value=""><?php 
                    echo NONE;
                    ?>
</option>
<?php 
                    foreach ($styles as $style => $path) {
                        $templateInfo = serendipity_fetchTemplateInfo($style);
                        ?>
            <option value="<?php 
                        echo function_exists('serendipity_specialchars') ? serendipity_specialchars($style) : htmlspecialchars($style, ENT_COMPAT, LANG_CHARSET);
                        ?>
" <?php 
                        echo $style == $template ? 'selected="selected"' : '';
                        ?>
><?php 
                        echo function_exists('serendipity_specialchars') ? serendipity_specialchars($templateInfo['name']) : htmlspecialchars($templateInfo['name'], ENT_COMPAT, LANG_CHARSET);
                        ?>
</option>
<?php 
                    }
                    ?>
            </select>
            
            <?php 
                    if (!empty($template)) {
                        ?>
            <br /><br /><a class="serendipityPrettyButton" href="serendipity_admin.php?serendipity[adminModule]=event_display&amp;serendipity[adminAction]=cattemplate&amp;serendipity[catid]=<?php 
                        echo $eventData;
                        ?>
&amp;serendipity[cat_template]=<?php 
                        echo urlencode($template);
                        ?>
"><?php 
                        echo STYLE_OPTIONS;
                        ?>
</a>
            <?php 
                    }
                    ?>
        </td>
    </tr>
    <tr>
        <td colspan="2"><em><?php 
                    echo PLUGIN_CATEGORYTEMPLATES_SELECT;
                    ?>
</em></td>
    </tr>

<!-- TODO: This does not work easily.
    <tr>
        <td><label for="language"><?php 
                    echo INSTALL_LANG;
                    ?>
</label></td>
        <td><select id="language" name="serendipity[cat][lang]">
            <option value="default"><?php 
                    echo USE_DEFAULT;
                    ?>
</option>
        <?php 
                    foreach ($serendipity['languages'] as $langkey => $lang) {
                        ?>
            <option value="<?php 
                        echo $lang;
                        ?>
" <?php 
                        echo $langkey == $clang ? 'selected="selected"' : '';
                        ?>
><?php 
                        echo function_exists('serendipity_specialchars') ? serendipity_specialchars($lang) : htmlspecialchars($lang, ENT_COMPAT, LANG_CHARSET);
                        ?>
</option>
        <?php 
                    }
                    ?>
        </select></td>
    </tr>
-->

    <tr>
        <td><?php 
                    echo INSTALL_SHOWFUTURE;
                    ?>
</td>
        <td>
            <input class="input_radio" type="radio" id ="futureentries_default" name="serendipity[cat][futureentries]" value="0" <?php 
                    echo empty($cfuture) || $cfuture == 0 ? 'checked="checked"' : '';
                    ?>
 /><label for="futureentries_default"><?php 
                    echo USE_DEFAULT;
                    ?>
</label><br />
            <input class="input_radio" type="radio" id ="futureentries_no"      name="serendipity[cat][futureentries]" value="1" <?php 
                    echo $cfuture == 1 ? 'checked="checked"' : '';
                    ?>
 /><label for="futureentries_no"><?php 
                    echo NO;
                    ?>
</label><br />
            <input class="input_radio" type="radio" id ="futureentries_yes"     name="serendipity[cat][futureentries]" value="2" <?php 
                    echo $cfuture == 2 ? 'checked="checked"' : '';
                    ?>
 /><label for="futureentries_yes"><?php 
                    echo YES;
                    ?>
</label>
        </td>
    </tr>


    <tr>
        <td><label for="fetchlimit"><?php 
                    echo PLUGIN_CATEGORYTEMPLATES_FETCHLIMIT;
                    ?>
</label></td>
        <td><input class="input_textbox" id="fetchlimit" type="text" name="serendipity[cat][fetchlimit]" value="<?php 
                    echo $this->fetchLimit($eventData, '');
                    ?>
" /></td>
    </tr>

    <tr>
        <td><label for="sort_order"><?php 
                    echo SORT_ORDER;
                    ?>
</label></td>
        <td><input class="input_textbox" id="sort_order" type="text" name="serendipity[cat][sort_order]" value="<?php 
                    echo $this->fetchSortOrder($eventData, $this->get_config('sort_order'));
                    ?>
" /></td>
    </tr>
    
    <tr>
        <td><label for="hide_rss"><?php 
                    echo PLUGIN_CATEGORYTEMPLATES_HIDERSS;
                    ?>
</label></td>
        <td>
            <input class="input_radio" type="radio" id="hiderss_no"  name="serendipity[cat][hide_rss]" value="0" <?php 
                    echo $hide_rss ? '' : 'checked="checked"';
                    ?>
 /><label for="hiderss_no"><?php 
                    echo NO;
                    ?>
</label><br />
            <input class="input_radio" type="radio" id="hiderss_yes"  name="serendipity[cat][hide_rss]" value="1" <?php 
                    echo $hide_rss ? 'checked="checked"' : '';
                    ?>
 /><label for="hiderss_yes"><?php 
                    echo YES;
                    ?>
</label><br />
        </td>
    </tr>

<?php 
                    if (serendipity_db_bool($this->get_config('pass'))) {
                        ?>
    <tr>
        <td><label for="pass"><?php 
                        echo PLUGIN_CATEGORYTEMPLATES_PASS;
                        ?>
</label></td>
        <td><input class="input_textbox" id="pass" type="text" name="serendipity[cat][pass]" value="<?php 
                        echo $this->fetchProp($eventData, 'pass');
                        ?>
" /></td>
    </tr>
<?php 
                    }
                    return true;
                    break;
                    // When a category is deleted, delete its custom properties
                // When a category is deleted, delete its custom properties
                case 'backend_category_delete':
                    // $eventData is the category ID.  This just deletes.
                    $this->setProps($eventData, null, true);
                    // Remove it from the list of template categories, too.
                    $cidstr = $this->get_config('cat_precedence', false);
                    // No need to modify config if no config set, or if no
                    // templates are templatized
                    if ($cidstr) {
                        $cids = explode(',', $cidstr);
                        // Why doesn't PHP have an array_remove(item)?
                        if (in_array($eventData, $cids)) {
                            $newcids = array();
                            foreach ($cids as $cid) {
                                if ($cid != $eventData) {
                                    $newcids[] = $cid;
                                }
                            }
                            $cidstr = implode(',', $newcids);
                            $this->set_config('cat_precedence', $cidstr);
                        }
                    }
                    break;
                    // When a category is updated or added, modify its properties
                // When a category is updated or added, modify its properties
                case 'backend_category_update':
                case 'backend_category_addNew':
                    $orig_tpl = $this->fetchTemplate($eventData, '');
                    $text_tpl = $serendipity['POST']['cat']['template'];
                    $drop_tpl = $serendipity['POST']['cat']['drop_template'];
                    // Default no change to template
                    $set_tpl = $orig_tpl;
                    // If text template changed, it takes precedence
                    if ($text_tpl != $orig_tpl) {
                        // (even when invalid; no checking)
                        $set_tpl = $text_tpl;
                    } else {
                        if ($drop_tpl != $orig_tpl) {
                            $set_tpl = $drop_tpl;
                        }
                    }
                    $val = array('fetchlimit' => (int) $serendipity['POST']['cat']['fetchlimit'], 'template' => $set_tpl, 'categoryid' => (int) $eventData, 'lang' => $serendipity['POST']['cat']['lang'], 'futureentries' => (int) $serendipity['POST']['cat']['futureentries'], 'pass' => $serendipity['POST']['cat']['pass'], 'sort_order' => serendipity_db_escape_string($serendipity['POST']['cat']['sort_order']), 'hide_rss' => $serendipity['POST']['cat']['hide_rss']);
                    $this->setProps($eventData, $val);
                    // Update list of template categories, too.
                    //
                    // Get the list of customized category IDs, in precedence order
                    $cidstr = $this->get_config('cat_precedence', false);
                    // Only save the new precedence if we can actually
                    // manually change templatized categories precedence
                    if ($cidstr !== false) {
                        if ($cidstr) {
                            // If $cidstr is empty, this returns an array
                            // with an empty string
                            $cids = explode(',', $cidstr);
                        } else {
                            // For instance, set but empty
                            $cids = array();
                        }
                        // If it had a custom template just added, append it
                        // to the list (user can change precedence later)
                        if (!in_array($eventData, $cids) && !empty($set_tpl)) {
                            $cids[] = $eventData;
                            $cidstr = implode(',', $cids);
                            $this->set_config('cat_precedence', $cidstr);
                        }
                        // If it had a custom template just deleted, remove it
                        // from the list
                        if (in_array($eventData, $cids) && empty($set_tpl)) {
                            // Why doesn't PHP have an array_remove(item)?
                            $newcids = array();
                            foreach ($cids as $cid) {
                                if ($cid != $eventData) {
                                    $newcids[] = $cid;
                                }
                            }
                            $cidstr = implode(',', $newcids);
                            $this->set_config('cat_precedence', $cidstr);
                        }
                    }
                    break;
                    // When an entry or category is displayed, this changes the
                    // CSS to the custom template
                // When an entry or category is displayed, this changes the
                // CSS to the custom template
                case 'external_plugin':
                    $parts = explode('_', $eventData);
                    if (!empty($parts[1])) {
                        $param = (int) $parts[1];
                    } else {
                        $param = null;
                    }
                    // Shouldn't this just be a string comparison?
                    $methods = array('categorytemplate');
                    if (!in_array($parts[0], $methods)) {
                        return;
                    }
                    $cid = (int) $parts[1];
                    $serendipity['template'] = $this->fetchTemplate($cid, $serendipity['template']);
                    $css_mode = 'serendipity.css';
                    include_once S9Y_INCLUDE_PATH . 'serendipity.css.php';
                    exit;
                    break;
                    // When Serendipity tries to get the entries, check for
                    // passwords
                // When Serendipity tries to get the entries, check for
                // passwords
                case 'frontend_fetchentries':
                case 'frontend_fetchentry':
                    // Override sort order
                    if (!empty($this->sort_order)) {
                        $eventData['orderby'] = $this->sort_order . (!empty($eventData['orderby']) ? ',' : '') . $eventData['orderby'] . '/*categorytemplate*/';
                    }
                    // Password not required on search or calendar, and we
                    // don't do rss for them, either
                    if (!isset($addData['source']) || ($addData['source'] == 'search' || $addData['source'] == 'calendar')) {
                        return true;
                    }
                    // Password and RSS not required for installation
                    if (defined('IN_installer') && IN_installer === true && defined('IN_upgrader') && IN_upgrader === true) {
                        return true;
                    }
                    // Prepare to modify SQL
                    $joins = array();
                    $conds = array();
                    $addkeys = array();
                    // Password protection SQL
                    if (serendipity_db_bool($this->get_config('pass'))) {
                        $conds[] = "(ctpass.pass IS NULL OR ctpass.pass = '******' OR ctpass.pass = '')";
                        $joins[] = "LEFT OUTER JOIN {$serendipity['dbPrefix']}categorytemplates ctpass\n                            ON (ec.categoryid = ctpass.categoryid)";
                    }
                    // RSS hiding SQL
                    if ($serendipity['view'] == 'feed') {
                        $conds[] = "(e.id NOT IN (SELECT e.id FROM {$serendipity['dbPrefix']}entries AS e\n                            LEFT JOIN {$serendipity['dbPrefix']}entrycat AS ec ON ec.entryid = e.id\n                            JOIN {$serendipity['dbPrefix']}categorytemplates AS t ON ec.categoryid = t.categoryid AND hide_rss = '1'))";
                        /*
                        $q = serendipity_db_query("SELECT categoryid FROM {$serendipity['dbPrefix']}categorytemplates WHERE hide_rss = 1");
                        if (is_array($q)) {
                            $hidecats = array();
                            foreach($q as $hidden) {
                                $hidecats[] = $hidden['categoryid'];
                            }
                            $hidecats = implode(';', $hidecats);
                        }
                        if (!empty($hidecats)) {
                            $hide_sql = serendipity_getMultiCategoriesSQL($hidecats, true);
                            $conds[] = $hide_sql;
                        }
                        */
                        /*
                        $addkeys[] = "SUM(ctpass.hide_rss) as cat_hide_rss, ";
                        // Reuse password join if possible
                        if (count($joins) == 0) {
                            $joins[] = "LEFT OUTER JOIN {$serendipity['dbPrefix']}categorytemplates AS ctpass
                                ON (ec.categoryid = ctpass.categoryid)\n";
                        }
                        //$conds[] = "(cat_hide_rss IS NULL OR cat_hide_rss < 1)";
                        //$conds[] = "(ctpass.hide_rss IS NULL OR ctpass.hide_rss = 0)";
                        //$conds[] = "(SUM(ctpass.hide_rss < 1))";
                        $havings[] = '(cat_hide_rss IS NULL OR cat_hide_rss < 1)';
                        */
                    }
                    // Apply query additions
                    // Select keys
                    if (count($addkeys) > 0) {
                        $cond = implode("\n", $addkeys);
                        if (empty($eventData['select'])) {
                            $eventData['addkey'] = $cond;
                        } else {
                            $eventData['addkey'] .= $cond;
                        }
                    }
                    // Conditions
                    if (count($conds) > 0) {
                        $cond = implode(' AND ', $conds);
                        if (empty($eventData['and'])) {
                            $eventData['and'] = " WHERE {$cond} ";
                        } else {
                            $eventData['and'] .= " AND {$cond} ";
                        }
                    }
                    // Joins
                    if (count($joins) > 0) {
                        $cond = implode("\n", $joins);
                        if (empty($eventData['joins'])) {
                            $eventData['joins'] = $cond;
                        } else {
                            $eventData['joins'] .= $cond;
                        }
                    }
                    // Havings
                    if (count($havings) > 0) {
                        $cond = implode(' AND ', $havings);
                        if (empty($eventData['having'])) {
                            $eventData['having'] = "HAVING {$cond} ";
                        } else {
                            $eventData['having'] .= " AND {$cond} ";
                        }
                    }
                    return true;
                    break;
                    // Experimental code: fetch language for entry
                // Experimental code: fetch language for entry
                case 'frontend_configure':
                    // TODO: This does not work. The ID is not present! :-()
                    // $cid = $this->getID(true);
                    // $serendipity['lang']              = $this->fetchLang($cid, $serendipity['lang']);
                    return true;
                    break;
                    // When the HTML is generated, apply properties
                // When the HTML is generated, apply properties
                case 'genpage':
                    // Get the category in question
                    $cid = $this->getID();
                    $fc = $this->get_config('fixcat');
                    if ((string) $fc === 'hard') {
                        $fc = 'true';
                    }
                    if ($cid != 'default' && serendipity_db_bool($fc)) {
                        // Need this for category_name to be set.  (?)
                        $serendipity['GET']['category'] = $cid;
                        header('X-FixEntry-Cat: true');
                    }
                    // Reset s9y to use the category's properties
                    $serendipity['fetchLimit'] = $this->fetchLimit($cid, $serendipity['fetchLimit']);
                    $serendipity['showFutureEntries'] = $this->fetchFuture($cid, $serendipity['showFutureEntries']);
                    $serendipity['template'] = $this->fetchTemplate($cid, $serendipity['template']);
                    $this->sort_order = $this->fetchSortOrder($cid, $this->get_config('sort_order'));
                    // Set the template options
                    if (!$this->usesDefaultTemplate) {
                        $serendipity['smarty_vars']['template_option'] = $serendipity['template'] . '_' . $cid;
                    }
                    // Check for password
                    if ($cid != 'default' && serendipity_db_bool($this->get_config('pass')) && $this->fetchProp($cid, 'pass') != '') {
                        if (!isset($_SERVER['PHP_AUTH_PW']) || $_SERVER['PHP_AUTH_PW'] != $this->fetchProp($cid, 'pass')) {
                            header('WWW-Authenticate: Basic realm="' . PLUGIN_CATEGORYTEMPLATES_PASS_USER . '"');
                            header("HTTP/1.0 401 Unauthorized");
                            header('Status: 401 Unauthorized');
                            echo PLUGIN_CATEGORYTEMPLATES_PASS_USER;
                            exit;
                        } else {
                            $this->current_pw = $_SERVER['PHP_AUTH_PW'];
                        }
                    }
                    // Set the template stylesheet
                    $serendipity['smarty_vars']['head_link_stylesheet'] = serendipity_rewriteURL('plugin/categorytemplate_' . $cid, 'baseURL', true);
                    return true;
                    break;
                    // When the back end is displayed, use the custom template, too
                // When the back end is displayed, use the custom template, too
                case 'backend_sidebar_entries_event_display_cattemplate':
                    if (empty($serendipity['GET']['cat_template'])) {
                        $serendipity['GET']['cat_template'] = $serendipity['POST']['cat_template'];
                    }
                    if (empty($serendipity['GET']['catid'])) {
                        $serendipity['GET']['catid'] = $serendipity['POST']['catid'];
                    }
                    $old = $serendipity['GET']['adminModule'];
                    $serendipity['GET']['adminModule'] = 'templates';
                    $this->template_options($serendipity['GET']['cat_template'], $serendipity['GET']['catid']);
                    $serendipity['GET']['adminModule'] = $old;
                    return true;
                    break;
                default:
                    return true;
                    break;
            }
        } else {
            return false;
        }
    }
Example #5
0
    echo '</form><br />';
    serendipity_plugin_api::hook_event('backend_templates_configuration_bottom', $template_config);
} else {
    echo '<p>' . STYLE_OPTIONS_NONE . '</p>';
    serendipity_plugin_api::hook_event('backend_templates_configuration_none', $template_config);
}
echo '<h3>' . SELECT_TEMPLATE . '</h3>';
?>
<br />
<?php 
$i = 0;
$stack = array();
serendipity_plugin_api::hook_event('backend_templates_fetchlist', $stack);
$themes = serendipity_fetchTemplates();
foreach ($themes as $theme) {
    $stack[$theme] = serendipity_fetchTemplateInfo($theme);
}
ksort($stack);
foreach ($stack as $theme => $info) {
    $i++;
    /* Sorry, but we don't display engines */
    if (strtolower($info['engine']) == 'yes') {
        continue;
    }
    $preview = '';
    $preview_link = false;
    if (file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $theme . '/preview_fullsize.jpg')) {
        $preview .= '<a href="' . $serendipity['baseURL'] . $serendipity['templatePath'] . $theme . '/preview_fullsize.jpg" target="_blank">';
        $preview_link = true;
    } elseif (!empty($info['preview_fullsizeURL'])) {
        $preview .= '<a href="' . $info['preview_fullsizeURL'] . '" target="_blank">';
 function forkTemplate()
 {
     global $serendipity;
     $template_path = $serendipity['serendipity_path'] . $serendipity['templatePath'];
     $cur_template = $serendipity['template'];
     //fork only if not already forked
     $info_txt = file_get_contents($template_path . $cur_template . '/info.txt');
     $forked = false;
     if (strpos($info_txt, 'Fork_of:') !== false) {
         $forked = true;
     }
     if (!$forked) {
         $fork_template = $cur_template . '_fork';
         if (is_writable($template_path)) {
             if (!is_dir($template_path . $fork_template)) {
                 $this->copy_directory($template_path . $cur_template, $template_path . $fork_template);
                 $info_txt = preg_replace('/Name: (.*)/', 'Name: ${1}_fork', $info_txt);
                 $info_txt = $info_txt . "\nFork_of: {$cur_template}";
                 file_put_contents($template_path . $fork_template . '/info.txt', $info_txt);
             }
             //Now that the fork is created we need to set it instantly
             //but only if copying succeeded
             if (is_dir($template_path . $fork_template)) {
                 $themeInfo = serendipity_fetchTemplateInfo(function_exists('serendipity_specialchars') ? serendipity_specialchars($fork_template) : htmlspecialchars($fork_template, ENT_COMPAT, LANG_CHARSET));
                 serendipity_set_config_var('template', function_exists('serendipity_specialchars') ? serendipity_specialchars($fork_template) : htmlspecialchars($fork_template, ENT_COMPAT, LANG_CHARSET));
                 serendipity_set_config_var('template_engine', isset($themeInfo['engine']) ? $themeInfo['engine'] : 'default');
             }
         } else {
             echo 'Error: Template Directory not writeable';
             return false;
         }
     }
     return true;
 }
 function getTemplates($dir = '/home/garvin/cvs/serendipity/additional_themes/')
 {
     $this->i18n = false;
     $ret = serendipity_traversePath($dir, '', true, null, 1, 1);
     $this->xmlData['template'] = array();
     $x =& $this->xmlData['template'];
     $x[] = '<?xml version="1.0" encoding="UTF-8" ?>';
     $x[] = '<!--  -->' . "\n";
     $x[] = '<packages>';
     $_blacklist = explode("\n", file_get_contents($dir . '/blacklist.txt'));
     $blacklist = array();
     foreach ($_blacklist as $idx => $blackline) {
         $blackline = trim($blackline);
         if (empty($blackline)) {
             continue;
         }
         if ($blackline[0] == '#') {
             continue;
         }
         $blacklist[$blackline] = true;
     }
     $t = array();
     $nametofile = array();
     foreach ($ret as $idx => $path) {
         $info = array();
         if (file_exists($dir . $path['name'] . '/info.txt')) {
             $info = serendipity_fetchTemplateInfo($path['name'], $dir);
         }
         if (empty($info['name'])) {
             continue;
         }
         $olddir = getcwd();
         chdir($dir);
         $info['files'] = $this->get_files($path['name']);
         chdir($olddir);
         $td = '';
         $td .= '<div class="template_summary">' . $this->encode($info['name']) . '<br />' . $this->encode($info['summary']) . '</div>';
         $td .= '<div class="template_name">' . $this->encode($path['name']) . '</template>';
         if (empty($info['version'])) {
             $info['version'] = '1.0';
         }
         if (empty($info['license'])) {
             $info['license'] = 'N/A (=GPL)';
         }
         $td .= '<div class="template_version">' . $this->encode(VERSION . ' ' . $info['version']) . '(' . $this->encode($info['license']) . ', ' . $this->encode($info['date']) . ')</div>';
         $td .= '<div class="template_maintainers">' . $this->encode($info['author']) . '</div>';
         if (!empty($info['require serendipity'])) {
             $td .= '<div class="template_requirements">Serendipity &gt;= ' . $this->encode($info['require serendipity']) . '</div>';
         }
         if (!isset($blacklist[$path['name']])) {
             $td .= '<a style="font-weight: bold; margin: 0px auto" href="http://blog.s9y.org/index.php?user_template=additional_themes/' . $path['name'] . '">See demo on blog.s9y.org</a>' . "\n";
         }
         $td .= '<div class="template_description"><span class="template_download"><a href="cvs/additional_themes/' . $path['name'] . '.zip"><img alt="Download" src="cvs/additional_themes/' . $path['name'] . '/preview_fullsize.jpg" width="100%" /></a></div>' . $this->encode($info['description']) . '</div>';
         $x[] = '<package version="1.0">';
         $x[] = '<name>' . $this->encode($info['name'], true) . '</name>';
         $x[] = '<template>' . $this->encode($path['name'], true) . '</template>';
         $x[] = '<license>' . $this->encode($info['license'], true) . '</license>';
         $x[] = '<summary>' . $this->encode($info['summary']) . '</summary>';
         $x[] = '<description>' . $this->encode($info['description']) . '</description>';
         $x[] = '<maintainers><maintainer><name>' . $this->encode($info['author'], true) . '</name><role>lead</role></maintainer></maintainers>';
         $x[] = '<release>';
         $x[] = '  <version>' . $this->encode($info['version'], true) . '</version>';
         $x[] = '  <requirements:s9yVersion>' . $this->encode($info['require serendipity'], true) . '</requirements:s9yVersion>';
         $x[] = '  <date>' . $this->encode($info['date'], true) . '</date>';
         $x[] = '  <filelist>';
         $x[] = $info['files']['xml'];
         $x[] = '  </filelist>';
         $x[] = '  <serendipityFilelist>';
         foreach ($info['files']['full'] as $file) {
             $x[] = '    <file>' . $file . '</file>';
         }
         $x[] = '  </serendipityFilelist>';
         $x[] = '</release>';
         $x[] = '</package>';
         $t[$info['name']] .= '<div class="template">' . $td . '</div>' . "\n";
         $nametofile[$info['name']] = $path['name'];
     }
     $x[] = '</packages>';
     ksort($t);
     $theme_li = '';
     foreach ($t as $theme => $html) {
         $theme_li .= '<li><a href="index.php?mode=template_' . $nametofile[$theme] . '">' . $theme . '</a></li>' . "\n";
         $fp = fopen('homepage/template_' . $nametofile[$theme] . '.htm', 'w');
         fwrite($fp, $html);
         fclose($fp);
     }
     $fp = fopen('homepage/template_all.htm', 'w');
     fwrite($fp, implode("\n", $t));
     fclose($fp);
     $fp = fopen('homepage/box_groups_template.htm', 'w');
     fwrite($fp, $theme_li);
     fclose($fp);
 }