Example #1
0
/**
 * Performs searching and returns results.
 *
 * This is now performed by doArticles().
 *
 * @param      string $q
 * @deprecated in 4.0.4
 * @see        doArticles()
 */
function search($q)
{
    global $prefs;
    $url = $prefs['siteurl'];
    extract($prefs);
    $s_filter = filterSearch();
    $form = fetch('form', 'txp_form', 'name', 'search_results');
    // Lose this eventually - only used if search_results form is missing.
    $form = !$form ? legacy_form() : $form;
    $rs = safe_rows("*, ID AS thisid, UNIX_TIMESTAMP(Posted) AS posted, Title AS title,\n        MATCH (Title,Body) AGAINST ('{$q}') AS score", 'textpattern', "(Title RLIKE '{$q}' OR Body RLIKE '{$q}') {$s_filter}\n        AND Status = 4 AND Posted <= " . now('posted') . " ORDER BY score DESC LIMIT 40");
    if ($rs) {
        $result_rows = count($rs);
        $text = $result_rows == 1 ? gTxt('article_found') : gTxt('articles_found');
    } else {
        $result_rows = 0;
        $text = gTxt('articles_found');
    }
    $results[] = graf($result_rows . ' ' . $text);
    if ($result_rows > 0) {
        foreach ($rs as $a) {
            extract($a);
            $result_date = safe_strftime($archive_dateformat, $posted);
            $uTitle = $url_title ? $url_title : stripSpace($Title);
            $hurl = permlinkurl($a);
            $result_url = '<a href="' . $hurl . '">' . $hurl . '</a>';
            $result_title = '<a href="' . $hurl . '">' . $Title . '</a>';
            $result = preg_replace("/>\\s*</", "> <", $Body_html);
            preg_match_all("/\\s.{1,50}" . preg_quote($q) . ".{1,50}\\s/i", $result, $concat);
            $concat = join(" ... ", $concat[0]);
            $concat = strip_tags($concat);
            $concat = preg_replace('/^[^>]+>/U', "", $concat);
            $concat = preg_replace("/({$q})/i", "<strong>\$1</strong>", $concat);
            $result_excerpt = $concat ? "... " . $concat . " ..." : '';
            $glob['search_result_title'] = $result_title;
            $glob['search_result_excerpt'] = $result_excerpt;
            $glob['search_result_url'] = $result_url;
            $glob['search_result_date'] = $result_date;
            $GLOBALS['this_result'] = $glob;
            $thisresult = $form;
            $results[] = parse($thisresult);
        }
    }
    return is_array($results) ? join('', $results) : '';
}
Example #2
0
function search($q)
{
    global $prefs;
    $url = $prefs['siteurl'];
    extract($prefs);
    $s_filter = filterSearch();
    $form = fetch('form', 'txp_form', 'name', 'search_results');
    // lose this eventually - only used if search_results form is missing
    $form = !$form ? legacy_form() : $form;
    $rs = safe_rows("*, ID as thisid, unix_timestamp(Posted) as posted, Title as title,\n\t\t\tmatch (Title,Body) against ('{$q}') as score", "textpattern", "(Title rlike '{$q}' or Body rlike '{$q}') {$s_filter}\n\t\t\tand Status = 4 and Posted <=now() order by score desc limit 40");
    if ($rs) {
        $result_rows = count($rs);
        $text = $result_rows == 1 ? gTxt('article_found') : gTxt('articles_found');
    } else {
        $result_rows = 0;
        $text = gTxt('articles_found');
    }
    $results[] = graf($result_rows . ' ' . $text);
    if ($result_rows > 0) {
        foreach ($rs as $a) {
            extract($a);
            $result_date = safe_strftime($archive_dateformat, $posted);
            $uTitle = $url_title ? $url_title : stripSpace($Title);
            $hurl = permlinkurl($a);
            $result_url = '<a href="' . $hurl . '">' . $hurl . '</a>';
            $result_title = '<a href="' . $hurl . '">' . $Title . '</a>';
            $result = preg_replace("/>\\s*</", "> <", $Body_html);
            preg_match_all("/\\s.{1,50}" . preg_quote($q) . ".{1,50}\\s/i", $result, $concat);
            $concat = join(" ... ", $concat[0]);
            $concat = strip_tags($concat);
            $concat = preg_replace('/^[^>]+>/U', "", $concat);
            $concat = preg_replace("/({$q})/i", "<strong>\$1</strong>", $concat);
            $result_excerpt = $concat ? "... " . $concat . " ..." : '';
            $glob['search_result_title'] = $result_title;
            $glob['search_result_excerpt'] = $result_excerpt;
            $glob['search_result_url'] = $result_url;
            $glob['search_result_date'] = $result_date;
            $GLOBALS['this_result'] = $glob;
            $thisresult = $form;
            $results[] = parse($thisresult);
        }
    }
    return is_array($results) ? join('', $results) : '';
}
Example #3
0
function link_list($message = '')
{
    global $step, $link_list_pageby;
    extract(get_prefs());
    extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
    $dir = $dir == 'desc' ? 'desc' : 'asc';
    switch ($sort) {
        case 'id':
            $sort_sql = 'id ' . $dir;
            break;
        case 'name':
            $sort_sql = 'linksort ' . $dir . ', id asc';
            break;
        case 'description':
            $sort_sql = 'description ' . $dir . ', id asc';
            break;
        case 'category':
            $sort_sql = 'category ' . $dir . ', id asc';
            break;
        case 'date':
            $sort_sql = 'date ' . $dir . ', id asc';
            break;
        default:
            $dir = 'asc';
            $sort_sql = 'linksort asc';
            break;
    }
    $switch_dir = $dir == 'desc' ? 'asc' : 'desc';
    $criteria = 1;
    if ($search_method and $crit) {
        $crit_escaped = doSlash($crit);
        $critsql = array('id' => "id = '{$crit_escaped}'", 'name' => "linkname like '%{$crit_escaped}%'", 'description' => "description like '%{$crit_escaped}%'", 'category' => "category like '%{$crit_escaped}%'");
        if (array_key_exists($search_method, $critsql)) {
            $criteria = $critsql[$search_method];
            $limit = 500;
        } else {
            $search_method = '';
            $crit = '';
        }
    } else {
        $search_method = '';
        $crit = '';
    }
    $total = getCount('txp_link', $criteria);
    if ($total < 1) {
        if ($criteria != 1) {
            echo n . link_search_form($crit, $search_method) . n . graf(gTxt('no_results_found'), ' style="text-align: center;"');
        } else {
            echo n . graf(gTxt('no_links_recorded'), ' style="text-align: center;"');
        }
        return;
    }
    $limit = max(@$link_list_pageby, 15);
    list($page, $offset, $numPages) = pager($total, $limit, $page);
    echo link_search_form($crit, $search_method);
    $rs = safe_rows_start('*, unix_timestamp(date) as uDate', 'txp_link', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}");
    if ($rs) {
        echo n . n . '<form action="index.php" method="post" name="longform" onsubmit="return verify(\'' . gTxt('are_you_sure') . '\')">', startTable('list') . n . tr(column_head('ID', 'id', 'link', true, $switch_dir, $crit, $search_method) . hCell() . column_head('link_name', 'name', 'link', true, $switch_dir, $crit, $search_method) . column_head('description', 'description', 'link', true, $switch_dir, $crit, $search_method) . column_head('link_category', 'category', 'link', true, $switch_dir, $crit, $search_method) . column_head('date', 'date', 'link', true, $switch_dir, $crit, $search_method) . hCell());
        while ($a = nextRow($rs)) {
            extract($a);
            $edit_url = '?event=link' . a . 'step=link_edit' . a . 'id=' . $id . a . 'sort=' . $sort . a . 'dir=' . $dir . a . 'page=' . $page . a . 'search_method=' . $search_method . a . 'crit=' . $crit;
            echo tr(n . td($id, 20) . td(n . '<ul>' . n . t . '<li>' . href(gTxt('edit'), $edit_url) . '</li>' . n . t . '<li>' . href(gTxt('view'), $url) . '</li>' . n . '</ul>', 35) . td(href($linkname, $edit_url), 125) . td($description, 150) . td('<span title="' . fetch_category_title($category, 'link') . '">' . $category . '</span>', 125) . td(safe_strftime('%d %b %Y %I:%M %p', $uDate), 75) . td(fInput('checkbox', 'selected[]', $id)));
        }
        echo n . n . tr(tda(select_buttons() . link_multiedit_form($page, $sort, $dir, $crit, $search_method), ' colspan="7" style="text-align: right; border: none;"')) . endTable() . '</form>' . n . nav_form('link', $page, $numPages, $sort, $dir, $crit, $search_method) . pageby_form('link', $link_list_pageby);
    }
}
Example #4
0
/**
 * Generates a &lt;table&gt; of every language that Textpattern supports.
 *
 * If requested with HTTP POST parameter 'force' set anything other than 'file',
 * outputs any errors in RPC server connection.
 *
 * @param string|array $message The activity message
 */
function list_languages($message = '')
{
    require_once txpath . '/lib/IXRClass.php';
    $active_lang = safe_field("val", 'txp_prefs', "name = 'language'");
    $lang_form = tag(form(tag(gTxt('active_language'), 'label', array('for' => 'language')) . languages('language', $active_lang) . eInput('lang') . sInput('save_language')), 'div', array('class' => 'txp-control-panel'));
    $client = new IXR_Client(RPC_SERVER);
    //    $client->debug = true;
    $available_lang = array();
    $rpc_connect = false;
    $show_files = false;
    // Get items from RPC.
    @set_time_limit(90);
    // TODO: 90 seconds: seriously?
    if ($client->query('tups.listLanguages', get_pref('blog_uid'))) {
        $rpc_connect = true;
        $response = $client->getResponse();
        foreach ($response as $language) {
            $available_lang[$language['language']]['rpc_lastmod'] = gmmktime($language['lastmodified']->hour, $language['lastmodified']->minute, $language['lastmodified']->second, $language['lastmodified']->month, $language['lastmodified']->day, $language['lastmodified']->year);
        }
    } elseif (gps('force') != 'file') {
        $msg = gTxt('rpc_connect_error') . "<!--" . $client->getErrorCode() . ' ' . $client->getErrorMessage() . "-->";
    }
    // Get items from Filesystem.
    $files = get_lang_files();
    if (is_array($files) && !empty($files)) {
        foreach ($files as $file) {
            if ($fp = @fopen(txpath . DS . 'lang' . DS . $file, 'r')) {
                $name = preg_replace('/\\.(txt|textpack)$/i', '', $file);
                $firstline = fgets($fp, 4069);
                fclose($fp);
                if (strpos($firstline, '#@version') !== false) {
                    @(list($fversion, $ftime) = explode(';', trim(substr($firstline, strpos($firstline, ' ', 1)))));
                } else {
                    $fversion = $ftime = null;
                }
                $available_lang[$name]['file_note'] = isset($fversion) ? $fversion : 0;
                $available_lang[$name]['file_lastmod'] = isset($ftime) ? $ftime : 0;
            }
        }
    }
    // Get installed items from the database.
    // We need a value here for the language itself, not for each one of the rows.
    $rows = safe_rows("lang, UNIX_TIMESTAMP(MAX(lastmod)) AS lastmod", 'txp_lang', "1 = 1 GROUP BY lang ORDER BY lastmod DESC");
    $installed_lang = array();
    foreach ($rows as $language) {
        $available_lang[$language['lang']]['db_lastmod'] = $language['lastmod'];
        if ($language['lang'] != $active_lang) {
            $installed_lang[] = $language['lang'];
        }
    }
    $list = '';
    // Create the language table components.
    foreach ($available_lang as $langname => $langdat) {
        $file_updated = isset($langdat['db_lastmod']) && @$langdat['file_lastmod'] > $langdat['db_lastmod'];
        $rpc_updated = @$langdat['rpc_lastmod'] > @$langdat['db_lastmod'];
        $rpc_install = tda($rpc_updated ? strong(eLink('lang', 'get_language', 'lang_code', $langname, isset($langdat['db_lastmod']) ? gTxt('update') : gTxt('install'), 'updating', isset($langdat['db_lastmod']), '')) . n . span(safe_strftime('%d %b %Y %X', @$langdat['rpc_lastmod']), array('class' => 'date modified')) : (isset($langdat['rpc_lastmod']) ? gTxt('up_to_date') : '-') . (isset($langdat['db_lastmod']) ? n . span(safe_strftime('%d %b %Y %X', $langdat['db_lastmod']), array('class' => 'date modified')) : ''), isset($langdat['db_lastmod']) && $rpc_updated ? ' class="highlight lang-value"' : ' class="lang-value"');
        $lang_file = tda(isset($langdat['file_lastmod']) ? strong(eLink('lang', 'get_language', 'lang_code', $langname, $file_updated ? gTxt('update') : gTxt('install'), 'force', 'file', '')) . n . span(safe_strftime(get_pref('archive_dateformat'), $langdat['file_lastmod']), array('class' => 'date ' . ($file_updated ? 'created' : 'modified'))) : '-', ' class="lang-value languages_detail' . (isset($langdat['db_lastmod']) && $rpc_updated ? ' highlight' : '') . '"');
        $list .= tr(hCell(gTxt($langname), '', isset($langdat['db_lastmod']) && $rpc_updated ? ' class="highlight lang-label" scope="row"' : ' class="lang-label" scope="row"') . n . $rpc_install . n . $lang_file . tda(in_array($langname, $installed_lang) ? dLink('lang', 'remove_language', 'lang_code', $langname, 1) : '-', ' class="languages_detail' . (isset($langdat['db_lastmod']) && $rpc_updated ? ' highlight' : '') . '"')) . n;
    }
    // Output table and content.
    pagetop(gTxt('tab_languages'), $message);
    echo n . tag(hed(gTxt('tab_languages'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')) . n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => 'language_container'));
    if (isset($msg) && $msg) {
        echo graf('<span class="ui-icon ui-icon-closethick"></span> ' . $msg, array('class' => 'alert-block error'));
    }
    echo $lang_form, n . tag(toggle_box('languages_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(gTxt('language'), '', ' scope="col"') . hCell(gTxt('from_server') . popHelp('install_lang_from_server'), '', ' scope="col"') . hCell(gTxt('from_file') . popHelp('install_lang_from_file'), '', ' class="languages_detail" scope="col"') . hCell(gTxt('remove_lang') . popHelp('remove_lang'), '', ' class="languages_detail" scope="col"')) . n . tag_end('thead') . n . tag_start('tbody') . $list . n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . hed(gTxt('install_from_textpack'), 2) . n . tag(form('<label for="textpack-install">' . gTxt('install_textpack') . '</label>' . popHelp('get_textpack') . n . '<textarea class="code" id="textpack-install" name="textpack" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_SMALL . '" dir="ltr"></textarea>' . fInput('submit', 'install_new', gTxt('upload')) . eInput('lang') . sInput('get_textpack'), '', '', 'post', '', '', 'text_uploader'), 'div', array('class' => 'txp-control-panel')) . n . tag_end('div');
}
Example #5
0
function atom()
{
    global $thisarticle;
    extract($GLOBALS['prefs']);
    define("t_texthtml", ' type="text/html"');
    define("t_text", ' type="text"');
    define("t_html", ' type="html"');
    define("t_xhtml", ' type="xhtml"');
    define('t_appxhtml', ' type="xhtml"');
    define("r_relalt", ' rel="alternate"');
    define("r_relself", ' rel="self"');
    $area = doSlash(gps('area'));
    extract(doSlash(gpsa(array('category', 'section', 'limit'))));
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    $sitename .= $section ? ' - ' . $section : '';
    $sitename .= $category ? ' - ' . $category : '';
    $pub = safe_row("RealName, email", "txp_users", "privs=1");
    $out[] = tag(escape_output($sitename), 'title', t_text);
    $out[] = tag(escape_output($site_slogan), 'subtitle', t_text);
    $out[] = '<link' . r_relself . ' href="' . pagelinkurl(array('atom' => 1, 'area' => $area, 'section' => $section, 'category' => $category, 'limit' => $limit)) . '" />';
    $out[] = '<link' . r_relalt . t_texthtml . ' href="' . hu . '" />';
    $articles = array();
    //Atom feeds with mail or domain name
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    $out[] = tag('tag:' . $mail_or_domain . ',' . $blog_time_uid . ':' . $blog_uid . ($section ? '/' . $section : '') . ($category ? '/' . $category : ''), 'id');
    $out[] = tag('Textpattern', 'generator', ' uri="http://textpattern.com/" version="' . $version . '"');
    $out[] = tag(safe_strftime("w3cdtf", $last), 'updated');
    $auth[] = tag($pub['RealName'], 'name');
    $auth[] = $include_email_atom ? tag(eE($pub['email']), 'email') : '';
    $auth[] = tag(hu, 'uri');
    $out[] = tag(n . t . t . join(n . t . t, $auth) . n, 'author');
    if (!$area or $area == 'article') {
        $sfilter = $section ? "and Section = '" . $section . "'" : '';
        $cfilter = $category ? "and (Category1='" . $category . "' or Category2='" . $category . "')" : '';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $frs = safe_column("name", "txp_section", "in_rss != '1'");
        $query = array();
        foreach ($frs as $f) {
            $query[] = "and Section != '" . doSlash($f) . "'";
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $rs = safe_rows_start("*, \n\t\t\t\tID as thisid, \n\t\t\t\tunix_timestamp(Posted) as uPosted,\n\t\t\t\tunix_timestamp(LastMod) as uLastMod", "textpattern", "Status=4 and Posted <= now() " . join(' ', $query) . "order by Posted desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event('atom_entry');
                $e = array();
                $a['posted'] = $uPosted;
                if ($show_comment_count_in_feed) {
                    $count = $comments_count > 0 ? ' [' . $comments_count . ']' : '';
                } else {
                    $count = '';
                }
                $thisauthor = get_author_name($AuthorID);
                $e['thisauthor'] = tag(n . t . t . t . tag(htmlspecialchars($thisauthor), 'name') . n . t . t, 'author');
                $e['issued'] = tag(safe_strftime('w3cdtf', $uPosted), 'published');
                $e['modified'] = tag(safe_strftime('w3cdtf', $uLastMod), 'updated');
                $escaped_title = escape_output($Title);
                $e['title'] = tag($escaped_title . $count, 'title', t_html);
                $permlink = permlinkurl($a);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $permlink . '" />';
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'id');
                $e['category1'] = trim($Category1) ? '<category term="' . htmlspecialchars($Category1) . '" />' : '';
                $e['category2'] = trim($Category2) ? '<category term="' . htmlspecialchars($Category2) . '" />' : '';
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    # short feed: use body as summary if there's no excerpt
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if (trim($content)) {
                    $e['content'] = tag(n . escape_cdata($content) . n, 'content', t_html);
                }
                if (trim($summary)) {
                    $e['summary'] = tag(n . escape_cdata($summary) . n, 'summary', t_html);
                }
                $articles[$ID] = tag(n . t . t . join(n . t . t, $e) . n . $cb, 'entry');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uLastMod;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category='" . $category . "'" : '1';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $rs = safe_rows_start("*", "txp_link", "{$cfilter} order by date desc, id desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $e['title'] = tag(htmlspecialchars($linkname), 'title', t_html);
                $e['content'] = tag(n . htmlspecialchars($description) . n, 'content', t_html);
                $url = preg_replace("/^\\/(.*)/", "https?://{$siteurl}/\$1", $url);
                $url = preg_replace("/&((?U).*)=/", "&amp;\\1=", $url);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $url . '" />';
                $e['issued'] = tag(safe_strftime('w3cdtf', strtotime($date)), 'published');
                $e['modified'] = tag(gmdate('Y-m-d\\TH:i:s\\Z', strtotime($date)), 'updated');
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $id, 'id');
                $articles[$id] = tag(n . t . t . join(n . t . t, $e) . n, 'entry');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!empty($articles)) {
        //turn on compression if we aren't using it already
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            @ob_start("ob_gzhandler");
        }
        handle_lastmod();
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        $imsd = $hims ? strtotime($hims) : 0;
        if ($imsd >= $last) {
            txp_status_header("304 Not Modified");
            exit;
        }
        header("Last-Modified: " . gmdate('D, d M Y H:i:s \\G\\M\\T', $last));
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id])) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } else {
            if (isset($cut_etag)) {
                header("Vary: If-None-Match");
            } else {
                if (isset($cut_time)) {
                    header("Vary: If-Modified-Since");
                }
            }
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            header("HTTP/1.1 304 Not Modified");
            exit;
        }
        if ($etag) {
            header('ETag: "' . $etag . '"');
        }
        if ($cutarticles) {
            //header("HTTP/1.1 226 IM Used");
            //This should be used as opposed to 200, but Apache doesn't like it.
            //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
        $out = array_merge($out, $articles);
        header('Content-type: application/atom+xml; charset=utf-8');
        return chr(60) . '?xml version="1.0" encoding="UTF-8"?' . chr(62) . n . '<feed xml:lang="' . $language . '" xmlns="http://www.w3.org/2005/Atom">' . join(n, $out) . '</feed>';
    }
}
Example #6
0
/**
 * The main author list.
 *
 * @param string|array $message The activity message
 */
function author_list($message = '')
{
    global $txp_user, $author_list_pageby;
    pagetop(gTxt('tab_site_admin'), $message);
    if (is_disabled('mail')) {
        echo graf(span(null, array('class' => 'ui-icon ui-icon-alert')) . ' ' . gTxt('warn_mail_unavailable'), array('class' => 'alert-block warning'));
    }
    echo hed(gTxt('tab_site_admin'), 1, array('class' => 'txp-heading'));
    echo n . '<div id="users_control" class="txp-control-panel">';
    $buttons = array();
    // Change password button.
    $buttons[] = sLink('admin', 'new_pass_form', gTxt('change_password'));
    if (!has_privs('admin.edit')) {
        // Change email address button.
        $buttons[] = sLink('admin', 'change_email_form', gTxt('change_email_address'));
    } else {
        // New author button.
        $buttons[] = sLink('admin', 'author_edit', gTxt('add_new_author'));
    }
    echo graf(join(n, $buttons), array('class' => 'txp-buttons'));
    // User list.
    if (has_privs('admin.list')) {
        extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
        if ($sort === '') {
            $sort = get_pref('admin_sort_column', 'name');
        }
        if ($dir === '') {
            $dir = get_pref('admin_sort_dir', 'asc');
        }
        $dir = $dir == 'desc' ? 'desc' : 'asc';
        if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) {
            $sort = 'name';
        }
        $sort_sql = $sort . ' ' . $dir;
        set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE);
        set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE);
        $switch_dir = $dir == 'desc' ? 'asc' : 'desc';
        $criteria = 1;
        if ($search_method and $crit != '') {
            $verbatim = preg_match('/^"(.*)"$/', $crit, $m);
            $crit_escaped = $verbatim ? doSlash($m[1]) : doLike($crit);
            $critsql = $verbatim ? array('id' => "user_id in ('" . join("','", do_list($crit_escaped)) . "')", 'login' => "name = '{$crit_escaped}'", 'real_name' => "RealName = '{$crit_escaped}'", 'email' => "email = '{$crit_escaped}'", 'privs' => "convert(privs, char) in ('" . join("','", do_list($crit_escaped)) . "')") : array('id' => "user_id in ('" . join("','", do_list($crit_escaped)) . "')", 'login' => "name like '%{$crit_escaped}%'", 'real_name' => "RealName like '%{$crit_escaped}%'", 'email' => "email like '%{$crit_escaped}%'", 'privs' => "convert(privs, char) in ('" . join("','", do_list($crit_escaped)) . "')");
            if (array_key_exists($search_method, $critsql)) {
                $criteria = $critsql[$search_method];
            } else {
                $search_method = '';
                $crit = '';
            }
        } else {
            $search_method = '';
            $crit = '';
        }
        $criteria .= callback_event('admin_criteria', 'author_list', 0, $criteria);
        $total = getCount('txp_users', $criteria);
        if ($total < 1) {
            if ($criteria != 1) {
                echo n . author_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>';
            }
            return;
        }
        $limit = max($author_list_pageby, 15);
        list($page, $offset, $numPages) = pager($total, $limit, $page);
        $use_multi_edit = has_privs('admin.edit') && safe_count('txp_users', '1=1') > 1;
        echo author_search_form($crit, $search_method) . '</div>';
        $rs = safe_rows_start('*, unix_timestamp(last_access) as last_login', 'txp_users', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}");
        if ($rs) {
            echo n . tag_start('div', array('id' => 'users_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'users_form', 'class' => 'multi_edit_form', 'method' => 'post', 'name' => 'longform')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(($use_multi_edit ? hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') : hCell('', '', ' scope="col" class="txp-list-col-multi-edit"')) . column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-login-name name') . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', ('RealName' == $sort ? "{$dir} " : '') . 'txp-list-col-real-name name') . column_head('email', 'email', 'admin', true, $switch_dir, '', '', ('email' == $sort ? "{$dir} " : '') . 'txp-list-col-email') . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', ('privs' == $sort ? "{$dir} " : '') . 'txp-list-col-privs') . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', ('last_login' == $sort ? "{$dir} " : '') . 'txp-list-col-last-login date')) . n . tag_end('thead') . n . tag_start('tbody');
            while ($a = nextRow($rs)) {
                extract(doSpecial($a));
                echo tr(td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name'], 'checkbox') : '', '', 'txp-list-col-multi-edit') . hCell(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, $name) : $name, '', ' scope="row" class="txp-list-col-login-name name"') . td($RealName, '', 'txp-list-col-real-name name') . td(href($email, 'mailto:' . $email), '', 'txp-list-col-email') . td(get_priv_level($privs), '', 'txp-list-col-privs') . td($last_login ? safe_strftime('%b&#160;%Y', $last_login) : '', '', 'txp-list-col-last-login date'));
            }
            echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . ($use_multi_edit ? author_multiedit_form($page, $sort, $dir, $crit, $search_method) : '') . tInput() . n . tag_end('form') . n . tag_start('div', array('id' => 'users_navigation', 'class' => 'txp-navigation')) . pageby_form('admin', $author_list_pageby) . nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method) . n . tag_end('div') . n . tag_end('div');
        }
    } else {
        echo n . tag_end('div');
    }
}
Example #7
0
 function write_trace()
 {
     global $prefs;
     $file = $prefs['tempdir'] . DS . 'evaluator_trace.php';
     if (!file_exists($file)) {
         $fp = fopen($file, 'wb');
         if ($fp) {
             fwrite($fp, "<?php return; ?>\n" . "This trace-file tracks saved comments. (created " . safe_strftime($prefs['archive_dateformat'], time()) . ")\n" . "Format is: Type; Probability; Message (Type can be -1 => spam, 0 => moderate, 1 => visible)\n\n");
         }
     } else {
         $fp = fopen($file, 'ab');
     }
     if ($fp) {
         fwrite($fp, implode("\n", $this->txpspamtrace));
         fwrite($fp, "\n  RESULT: " . $this->get_result() . "\n\n");
         fclose($fp);
     }
 }
Example #8
0
/**
 * Generates and outputs an Atom feed.
 *
 * This function can only be called once on a page. It outputs an Atom feed
 * based on the requested URL parameters. Accepts HTTP GET parameters 'limit',
 * 'area', 'section' and 'category'.
 */
function atom()
{
    global $thisarticle, $prefs;
    set_error_handler('feedErrorHandler');
    ob_clean();
    extract($prefs);
    $last = fetch("UNIX_TIMESTAMP(val)", 'txp_prefs', 'name', 'lastmod');
    extract(doSlash(gpsa(array('limit', 'area'))));
    // Build filter criteria from a comma-separated list of sections
    // and categories.
    $feed_filter_limit = get_pref('feed_filter_limit', 10);
    $section = gps('section');
    $category = gps('category');
    if (!is_scalar($section) || !is_scalar($category)) {
        txp_die('Not Found', 404);
    }
    $section = $section ? array_slice(do_list_unique($section), 0, $feed_filter_limit) : array();
    $category = $category ? array_slice(do_list_unique($category), 0, $feed_filter_limit) : array();
    $st = array();
    foreach ($section as $s) {
        $st[] = fetch_section_title($s);
    }
    $ct = array();
    foreach ($category as $c) {
        $ct[] = fetch_category_title($c);
    }
    $sitename .= $section ? ' - ' . join(' - ', $st) : '';
    $sitename .= $category ? ' - ' . join(' - ', $ct) : '';
    $pub = safe_row("RealName, email", 'txp_users', "privs = 1");
    // Feed header.
    $out[] = tag(htmlspecialchars($sitename), 'title', t_text);
    $out[] = tag(htmlspecialchars($site_slogan), 'subtitle', t_text);
    $out[] = '<link' . r_relself . ' href="' . pagelinkurl(array('atom' => 1, 'area' => $area, 'section' => $section, 'category' => $category, 'limit' => $limit)) . '" />';
    $out[] = '<link' . r_relalt . t_texthtml . ' href="' . hu . '" />';
    // Atom feeds with mail or domain name.
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    $out[] = tag('tag:' . $mail_or_domain . ',' . $blog_time_uid . ':' . $blog_uid . ($section ? '/' . join(',', $section) : '') . ($category ? '/' . join(',', $category) : ''), 'id');
    $out[] = tag('Textpattern', 'generator', ' uri="http://textpattern.com/" version="' . $version . '"');
    $out[] = tag(safe_strftime("w3cdtf", $last), 'updated');
    $auth[] = tag($pub['RealName'], 'name');
    $auth[] = $include_email_atom ? tag(eE($pub['email']), 'email') : '';
    $auth[] = tag(hu, 'uri');
    $out[] = tag(n . t . t . join(n . t . t, $auth) . n, 'author');
    $out[] = callback_event('atom_head');
    // Feed items.
    $articles = array();
    $section = doSlash($section);
    $category = doSlash($category);
    if (!$area or $area == 'article') {
        $sfilter = !empty($section) ? "AND Section IN ('" . join("','", $section) . "')" : '';
        $cfilter = !empty($category) ? "AND (Category1 IN ('" . join("','", $category) . "') OR Category2 IN ('" . join("','", $category) . "'))" : '';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $frs = safe_column("name", 'txp_section', "in_rss != '1'");
        $query = array();
        foreach ($frs as $f) {
            $query[] = "AND Section != '" . doSlash($f) . "'";
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $expired = $publish_expired_articles ? " " : " AND (" . now('expires') . " <= Expires OR Expires = " . NULLDATETIME . ") ";
        $rs = safe_rows_start("*,\n            ID AS thisid,\n            UNIX_TIMESTAMP(Posted) AS uPosted,\n            UNIX_TIMESTAMP(Expires) AS uExpires,\n            UNIX_TIMESTAMP(LastMod) AS uLastMod", 'textpattern', "Status = 4 AND Posted <= " . now('posted') . $expired . join(' ', $query) . "ORDER BY Posted DESC LIMIT {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event('atom_entry');
                $e = array();
                $a['posted'] = $uPosted;
                $a['expires'] = $uExpires;
                if ($show_comment_count_in_feed) {
                    $count = $comments_count > 0 ? ' [' . $comments_count . ']' : '';
                } else {
                    $count = '';
                }
                $thisauthor = get_author_name($AuthorID);
                $e['thisauthor'] = tag(n . t . t . t . tag(htmlspecialchars($thisauthor), 'name') . n . t . t, 'author');
                $e['issued'] = tag(safe_strftime('w3cdtf', $uPosted), 'published');
                $e['modified'] = tag(safe_strftime('w3cdtf', $uLastMod), 'updated');
                $escaped_title = htmlspecialchars($Title);
                $e['title'] = tag($escaped_title . $count, 'title', t_html);
                $permlink = permlinkurl($a);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $permlink . '" />';
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'id');
                $e['category1'] = trim($Category1) ? '<category term="' . htmlspecialchars($Category1) . '" />' : '';
                $e['category2'] = trim($Category2) ? '<category term="' . htmlspecialchars($Category2) . '" />' : '';
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    // Short feed: use body as summary if there's no excerpt.
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if (trim($content)) {
                    $e['content'] = tag(n . escape_cdata($content) . n, 'content', t_html);
                }
                if (trim($summary)) {
                    $e['summary'] = tag(n . escape_cdata($summary) . n, 'summary', t_html);
                }
                $articles[$ID] = tag(n . t . t . join(n . t . t, $e) . n . $cb, 'entry');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uLastMod;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category in ('" . join("','", $category) . "')" : '1';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $rs = safe_rows_start("*", 'txp_link', "{$cfilter} ORDER BY date DESC, id DESC LIMIT {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $e['title'] = tag(htmlspecialchars($linkname), 'title', t_html);
                $e['content'] = tag(n . htmlspecialchars($description) . n, 'content', t_html);
                $url = preg_replace("/^\\/(.*)/", "https?://{$siteurl}/\$1", $url);
                $url = preg_replace("/&((?U).*)=/", "&amp;\\1=", $url);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $url . '" />';
                $e['issued'] = tag(safe_strftime('w3cdtf', strtotime($date)), 'published');
                $e['modified'] = tag(gmdate('Y-m-d\\TH:i:s\\Z', strtotime($date)), 'updated');
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . safe_strftime('%Y-%m-%d', strtotime($date)) . ':' . $blog_uid . '/' . $id, 'id');
                $articles[$id] = tag(n . t . t . join(n . t . t, $e) . n, 'entry');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!$articles) {
        if ($section) {
            if (safe_field("name", 'txp_section', "name IN ('" . join("','", $section) . "')") == false) {
                txp_die(gTxt('404_not_found'), '404');
            }
        } elseif ($category) {
            switch ($area) {
                case 'link':
                    if (safe_field("id", 'txp_category', "name = '{$category}' AND type = 'link'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
                case 'article':
                default:
                    if (safe_field("id", 'txp_category', "name IN ('" . join("','", $category) . "') AND type = 'article'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
            }
        }
    } else {
        // Turn on compression if we aren't using it already.
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            // Make sure notices/warnings/errors don't fudge up the feed when
            // compression is used.
            $buf = '';
            while ($b = @ob_get_clean()) {
                $buf .= $b;
            }
            @ob_start('ob_gzhandler');
            echo $buf;
        }
        handle_lastmod();
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        $imsd = $hims ? strtotime($hims) : 0;
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id])) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } elseif (isset($cut_etag)) {
            header("Vary: If-None-Match");
        } elseif (isset($cut_time)) {
            header("Vary: If-Modified-Since");
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            txp_status_header('304 Not Modified');
            exit(0);
        }
        if ($etag) {
            header('ETag: "' . $etag . '"');
        }
        if ($cutarticles) {
            // header("HTTP/1.1 226 IM Used");
            // This should be used as opposed to 200, but Apache doesn't like it.
            // http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the
            // status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
    }
    $out = array_merge($out, $articles);
    header('Content-type: application/atom+xml; charset=utf-8');
    return chr(60) . '?xml version="1.0" encoding="UTF-8"?' . chr(62) . n . '<feed xml:lang="' . txpspecialchars($language) . '" xmlns="http://www.w3.org/2005/Atom">' . join(n, $out) . '</feed>';
}
Example #9
0
function list_list($message = '', $post = '')
{
    global $statuses, $comments_disabled_after, $step, $txp_user;
    pagetop(gTxt('tab_list'), $message);
    extract(get_prefs());
    extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
    $sesutats = array_flip($statuses);
    $dir = $dir == 'desc' ? 'desc' : 'asc';
    switch ($sort) {
        case 'id':
            $sort_sql = 'ID ' . $dir;
            break;
        case 'posted':
            $sort_sql = 'Posted ' . $dir;
            break;
        case 'title':
            $sort_sql = 'Title ' . $dir . ', Posted desc';
            break;
        case 'section':
            $sort_sql = 'Section ' . $dir . ', Posted desc';
            break;
        case 'category1':
            $sort_sql = 'Category1 ' . $dir . ', Posted desc';
            break;
        case 'category2':
            $sort_sql = 'Category2 ' . $dir . ', Posted desc';
            break;
        case 'status':
            $sort_sql = 'Status ' . $dir . ', Posted desc';
            break;
        case 'author':
            $sort_sql = 'AuthorID ' . $dir . ', Posted desc';
            break;
        case 'comments':
            $sort_sql = 'comments_count ' . $dir . ', Posted desc';
            break;
        default:
            $dir = 'desc';
            $sort_sql = 'Posted ' . $dir;
            break;
    }
    $switch_dir = $dir == 'desc' ? 'asc' : 'desc';
    $criteria = 1;
    if ($search_method and $crit) {
        $crit_escaped = doSlash($crit);
        $critsql = array('id' => "ID = '{$crit_escaped}'", 'title_body' => "Title rlike '{$crit_escaped}' or Body rlike '{$crit_escaped}'", 'section' => "Section rlike '{$crit_escaped}'", 'categories' => "Category1 rlike '{$crit_escaped}' or Category2 rlike '{$crit_escaped}'", 'status' => "Status = '" . @$sesutats[gTxt($crit_escaped)] . "'", 'author' => "AuthorID rlike '{$crit_escaped}'");
        if (array_key_exists($search_method, $critsql)) {
            $criteria = $critsql[$search_method];
            $limit = 500;
        } else {
            $search_method = '';
            $crit = '';
        }
    } else {
        $search_method = '';
        $crit = '';
    }
    $total = safe_count('textpattern', "{$criteria}");
    if ($total < 1) {
        if ($criteria != 1) {
            echo n . list_search_form($crit, $search_method) . n . graf(gTxt('no_results_found'), ' style="text-align: center;"');
        } else {
            echo graf(gTxt('no_articles_recorded'), ' style="text-align: center;"');
        }
        return;
    }
    $limit = max(@$article_list_pageby, 15);
    list($page, $offset, $numPages) = pager($total, $limit, $page);
    echo n . list_search_form($crit, $search_method);
    $rs = safe_rows_start('*, unix_timestamp(Posted) as posted', 'textpattern', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}");
    if ($rs) {
        $total_comments = array();
        // fetch true comment count, not the public comment count
        // maybe we should have another row in the db?
        $rs2 = safe_rows_start('parentid, count(*) as num', 'txp_discuss', "1 group by parentid order by parentid");
        if ($rs2) {
            while ($a = nextRow($rs2)) {
                $pid = $a['parentid'];
                $num = $a['num'];
                $total_comments[$pid] = $num;
            }
        }
        echo n . n . '<form name="longform" method="post" action="index.php" onsubmit="return verify(\'' . gTxt('are_you_sure') . '\')">' . n . startTable('list', '', '', '', '90%') . n . tr(n . column_head('ID', 'id', 'list', true, $switch_dir, $crit, $search_method) . column_head('posted', 'posted', 'list', true, $switch_dir, $crit, $search_method) . column_head('title', 'title', 'list', true, $switch_dir, $crit, $search_method) . column_head('section', 'section', 'list', true, $switch_dir, $crit, $search_method) . column_head('category1', 'category1', 'list', true, $switch_dir, $crit, $search_method, 'articles_detail') . column_head('category2', 'category2', 'list', true, $switch_dir, $crit, $search_method, 'articles_detail') . column_head('status', 'status', 'list', true, $switch_dir, $crit, $search_method) . column_head('author', 'author', 'list', true, $switch_dir, $crit, $search_method) . column_head('comments', 'comments', 'list', true, $switch_dir, $crit, $search_method, 'articles_detail') . hCell());
        include_once txpath . '/publish/taghandlers.php';
        while ($a = nextRow($rs)) {
            extract($a);
            if (empty($Title)) {
                $Title = '<em>' . eLink('article', 'edit', 'ID', $ID, gTxt('untitled')) . '</em>';
            } else {
                $Title = eLink('article', 'edit', 'ID', $ID, $Title);
            }
            $Category1 = $Category1 ? '<span title="' . htmlspecialchars(fetch_category_title($Category1)) . '">' . $Category1 . '</span>' : '';
            $Category2 = $Category2 ? '<span title="' . htmlspecialchars(fetch_category_title($Category2)) . '">' . $Category2 . '</span>' : '';
            $manage = n . '<ul class="articles_detail">' . n . t . '<li>' . eLink('article', 'edit', 'ID', $ID, gTxt('edit')) . '</li>' . (($Status == 4 or $Status == 5) ? n . t . '<li><a href="' . permlinkurl($a) . '">' . gTxt('view') . '</a></li>' : '') . n . '</ul>';
            $Status = !empty($Status) ? $statuses[$Status] : '';
            $comments = gTxt('none');
            if (isset($total_comments[$ID]) and $total_comments[$ID] > 0) {
                $comments = href(gTxt('manage'), 'index.php?event=discuss' . a . 'step=list' . a . 'search_method=parent' . a . 'crit=' . $ID) . ' (' . $total_comments[$ID] . ')';
            }
            $comment_status = $Annotate ? gTxt('on') : gTxt('off');
            if ($comments_disabled_after) {
                $lifespan = $comments_disabled_after * 86400;
                $time_since = time() - $posted;
                if ($time_since > $lifespan) {
                    $comment_status = gTxt('expired');
                }
            }
            $comments = n . '<ul>' . n . t . '<li>' . $comment_status . '</li>' . n . t . '<li>' . $comments . '</li>' . n . '</ul>';
            echo n . n . tr(n . td(eLink('article', 'edit', 'ID', $ID, $ID) . $manage) . td(safe_strftime('%d %b %Y %I:%M %p', $posted)) . td($Title) . td('<span title="' . htmlspecialchars(fetch_section_title($Section)) . '">' . $Section . '</span>', 75) . td($Category1, 100, "articles_detail") . td($Category2, 100, "articles_detail") . td($a['Status'] < 4 ? $Status : '<a href="' . permlinkurl($a) . '">' . $Status . '</a>', 50) . td('<span title="' . htmlspecialchars(get_author_name($AuthorID)) . '">' . $AuthorID . '</span>') . td($comments, 50, "articles_detail") . td(($a['Status'] >= 4 and has_privs('article.edit.published') or $a['Status'] >= 4 and $AuthorID == $txp_user and has_privs('article.edit.own.published') or $a['Status'] < 4 and has_privs('article.edit') or $a['Status'] < 4 and $AuthorID == $txp_user and has_privs('article.edit.own')) ? fInput('checkbox', 'selected[]', $ID) : '&nbsp;'));
        }
        echo n . n . tr(tda(toggle_box('articles_detail'), ' colspan="2" style="text-align: left; border: none;"') . tda(select_buttons() . list_multiedit_form($page, $sort, $dir, $crit, $search_method), ' colspan="9" style="text-align: right; border: none;"')) . n . endTable() . n . '</form>' . n . nav_form('list', $page, $numPages, $sort, $dir, $crit, $search_method) . n . pageby_form('list', $article_list_pageby);
    }
}
Example #10
0
/**
 * Sends and handles a lastmod header.
 *
 * @param   int|null   $unix_ts The last modification date as a UNIX timestamp
 * @param   bool       $exit    If TRUE, terminates the script
 * @return  array|null Array of sent HTTP status and the lastmod header, or NULL
 * @package Pref
 */
function handle_lastmod($unix_ts = null, $exit = true)
{
    if (get_pref('send_lastmod') && get_pref('production_status') == 'live') {
        $unix_ts = get_lastmod($unix_ts);
        // Make sure lastmod isn't in the future.
        $unix_ts = min($unix_ts, time());
        // Or too far in the past (7 days).
        $unix_ts = max($unix_ts, time() - 3600 * 24 * 7);
        $last = safe_strftime('rfc822', $unix_ts, 1);
        header("Last-Modified: {$last}");
        header('Cache-Control: no-cache');
        $hims = serverSet('HTTP_IF_MODIFIED_SINCE');
        if ($hims and @strtotime($hims) >= $unix_ts) {
            log_hit('304');
            if (!$exit) {
                return array('304', $last);
            }
            txp_status_header('304 Not Modified');
            // Some mod_deflate versions have a bug that breaks subsequent
            // requests when keepalive is used.  dropping the connection
            // is the only reliable way to fix this.
            if (!get_pref('lastmod_keepalive')) {
                header('Connection: close');
            }
            header('Content-Length: 0');
            // Discard all output.
            while (@ob_end_clean()) {
            }
            exit;
        }
        if (!$exit) {
            return array('200', $last);
        }
    }
}
Example #11
0
function article_edit($message = '', $concurrent = FALSE)
{
    global $vars, $txp_user, $comments_disabled_after, $txpcfg, $prefs, $event;
    extract($prefs);
    extract(gpsa(array('view', 'from_view', 'step')));
    if (!empty($GLOBALS['ID'])) {
        // newly-saved article
        $ID = $GLOBALS['ID'];
        $step = 'edit';
    } else {
        $ID = gps('ID');
    }
    include_once txpath . '/lib/classTextile.php';
    $textile = new Textile();
    // switch to 'text' view upon page load and after article post
    if (!$view || gps('save') || gps('publish')) {
        $view = 'text';
    }
    if (!$step) {
        $step = "create";
    }
    if ($step == "edit" && $view == "text" && !empty($ID) && $from_view != 'preview' && $from_view != 'html' && !$concurrent) {
        $pull = true;
        //-- it's an existing article - off we go to the db
        $ID = assert_int($ID);
        $rs = safe_row("*, unix_timestamp(Posted) as sPosted,\n\t\t\t\tunix_timestamp(Expires) as sExpires,\n\t\t\t\tunix_timestamp(LastMod) as sLastMod", "textpattern", "ID={$ID}");
        extract($rs);
        $reset_time = $publish_now = $Status < 4 && $sPosted <= time();
    } else {
        $pull = false;
        //-- assume they came from post
        if ($from_view == 'preview' or $from_view == 'html') {
            $store_out = array();
            $store = unserialize(base64_decode(ps('store')));
            foreach ($vars as $var) {
                if (isset($store[$var])) {
                    $store_out[$var] = $store[$var];
                }
            }
        } else {
            $store_out = gpsa($vars);
            if ($concurrent) {
                $store_out['sLastMod'] = safe_field('unix_timestamp(LastMod) as sLastMod', 'textpattern', 'ID=' . $ID);
            }
        }
        $rs = $store_out;
        extract($store_out);
    }
    $GLOBALS['step'] = $step;
    if ($step == 'create') {
        $textile_body = $use_textile;
        $textile_excerpt = $use_textile;
    }
    if ($step != 'create' && $sPosted) {
        // Previous record?
        $prev_id = checkIfNeighbour('prev', $sPosted);
        // Next record?
        $next_id = checkIfNeighbour('next', $sPosted);
    } else {
        $prev_id = $next_id = 0;
    }
    $page_title = $Title ? $Title : gTxt('write');
    pagetop($page_title, $message);
    echo n . '<div id="' . $event . '_container" class="txp-container txp-edit">';
    echo n . n . '<form id="article_form" name="article_form" method="post" action="index.php">';
    if (!empty($store_out)) {
        echo hInput('store', base64_encode(serialize($store_out)));
    }
    echo hInput('ID', $ID) . eInput('article') . sInput($step) . '<input type="hidden" name="view" />' . startTable('edit') . '<tr>' . n . '<td id="article-col-1"><div id="configuration_content">';
    if ($view == 'text') {
        //-- markup help --------------
        echo pluggable_ui('article_ui', 'sidehelp', side_help($textile_body, $textile_excerpt), $rs);
        //-- custom menu entries --------------
        echo pluggable_ui('article_ui', 'extend_col_1', '', $rs);
        //-- advanced --------------
        echo '<div id="advanced_group"><h3 class="plain lever' . (get_pref('pane_article_advanced_visible') ? ' expanded' : '') . '"><a href="#advanced">' . gTxt('advanced_options') . '</a></h3>' . '<div id="advanced" class="toggle" style="display:' . (get_pref('pane_article_advanced_visible') ? 'block' : 'none') . '">';
        // markup selection
        echo pluggable_ui('article_ui', 'markup', n . graf('<label for="markup-body">' . gTxt('article_markup') . '</label>' . br . pref_text('textile_body', $textile_body, 'markup-body'), ' class="markup markup-body"') . n . graf('<label for="markup-excerpt">' . gTxt('excerpt_markup') . '</label>' . br . pref_text('textile_excerpt', $textile_excerpt, 'markup-excerpt'), ' class="markup markup-excerpt"'), $rs);
        // form override
        echo $allow_form_override ? pluggable_ui('article_ui', 'override', graf('<label for="override-form">' . gTxt('override_default_form') . '</label>' . sp . popHelp('override_form') . br . form_pop($override_form, 'override-form'), ' class="override-form"'), $rs) : '';
        echo '</div></div>' . n;
        //-- custom fields --------------
        $cf = '';
        $cfs = getCustomFields();
        echo '<div id="custom_field_group"' . ($cfs ? '' : ' class="empty"') . '><h3 class="plain lever' . (get_pref('pane_article_custom_field_visible') ? ' expanded' : '') . '"><a href="#custom_field">' . gTxt('custom') . '</a></h3>' . '<div id="custom_field" class="toggle" style="display:' . (get_pref('pane_article_custom_field_visible') ? 'block' : 'none') . '">';
        foreach ($cfs as $i => $cf_name) {
            $custom_x_set = "custom_{$i}_set";
            $custom_x = "custom_{$i}";
            $cf .= ${$custom_x_set} !== '' ? custField($i, ${$custom_x_set}, ${$custom_x}) : '';
        }
        echo pluggable_ui('article_ui', 'custom_fields', $cf, $rs);
        echo '</div></div>' . n;
        //-- article image --------------
        echo '<div id="image_group"><h3 class="plain lever' . (get_pref('pane_article_image_visible') ? ' expanded' : '') . '"><a href="#image">' . gTxt('article_image') . '</a></h3>' . '<div id="image" class="toggle" style="display:' . (get_pref('pane_article_image_visible') ? 'block' : 'none') . '">';
        echo pluggable_ui('article_ui', 'article_image', n . graf('<label for="article-image">' . gTxt('article_image') . '</label>' . sp . popHelp('article_image') . br . fInput('text', 'Image', $Image, 'edit', '', '', 22, '', 'article-image'), ' class="article-image"'), $rs);
        echo '</div></div>' . n;
        //-- meta info --------------
        echo '<div id="meta_group"><h3 class="plain lever' . (get_pref('pane_article_meta_visible') ? ' expanded' : '') . '"><a href="#meta">' . gTxt('meta') . '</a></h3>' . '<div id="meta" class="toggle" style="display:' . (get_pref('pane_article_meta_visible') ? 'block' : 'none') . '">';
        // keywords
        echo pluggable_ui('article_ui', 'keywords', n . graf('<label for="keywords">' . gTxt('keywords') . '</label>' . sp . popHelp('keywords') . br . n . '<textarea id="keywords" name="Keywords" cols="18" rows="5">' . htmlspecialchars(str_replace(',', ', ', $Keywords)) . '</textarea>', ' class="keywords"'), $rs);
        // url title
        echo pluggable_ui('article_ui', 'url_title', n . graf('<label for="url-title">' . gTxt('url_title') . '</label>' . sp . popHelp('url_title') . br . fInput('text', 'url_title', $url_title, 'edit', '', '', 22, '', 'url-title'), ' class="url-title"'), $rs);
        echo '</div></div>' . n;
        //-- recent articles --------------
        echo '<div id="recent_group"><h3 class="plain lever' . (get_pref('pane_article_recent_visible') ? ' expanded' : '') . '"><a href="#recent">' . gTxt('recent_articles') . '</a>' . '</h3>' . '<div id="recent" class="toggle" style="display:' . (get_pref('pane_article_recent_visible') ? 'block' : 'none') . '">';
        $recents = safe_rows_start("Title, ID", 'textpattern', "1=1 order by LastMod desc limit 10");
        $ra = '';
        if ($recents) {
            $ra = '<ul class="recent plain-list">';
            while ($recent = nextRow($recents)) {
                if (!$recent['Title']) {
                    $recent['Title'] = gTxt('untitled') . sp . $recent['ID'];
                }
                $ra .= n . t . '<li class="recent-article"><a href="?event=article' . a . 'step=edit' . a . 'ID=' . $recent['ID'] . '">' . escape_title($recent['Title']) . '</a></li>';
            }
            $ra .= '</ul>';
        }
        echo pluggable_ui('article_ui', 'recent_articles', $ra, $rs);
        echo '</div></div>';
    } else {
        echo sp;
    }
    echo '</div></td>' . n . '<td id="article-main"><div id="main_content">';
    //-- title input --------------
    if ($view == 'preview') {
        echo '<div class="preview">' . hed(gTxt('preview'), 2) . hed($Title, 1, ' class="title"');
    } elseif ($view == 'html') {
        echo '<div class="xhtml">' . hed('XHTML', 2) . hed($Title, 1, ' class="title"');
    } elseif ($view == 'text') {
        echo '<div class="text">' . pluggable_ui('article_ui', 'title', n . '<p class="title"><label for="title">' . gTxt('title') . '</label>' . sp . popHelp('title') . br . '<input type="text" id="title" name="Title" value="' . escape_title($Title) . '" class="edit" size="40" tabindex="1" />', $rs);
        if ($step != 'create') {
            if ($Status != 4 and $Status != 5) {
                $url = '?txpreview=' . intval($ID) . '.' . time();
                // article ID plus cachebuster
            } else {
                include_once txpath . '/publish/taghandlers.php';
                $url = permlinkurl_id($ID);
            }
            echo sp . sp . '<a href="' . $url . '" class="article-view">' . gTxt('view') . '</a>';
        }
        echo '</p>';
    }
    //-- body --------------------
    if ($view == 'preview') {
        echo '<div class="body">';
        if ($textile_body == USE_TEXTILE) {
            echo $textile->TextileThis($Body);
        } else {
            if ($textile_body == CONVERT_LINEBREAKS) {
                echo nl2br($Body);
            } else {
                if ($textile_body == LEAVE_TEXT_UNTOUCHED) {
                    echo $Body;
                }
            }
        }
        echo '</div>';
    } elseif ($view == 'html') {
        if ($textile_body == USE_TEXTILE) {
            $bod = $textile->TextileThis($Body);
        } else {
            if ($textile_body == CONVERT_LINEBREAKS) {
                $bod = nl2br($Body);
            } else {
                if ($textile_body == LEAVE_TEXT_UNTOUCHED) {
                    $bod = $Body;
                }
            }
        }
        echo tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($bod)), 'code', ' class="body"');
    } else {
        echo pluggable_ui('article_ui', 'body', n . graf('<label for="body">' . gTxt('body') . '</label>' . sp . popHelp('body') . br . '<textarea id="body" name="Body" cols="55" rows="31" tabindex="2">' . htmlspecialchars($Body) . '</textarea>', ' class="body"'), $rs);
    }
    //-- excerpt --------------------
    if ($articles_use_excerpts) {
        if ($view == 'text') {
            echo pluggable_ui('article_ui', 'excerpt', n . graf('<label for="excerpt">' . gTxt('excerpt') . '</label>' . sp . popHelp('excerpt') . br . '<textarea id="excerpt" name="Excerpt" cols="55" rows="5" tabindex="3">' . htmlspecialchars($Excerpt) . '</textarea>', ' class="excerpt"'), $rs);
        } else {
            echo n . '<hr width="50%" />';
            echo '<div class="excerpt">';
            echo $textile_excerpt == USE_TEXTILE ? $view == 'preview' ? graf($textile->textileThis($Excerpt)) : tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($textile->TextileThis($Excerpt))), 'code', ' class="excerpt"') : graf($Excerpt);
            echo '</div>';
        }
    }
    //-- author --------------
    if ($view == "text" && $step != "create") {
        echo '<p class="author small">' . gTxt('posted_by') . ': ' . htmlspecialchars($AuthorID) . ' &#183; ' . safe_strftime('%d %b %Y &#183; %X', $sPosted);
        if ($sPosted != $sLastMod) {
            echo br . gTxt('modified_by') . ': ' . htmlspecialchars($LastModID) . ' &#183; ' . safe_strftime('%d %b %Y &#183; %X', $sLastMod);
        }
        echo '</p>';
    }
    echo hInput('from_view', $view), '</div></div></td>';
    //-- layer tabs -------------------
    echo '<td id="article-tabs"><div id="view_modes">';
    echo pluggable_ui('article_ui', 'view', $use_textile == USE_TEXTILE || $textile_body == USE_TEXTILE ? tag(tab('text', $view) . tab('html', $view) . tab('preview', $view), 'ul') : '&#160;', $rs);
    echo '</div></td>';
    echo '<td id="article-col-2"><div id="supporting_content">';
    if ($view == 'text') {
        if ($step != 'create') {
            echo n . graf(href(gtxt('create_new'), 'index.php?event=article'), ' class="action-create"');
        }
        //-- prev/next article links --
        if ($step != 'create' and ($prev_id or $next_id)) {
            echo '<p class="article-nav">', $prev_id ? prevnext_link('&#8249;' . gTxt('prev'), 'article', 'edit', $prev_id, gTxt('prev')) : '', $next_id ? prevnext_link(gTxt('next') . '&#8250;', 'article', 'edit', $next_id, gTxt('next')) : '', '</p>';
        }
        //-- status radios --------------
        echo pluggable_ui('article_ui', 'status', n . n . '<fieldset id="write-status">' . n . '<legend>' . gTxt('status') . '</legend>' . n . status_radio($Status) . n . '</fieldset>', $rs);
        //-- category selects -----------
        echo pluggable_ui('article_ui', 'categories', n . n . '<fieldset id="write-sort">' . n . '<legend>' . gTxt('sort_display') . '</legend>' . n . graf('<label for="category-1">' . gTxt('category1') . '</label> ' . '<span class="edit category-edit small">[' . eLink('category', '', '', '', gTxt('edit')) . ']</span>' . br . n . category_popup('Category1', $Category1, 'category-1'), ' class="category category-1"') . n . graf('<label for="category-2">' . gTxt('category2') . '</label>' . br . n . category_popup('Category2', $Category2, 'category-2'), ' class="category category-2"'), $rs);
        //-- section select --------------
        if (!$from_view && !$pull) {
            $Section = getDefaultSection();
        }
        echo pluggable_ui('article_ui', 'section', n . graf('<label for="section">' . gTxt('section') . '</label> ' . '<span class="edit section-edit small">[' . eLink('section', '', '', '', gTxt('edit')) . ']</span>' . br . section_popup($Section, 'section'), ' class="section"') . n . '</fieldset>', $rs);
        //-- "More" section
        echo n . n . '<div id="more_group"><h3 class="plain lever' . (get_pref('pane_article_more_visible') ? ' expanded' : '') . '"><a href="#more">' . gTxt('more') . '</a></h3>', '<div id="more" class="toggle" style="display:' . (get_pref('pane_article_more_visible') ? 'block' : 'none') . '">';
        //-- comments stuff --------------
        if ($step == "create") {
            //Avoiding invite disappear when previewing
            $AnnotateInvite = !empty($store_out['AnnotateInvite']) ? $store_out['AnnotateInvite'] : $comments_default_invite;
            if ($comments_on_default == 1) {
                $Annotate = 1;
            }
        }
        if ($use_comments == 1) {
            $invite[] = n . n . '<fieldset id="write-comments">' . n . '<legend>' . gTxt('comments') . '</legend>';
            $comments_expired = false;
            if ($step != 'create' && $comments_disabled_after) {
                $lifespan = $comments_disabled_after * 86400;
                $time_since = time() - $sPosted;
                if ($time_since > $lifespan) {
                    $comments_expired = true;
                }
            }
            if ($comments_expired) {
                $invite[] = n . n . graf(gTxt('expired'), ' class="comment-annotate"');
            } else {
                $invite[] = n . n . graf(onoffRadio('Annotate', $Annotate), ' class="comment-annotate"') . n . n . graf('<label for="comment-invite">' . gTxt('comment_invitation') . '</label>' . br . fInput('text', 'AnnotateInvite', $AnnotateInvite, 'edit', '', '', '', '', 'comment-invite'), ' class="comment-invite"');
            }
            $invite[] = n . n . '</fieldset>';
            echo pluggable_ui('article_ui', 'annotate_invite', join('', $invite), $rs);
        }
        if ($step == "create" and empty($GLOBALS['ID'])) {
            //-- timestamp -------------------
            //Avoiding modified date to disappear
            $persist_timestamp = !empty($store_out['year']) ? safe_strtotime($store_out['year'] . '-' . $store_out['month'] . '-' . $store_out['day'] . ' ' . $store_out['hour'] . ':' . $store_out['minute'] . ':' . $store_out['second']) : time();
            echo pluggable_ui('article_ui', 'timestamp', n . n . '<fieldset id="write-timestamp">' . n . '<legend>' . gTxt('timestamp') . '</legend>' . n . graf(checkbox('publish_now', '1', $publish_now, '', 'publish_now') . '<label for="publish_now">' . gTxt('set_to_now') . '</label>', ' class="publish-now"') . n . graf(gTxt('or_publish_at') . sp . popHelp('timestamp'), ' class="publish-at"') . n . graf('<span class="label">' . gtxt('date') . '</span>' . sp . tsi('year', '%Y', $persist_timestamp) . ' / ' . tsi('month', '%m', $persist_timestamp) . ' / ' . tsi('day', '%d', $persist_timestamp), ' class="date posted created"') . n . graf('<span class="label">' . gTxt('time') . '</span>' . sp . tsi('hour', '%H', $persist_timestamp) . ' : ' . tsi('minute', '%M', $persist_timestamp) . ' : ' . tsi('second', '%S', $persist_timestamp), ' class="time posted created"') . n . '</fieldset>', array('sPosted' => $persist_timestamp) + $rs);
            //-- expires -------------------
            $persist_timestamp = !empty($store_out['exp_year']) ? safe_strtotime($store_out['exp_year'] . '-' . $store_out['exp_month'] . '-' . $store_out['exp_day'] . ' ' . $store_out['exp_hour'] . ':' . $store_out['exp_minute'] . ':' . $store_out['second']) : NULLDATETIME;
            echo pluggable_ui('article_ui', 'expires', n . n . '<fieldset id="write-expires">' . n . '<legend>' . gTxt('expires') . '</legend>' . n . graf('<span class="label">' . gtxt('date') . '</span>' . sp . tsi('exp_year', '%Y', $persist_timestamp) . ' / ' . tsi('exp_month', '%m', $persist_timestamp) . ' / ' . tsi('exp_day', '%d', $persist_timestamp), ' class="date expires"') . n . graf('<span class="label">' . gTxt('time') . '</span>' . sp . tsi('exp_hour', '%H', $persist_timestamp) . ' : ' . tsi('exp_minute', '%M', $persist_timestamp) . ' : ' . tsi('exp_second', '%S', $persist_timestamp), ' class="time expires"') . n . '</fieldset>', $rs);
            // end "More" section
            echo n . n . '</div></div>';
            //-- publish button --------------
            echo has_privs('article.publish') ? fInput('submit', 'publish', gTxt('publish'), "publish", '', '', '', 4) : fInput('submit', 'publish', gTxt('save'), "publish", '', '', '', 4);
        } else {
            //-- timestamp -------------------
            if (!empty($year)) {
                $sPosted = safe_strtotime($year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minute . ':' . $second);
            }
            echo pluggable_ui('article_ui', 'timestamp', n . n . '<fieldset id="write-timestamp">' . n . '<legend>' . gTxt('timestamp') . '</legend>' . n . graf(checkbox('reset_time', '1', $reset_time, '', 'reset_time') . '<label for="reset_time">' . gTxt('reset_time') . '</label>', ' class="reset-time"') . n . graf(gTxt('published_at') . sp . popHelp('timestamp'), ' class="publish-at"') . n . graf('<span class="label">' . gtxt('date') . '</span>' . sp . tsi('year', '%Y', $sPosted) . ' / ' . tsi('month', '%m', $sPosted) . ' / ' . tsi('day', '%d', $sPosted), ' class="date posted created"') . n . graf('<span class="label">' . gTxt('time') . '</span>' . sp . tsi('hour', '%H', $sPosted) . ' : ' . tsi('minute', '%M', $sPosted) . ' : ' . tsi('second', '%S', $sPosted), ' class="time posted created"') . n . hInput('sPosted', $sPosted) . n . hInput('sLastMod', $sLastMod) . n . hInput('AuthorID', $AuthorID) . n . hInput('LastModID', $LastModID) . n . '</fieldset>', $rs);
            //-- expires -------------------
            if (!empty($exp_year)) {
                if (empty($exp_month)) {
                    $exp_month = 1;
                }
                if (empty($exp_day)) {
                    $exp_day = 1;
                }
                if (empty($exp_hour)) {
                    $exp_hour = 0;
                }
                if (empty($exp_minute)) {
                    $exp_minute = 0;
                }
                if (empty($exp_second)) {
                    $exp_second = 0;
                }
                $sExpires = safe_strtotime($exp_year . '-' . $exp_month . '-' . $exp_day . ' ' . $exp_hour . ':' . $exp_minute . ':' . $exp_second);
            }
            echo pluggable_ui('article_ui', 'expires', n . n . '<fieldset id="write-expires">' . n . '<legend>' . gTxt('expires') . '</legend>' . n . graf('<span class="label">' . gtxt('date') . '</span>' . sp . tsi('exp_year', '%Y', $sExpires) . ' / ' . tsi('exp_month', '%m', $sExpires) . ' / ' . tsi('exp_day', '%d', $sExpires), ' class="date expires"') . n . graf('<span class="label">' . gTxt('time') . '</span>' . sp . tsi('exp_hour', '%H', $sExpires) . ' : ' . tsi('exp_minute', '%M', $sExpires) . ' : ' . tsi('exp_second', '%S', $sExpires), ' class="time expires"') . n . hInput('sExpires', $sExpires) . n . '</fieldset>', $rs);
            // end "More" section
            echo n . n . '</div></div>';
            //-- save button --------------
            if ($Status >= 4 and has_privs('article.edit.published') or $Status >= 4 and $AuthorID == $txp_user and has_privs('article.edit.own.published') or $Status < 4 and has_privs('article.edit') or $Status < 4 and $AuthorID == $txp_user and has_privs('article.edit.own')) {
                echo fInput('submit', 'save', gTxt('save'), "publish", '', '', '', 4);
            }
        }
    }
    echo '</div></td></tr></table></form></div>' . n;
    // Assume users would not change the timestamp if they wanted to "publish now"/"reset time"
    echo script_js(<<<EOS
\t\t\$('#write-timestamp input.edit').change(
\t\t\tfunction() {
\t\t\t\t\$('#publish_now').attr('checked', false);
\t\t\t\t\$('#reset_time').attr('checked', false);
\t\t\t});
EOS
);
}
Example #12
0
function ipban_list($message = '')
{
    pageTop(gTxt('list_banned_ips'), $message);
    $rs = safe_rows_start('*, unix_timestamp(date_banned) as uBanned', 'txp_discuss_ipban', "1 = 1 order by date_banned desc");
    if ($rs and numRows($rs) > 0) {
        echo startTable('list') . tr(hCell(gTxt('date_banned')) . hCell(gTxt('IP')) . hCell(gTxt('name_used')) . hCell(gTxt('banned_for')) . hCell());
        while ($a = nextRow($rs)) {
            extract($a);
            echo tr(td(safe_strftime('%d %b %Y %I:%M %p', $uBanned), 100) . td($ip, 100) . td($name_used, 100) . td('<a href="?event=discuss' . a . 'step=discuss_edit' . a . 'discussid=' . $banned_on_message . '">' . $banned_on_message . '</a>', 100) . td('<a href="?event=discuss' . a . 'step=ipban_unban' . a . 'ip=' . $ip . '">' . gTxt('unban') . '</a>'));
        }
        echo endTable();
    } else {
        echo graf(gTxt('no_ips_banned'), ' class="indicator"');
    }
}
Example #13
0
function ipban_list($message = '')
{
    global $event;
    pageTop(gTxt('list_banned_ips'), $message);
    $rs = safe_rows_start('*, unix_timestamp(date_banned) as uBanned', 'txp_discuss_ipban', "1 = 1 order by date_banned desc");
    if ($rs and numRows($rs) > 0) {
        echo '<div id="' . $event . '_ban_container" class="txp-container txp-list">' . startTable('list', '', 'list') . n . '<thead>' . tr(hCell(gTxt('date_banned'), '', ' class="date banned"') . hCell(gTxt('IP'), '', ' class="ip"') . hCell(gTxt('name_used'), '', ' class="name"') . hCell(gTxt('banned_for'), '', ' class="id"') . hCell('', '', ' class="actions"')) . n . '</thead>';
        echo '<tbody>';
        $ctr = 1;
        while ($a = nextRow($rs)) {
            extract($a);
            echo tr(td(safe_strftime('%d %b %Y %I:%M %p', $uBanned), 100, 'date banned') . td($ip, 100, 'ip') . td($name_used, 100, 'name') . td('<a href="?event=discuss' . a . 'step=discuss_edit' . a . 'discussid=' . $banned_on_message . '">' . $banned_on_message . '</a>', 100, 'id') . td('<a class="action-ban" href="?event=discuss' . a . 'step=ipban_unban' . a . 'ip=' . $ip . '">' . gTxt('unban') . '</a>', '', 'actions'), ' class="' . ($ctr % 2 == 0 ? 'even' : 'odd') . '"');
            $ctr++;
        }
        echo '</tbody>' . endTable() . '</div>';
    } else {
        echo graf(gTxt('no_ips_banned'), ' class="indicator"');
    }
}
Example #14
0
function author_list()
{
    global $txp_user, $author_list_pageby;
    extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
    if ($sort === '') {
        $sort = get_pref('admin_sort_column', 'name');
    }
    if ($dir === '') {
        $dir = get_pref('admin_sort_dir', 'asc');
    }
    $dir = $dir == 'desc' ? 'desc' : 'asc';
    if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) {
        $sort = 'name';
    }
    $sort_sql = $sort . ' ' . $dir;
    set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE);
    set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE);
    $switch_dir = $dir == 'desc' ? 'asc' : 'desc';
    $total = getCount('txp_users', '1=1');
    $limit = max($author_list_pageby, 15);
    list($page, $offset, $numPages) = pager($total, $limit, $page);
    $rs = safe_rows_start('*, unix_timestamp(last_access) as last_login', 'txp_users', '1 = 1 order by ' . $sort_sql . ' limit ' . $offset . ', ' . $limit);
    if ($rs) {
        echo n . '<div class="txp-list">';
        echo '<form action="index.php" id="users_form" method="post" name="longform" onsubmit="return verify(\'' . gTxt('are_you_sure') . '\')">' . startTable('list', '', 'list') . n . '<thead>' . n . tr(column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', ('name' == $sort ? "{$dir} " : '') . 'name login-name') . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', ('RealName' == $sort ? "{$dir} " : '') . 'name real-name') . column_head('email', 'email', 'admin', true, $switch_dir, '', '', ('email' == $sort ? "{$dir} " : '') . 'email') . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', ('privs' == $sort ? "{$dir} " : '') . 'privs') . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', ('last_login' == $sort ? "{$dir} " : '') . 'date last-login modified') . hCell('', '', ' class="actions"') . hCell('', '', ' class="multi-edit"')) . n . '</thead>';
        $tfoot = n . '<tfoot>' . tr(tda(has_privs('admin.edit') ? select_buttons() . author_multiedit_form($page, $sort, $dir, $crit, $search_method) : '', ' class="multi-edit" colspan="7" style="text-align: right; border: none;"')) . n . '</tfoot>';
        echo $tfoot;
        echo '<tbody>';
        $ctr = 1;
        while ($a = nextRow($rs)) {
            extract(doSpecial($a));
            echo tr(td($name, '', 'name login-name') . td($RealName, '', 'name real-name') . td('<a href="mailto:' . $email . '">' . $email . '</a>', '', 'email') . td(get_priv_level($privs), '', 'privs') . td($last_login ? safe_strftime('%b&#160;%Y', $last_login) : '', '', 'date last-login modified') . td(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, gTxt('edit')) : '', '', 'actions') . td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name'], 'checkbox') : '', '', 'multi-edit'), ' class="' . ($ctr % 2 == 0 ? 'even' : 'odd') . '"');
            $ctr++;
        }
        echo '</tbody>' . n . endTable() . n . '</form>' . n . '<div id="users_navigation" class="txp-navigation">' . nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method) . pageby_form('admin', $author_list_pageby) . n . '</div>' . n . '</div>';
    }
}
Example #15
0
function discuss_edit()
{
    global $event;
    pagetop(gTxt('edit_comment'));
    extract(gpsa(array('discussid', 'sort', 'dir', 'page', 'crit', 'search_method')));
    $discussid = assert_int($discussid);
    $rs = safe_row('*, unix_timestamp(posted) as uPosted', 'txp_discuss', "discussid = {$discussid}");
    if ($rs) {
        extract($rs);
        $message = txpspecialchars($message);
        if (fetch('ip', 'txp_discuss_ipban', 'ip', $ip)) {
            $ban_step = 'ipban_unban';
            $ban_text = gTxt('unban');
        } else {
            $ban_step = 'ipban_add';
            $ban_text = gTxt('ban');
        }
        $ban_link = '[<a class="action-ban" href="?event=discuss' . a . 'step=' . $ban_step . a . 'ip=' . $ip . a . 'name=' . urlencode($name) . a . 'discussid=' . $discussid . a . '_txp_token=' . form_token() . '">' . $ban_text . '</a>]';
        $status_list = selectInput('visible', array(VISIBLE => gTxt('visible'), SPAM => gTxt('spam'), MODERATE => gTxt('unmoderated')), $visible, false, '', 'status');
        echo '<div id="' . $event . '_container" class="txp-container">' . form('<div class="txp-edit">' . n . hed(gTxt('edit_comment'), 2) . n . inputLabel('status', $status_list, 'status') . n . inputLabel('name', fInput('text', 'name', $name, '', '', '', INPUT_REGULAR, '', 'name'), 'name') . n . inputLabel('IP', $ip . n . $ban_link, '') . n . inputLabel('email', fInput('text', 'email', $email, '', '', '', INPUT_REGULAR, '', 'email'), 'email') . n . inputLabel('website', fInput('text', 'web', $web, '', '', '', INPUT_REGULAR, '', 'website'), 'website') . n . inputLabel('date', safe_strftime('%d %b %Y %X', $uPosted), '') . n . inputLabel('commentmessage', '<textarea id="commentmessage" name="message" cols="' . INPUT_LARGE . '" rows="' . INPUT_MEDIUM . '">' . $message . '</textarea>', 'message', '', '', '') . n . graf(fInput('submit', 'step', gTxt('save'), 'publish')) . hInput('sort', $sort) . hInput('dir', $dir) . hInput('page', $page) . hInput('crit', $crit) . hInput('search_method', $search_method) . hInput('discussid', $discussid) . hInput('parentid', $parentid) . hInput('ip', $ip) . eInput('discuss') . sInput('discuss_save') . '</div>', '', '', 'post', 'edit-form', '', 'discuss_edit_form'), '</div>';
    } else {
        echo graf(gTxt('comment_not_found'), ' class="indicator"');
    }
}
Example #16
0
function fileDownloadFormatTime($params)
{
    global $prefs;
    extract($params);
    if (!empty($ftime)) {
        return !empty($format) ? safe_strftime($format, $ftime) : safe_strftime($prefs['archive_dateformat'], $ftime);
    }
    return '';
}
Example #17
0
 function is_today($day, $ts)
 {
     if ($this->month == safe_strftime('%m', time()) and $day == safe_strftime('%d', time()) and $this->year == safe_strftime('%Y', time())) {
         return 1;
     } else {
         return 0;
     }
 }
Example #18
0
function list_languages($message = '')
{
    global $prefs, $locale, $textarray;
    require_once txpath . '/lib/IXRClass.php';
    // Select and save active language
    if (!$message && ps('step') == 'list_languages' && ps('language')) {
        $locale = doSlash(getlocale(ps('language')));
        safe_update("txp_prefs", "val='" . doSlash(ps('language')) . "'", "name='language'");
        safe_update("txp_prefs", "val='" . $locale . "'", "name='locale'");
        $textarray = load_lang(doSlash(ps('language')));
        $locale = setlocale(LC_ALL, $locale);
        $message = gTxt('preferences_saved');
    }
    $active_lang = safe_field('val', 'txp_prefs', "name='language'");
    $lang_form = '<div id="language_control" class="txp-control-panel">' . form(graf(gTxt('active_language') . languages('language', $active_lang) . n . fInput('submit', 'Submit', gTxt('save'), 'publish') . eInput('prefs') . sInput('list_languages'))) . '</div>';
    $client = new IXR_Client(RPC_SERVER);
    //$client->debug = true;
    $available_lang = array();
    $rpc_connect = false;
    $show_files = false;
    // Get items from RPC
    @set_time_limit(90);
    if ($client->query('tups.listLanguages', $prefs['blog_uid'])) {
        $rpc_connect = true;
        $response = $client->getResponse();
        foreach ($response as $language) {
            $available_lang[$language['language']]['rpc_lastmod'] = gmmktime($language['lastmodified']->hour, $language['lastmodified']->minute, $language['lastmodified']->second, $language['lastmodified']->month, $language['lastmodified']->day, $language['lastmodified']->year);
        }
    } elseif (gps('force') != 'file') {
        $msg = gTxt('rpc_connect_error') . "<!--" . $client->getErrorCode() . ' ' . $client->getErrorMessage() . "-->";
    }
    // Get items from Filesystem
    $files = get_lang_files();
    if (is_array($files) && !empty($files)) {
        foreach ($files as $file) {
            if ($fp = @fopen(txpath . DS . 'lang' . DS . $file, 'r')) {
                $name = str_replace('.txt', '', $file);
                $firstline = fgets($fp, 4069);
                fclose($fp);
                if (strpos($firstline, '#@version') !== false) {
                    @(list($fversion, $ftime) = explode(';', trim(substr($firstline, strpos($firstline, ' ', 1)))));
                } else {
                    $fversion = $ftime = NULL;
                }
                $available_lang[$name]['file_note'] = isset($fversion) ? $fversion : 0;
                $available_lang[$name]['file_lastmod'] = isset($ftime) ? $ftime : 0;
            }
        }
    }
    // Get installed items from the database
    // We need a value here for the language itself, not for each one of the rows
    $rows = safe_rows('lang, UNIX_TIMESTAMP(MAX(lastmod)) as lastmod', 'txp_lang', "1 GROUP BY lang ORDER BY lastmod DESC");
    $installed_lang = array();
    foreach ($rows as $language) {
        $available_lang[$language['lang']]['db_lastmod'] = $language['lastmod'];
        if ($language['lang'] != $active_lang) {
            $installed_lang[] = $language['lang'];
        }
    }
    $list = '';
    // Show the language table
    foreach ($available_lang as $langname => $langdat) {
        $file_updated = isset($langdat['db_lastmod']) && @$langdat['file_lastmod'] > $langdat['db_lastmod'];
        $rpc_updated = @$langdat['rpc_lastmod'] > @$langdat['db_lastmod'];
        $rpc_install = tda($rpc_updated ? strong(eLink('prefs', 'get_language', 'lang_code', $langname, isset($langdat['db_lastmod']) ? gTxt('update') : gTxt('install'), 'updating', isset($langdat['db_lastmod']), '')) . n . '<span class="date modified">' . safe_strftime('%d %b %Y %X', @$langdat['rpc_lastmod']) . '</span>' : (isset($langdat['rpc_lastmod']) ? gTxt('updated') : '-') . (isset($langdat['db_lastmod']) ? n . '<span class="date modified">' . safe_strftime('%d %b %Y %X', $langdat['db_lastmod']) . '</span>' : ''), isset($langdat['db_lastmod']) && $rpc_updated ? ' class="highlight lang-value"' : ' class="lang-value"');
        $lang_file = tda(isset($langdat['file_lastmod']) ? strong(eLink('prefs', 'get_language', 'lang_code', $langname, $file_updated ? gTxt('update') : gTxt('install'), 'force', 'file', '')) . n . '<span class="date ' . ($file_updated ? 'created' : 'modified') . '">' . safe_strftime($prefs['archive_dateformat'], $langdat['file_lastmod']) . '</span>' : '-', ' class="lang-value languages_detail' . (isset($langdat['db_lastmod']) && $rpc_updated ? ' highlight' : '') . '"');
        $list .= tr(tda(gTxt($langname), isset($langdat['db_lastmod']) && $rpc_updated ? ' class="highlight lang-label"' : ' class="lang-label"') . n . $rpc_install . n . $lang_file . n . tda(in_array($langname, $installed_lang) ? dLink('prefs', 'remove_language', 'lang_code', $langname, 1) : '-', ' class="languages_detail' . (isset($langdat['db_lastmod']) && $rpc_updated ? ' highlight' : '') . '"')) . n . n;
    }
    // Output Table + Content
    // TODO: tab_languages when this panel is moved to its own tab
    pagetop(gTxt('update_languages'), $message);
    //TODO: tab_languages when this panel is moved to its own tab
    echo '<h1 class="txp-heading">' . gTxt('update_languages') . '</h1>';
    echo n . '<div id="language_container" class="txp-container">';
    if (isset($msg) && $msg) {
        echo tag($msg, 'p', ' class="error lang-msg"');
    }
    echo n . '<p class="nav-tertiary">' . sLink('prefs', 'prefs_list', gTxt('site_prefs'), 'navlink') . sLink('prefs', 'advanced_prefs', gTxt('advanced_preferences'), 'navlink') . sLink('prefs', 'list_languages', gTxt('manage_languages'), 'navlink-active') . n . '</p>';
    echo $lang_form;
    echo n, '<div class="txp-listtables">', startTable('', '', 'txp-list'), '<thead>', tr(hCell(gTxt('language')) . hCell(gTxt('from_server') . n . popHelp('install_lang_from_server')) . hCell(gTxt('from_file') . n . popHelp('install_lang_from_file'), '', ' class="languages_detail"') . hCell(gTxt('remove_lang') . n . popHelp('remove_lang'), '', ' class="languages_detail"')), '</thead>';
    echo '<tbody>' . $list . '</tbody>', endTable(), n, '</div>';
    echo graf(toggle_box('languages_detail'), ' class="detail-toggle"');
    echo hed(gTxt('install_from_textpack'), 3) . n . form(graf('<label for="textpack-install">' . gTxt('install_textpack') . '</label>' . n . popHelp('get_textpack') . n . '<textarea id="textpack-install" class="code" name="textpack" cols="' . INPUT_LARGE . '" rows="' . INPUT_XSMALL . '"></textarea>' . n . fInput('submit', 'install_new', gTxt('upload')) . eInput('prefs') . sInput('get_textpack')), '', '', 'post', 'edit-form', '', 'text_uploader');
    echo '</div>';
    // end language_container
}
Example #19
0
/**
 * Renders a HTML &lt;select&gt; list of available ways to display the date.
 *
 * Can be altered by plugins via the 'prefs_ui > dateformats'
 * pluggable UI callback event.
 *
 * @param  string $name HTML name and id of the widget
 * @param  string $val  Initial (or current) selected item
 * @return string HTML
 */
function dateformats($name, $val)
{
    $dayname = '%A';
    $dayshort = '%a';
    $daynum = is_numeric(@strftime('%e')) ? '%e' : '%d';
    $daynumlead = '%d';
    $daynumord = is_numeric(substr(trim(@strftime('%Oe')), 0, 1)) ? '%Oe' : $daynum;
    $monthname = '%B';
    $monthshort = '%b';
    $monthnum = '%m';
    $year = '%Y';
    $yearshort = '%y';
    $time24 = '%H:%M';
    $time12 = @strftime('%p') ? '%I:%M %p' : $time24;
    $date = @strftime('%x') ? '%x' : '%Y-%m-%d';
    $formats = array("{$monthshort} {$daynumord}, {$time12}", "{$daynum}.{$monthnum}.{$yearshort}", "{$daynumord} {$monthname}, {$time12}", "{$yearshort}.{$monthnum}.{$daynumlead}, {$time12}", "{$dayshort} {$monthshort} {$daynumord}, {$time12}", "{$dayname} {$monthname} {$daynumord}, {$year}", "{$monthshort} {$daynumord}", "{$daynumord} {$monthname} {$yearshort}", "{$daynumord} {$monthnum} {$year} - {$time24}", "{$daynumord} {$monthname} {$year}", "{$daynumord} {$monthname} {$year}, {$time24}", "{$daynumord}. {$monthname} {$year}", "{$daynumord}. {$monthname} {$year}, {$time24}", "{$year}-{$monthnum}-{$daynumlead}", "{$year}-{$daynumlead}-{$monthnum}", "{$date} {$time12}", "{$date}", "{$time24}", "{$time12}", "{$year}-{$monthnum}-{$daynumlead} {$time24}");
    $ts = time();
    $vals = array();
    foreach ($formats as $f) {
        if ($d = safe_strftime($f, $ts)) {
            $vals[$f] = $d;
        }
    }
    $vals['since'] = gTxt('hours_days_ago');
    return pluggable_ui('prefs_ui', 'dateformats', selectInput($name, array_unique($vals), $val, '', '', $name), compact('vals', 'name', 'val', 'ts'));
}
Example #20
0
/**
 * The main panel listing all authors.
 *
 * @param string|array $message The activity message
 */
function author_list($message = '')
{
    global $event, $txp_user, $author_list_pageby, $levels;
    pagetop(gTxt('tab_site_admin'), $message);
    if (is_disabled('mail')) {
        echo graf(span(null, array('class' => 'ui-icon ui-icon-alert')) . ' ' . gTxt('warn_mail_unavailable'), array('class' => 'alert-block warning'));
    }
    $buttons = array();
    // Change password button.
    $buttons[] = sLink('admin', 'new_pass_form', gTxt('change_password'), 'txp-button');
    if (!has_privs('admin.edit')) {
        // Change email address button.
        $buttons[] = sLink('admin', 'change_email_form', gTxt('change_email_address'), 'txp-button');
    } else {
        // New author button.
        $buttons[] = sLink('admin', 'author_edit', gTxt('add_new_author'), 'txp-button');
    }
    // User list.
    if (has_privs('admin.list')) {
        extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
        if ($sort === '') {
            $sort = get_pref('admin_sort_column', 'name');
        } else {
            if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) {
                $sort = 'name';
            }
            set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE);
        }
        if ($dir === '') {
            $dir = get_pref('admin_sort_dir', 'asc');
        } else {
            $dir = $dir == 'desc' ? "desc" : "asc";
            set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE);
        }
        $sort_sql = $sort . ' ' . $dir;
        $switch_dir = $dir == 'desc' ? 'asc' : 'desc';
        $search = new Filter($event, array('login' => array('column' => 'txp_users.name', 'label' => gTxt('login_name')), 'RealName' => array('column' => 'txp_users.RealName', 'label' => gTxt('real_name')), 'email' => array('column' => 'txp_users.email', 'label' => gTxt('email')), 'privs' => array('column' => array('txp_users.privs'), 'label' => gTxt('privileges'), 'type' => 'boolean')));
        $search->setAliases('privs', $levels);
        list($criteria, $crit, $search_method) = $search->getFilter();
        $search_render_options = array('placeholder' => 'search_users');
        $total = getCount('txp_users', $criteria);
        echo n . tag(hed(gTxt('tab_site_admin'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1'));
        $searchBlock = n . tag($search->renderForm('author_list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => 'users_control'));
        $createBlock = array();
        $createBlock[] = n . tag(implode(n, $buttons), 'div', array('class' => 'txp-control-panel'));
        $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => 'users_container'));
        $createBlock = implode(n, $createBlock);
        if ($total < 1) {
            if ($criteria != 1) {
                echo $searchBlock . $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')) . n . tag_end('div');
            }
            return;
        }
        $limit = max($author_list_pageby, 15);
        list($page, $offset, $numPages) = pager($total, $limit, $page);
        $use_multi_edit = has_privs('admin.edit') && ($total > 1 or safe_count('txp_users', "1 = 1") > 1);
        echo $searchBlock . $contentBlockStart . $createBlock;
        $rs = safe_rows_start("*, UNIX_TIMESTAMP(last_access) AS last_login", 'txp_users', "{$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}");
        if ($rs) {
            echo n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'users_form', 'name' => 'longform', 'method' => 'post', 'action' => 'index.php')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(($use_multi_edit ? hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') : hCell('', '', ' class="txp-list-col-multi-edit" scope="col"')) . column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-login-name name') . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', ('RealName' == $sort ? "{$dir} " : '') . 'txp-list-col-real-name name') . column_head('email', 'email', 'admin', true, $switch_dir, '', '', ('email' == $sort ? "{$dir} " : '') . 'txp-list-col-email') . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', ('privs' == $sort ? "{$dir} " : '') . 'txp-list-col-privs') . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', ('last_login' == $sort ? "{$dir} " : '') . 'txp-list-col-last-login date')) . n . tag_end('thead') . n . tag_start('tbody');
            while ($a = nextRow($rs)) {
                extract(doSpecial($a));
                echo tr(td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name'], 'checkbox') : '', '', 'txp-list-col-multi-edit') . hCell(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, $name) : $name, '', ' class="txp-list-col-login-name name" scope="row"') . td($RealName, '', 'txp-list-col-real-name name') . td(href($email, 'mailto:' . $email), '', 'txp-list-col-email') . td(get_priv_level($privs), '', 'txp-list-col-privs') . td($last_login ? safe_strftime('%b&#160;%Y', $last_login) : '', '', 'txp-list-col-last-login date'));
            }
            echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . ($use_multi_edit ? author_multiedit_form($page, $sort, $dir, $crit, $search_method) : '') . tInput() . n . tag_end('form') . n . tag_start('div', array('class' => 'txp-navigation', 'id' => 'users_navigation')) . pageby_form('admin', $author_list_pageby) . nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method) . n . tag_end('div');
        }
        echo n . tag_end('div');
    } else {
        echo n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => 'users_container')) . n . tag(implode(n, $buttons), 'div', array('class' => 'txp-control-panel')) . n . tag_end('div');
    }
}
Example #21
0
function author_list()
{
    global $txp_user, $author_list_pageby;
    extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
    if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) {
        $sort = 'name';
    }
    $dir = $dir == 'desc' ? 'desc' : 'asc';
    $sort_sql = $sort . ' ' . $dir;
    $switch_dir = $dir == 'desc' ? 'asc' : 'desc';
    $total = getCount('txp_users', '1=1');
    $limit = max($author_list_pageby, 15);
    list($page, $offset, $numPages) = pager($total, $limit, $page);
    $rs = safe_rows_start('*, unix_timestamp(last_access) as last_login', 'txp_users', '1 = 1 order by ' . $sort_sql . ' limit ' . $offset . ', ' . $limit);
    if ($rs) {
        echo '<form action="index.php" method="post" name="longform" onsubmit="return verify(\'' . gTxt('are_you_sure') . '\')">' . startTable('list') . tr(column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', 'name' == $sort ? $dir : '') . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', 'RealName' == $sort ? $dir : '') . column_head('email', 'email', 'admin', true, $switch_dir, '', '', 'email' == $sort ? $dir : '') . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', 'privs' == $sort ? $dir : '') . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', 'last_login' == $sort ? $dir : '') . hCell() . hCell());
        while ($a = nextRow($rs)) {
            extract(doSpecial($a));
            echo tr(td($name) . td($RealName) . td('<a href="mailto:' . $email . '">' . $email . '</a>') . td(get_priv_level($privs)) . td($last_login ? safe_strftime('%b&#160;%Y', $last_login) : '') . td(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, gTxt('edit')) : '') . td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name']) : ''));
        }
        echo n . n . tr(tda(select_buttons() . author_multiedit_form($page, $sort, $dir, $crit, $search_method), ' colspan="6" style="text-align: right; border: none;"')) . endTable() . '</form>' . nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method) . pageby_form('admin', $author_list_pageby);
    }
}
Example #22
0
function preText($s, $prefs)
{
    extract($prefs);
    if (gps('rss')) {
        include txpath . '/publish/rss.php';
        exit(rss());
    }
    if (gps('atom')) {
        include txpath . '/publish/atom.php';
        exit(atom());
    }
    // set messy variables
    $out = makeOut('id', 's', 'c', 'q', 'pg', 'p', 'month');
    // some useful vars for taghandlers, plugins
    $out['request_uri'] = serverSet('REQUEST_URI');
    $out['qs'] = serverSet('QUERY_STRING');
    // IIS - can someone confirm whether or not this works?
    if (!$out['request_uri'] and $argv = serverSet('argv')) {
        $out['request_uri'] = @substr($argv[0], strpos($argv[0], ';' + 1));
    }
    // define the useable url, minus any subdirectories.
    // this is pretty fugly, if anyone wants to have a go at it - dean
    $out['subpath'] = $subpath = preg_quote(preg_replace("/http:\\/\\/.*(\\/.*)/Ui", "\$1", hu), "/");
    $out['req'] = $req = preg_replace("/^{$subpath}/i", "/", serverSet('REQUEST_URI'));
    // if messy vars exist, bypass url parsing
    if (!$out['id'] && !$out['s']) {
        extract(chopUrl($req));
        //first we sniff out some of the preset url schemes
        if (!empty($u1)) {
            switch ($u1) {
                case 'atom':
                    include txpath . '/publish/atom.php';
                    exit(atom());
                case 'rss':
                    include txpath . '/publish/rss.php';
                    exit(rss());
                case strtolower(gTxt('section')):
                    $out['s'] = ckEx('section', $u2) ? $u2 : 'default';
                    break;
                case strtolower(gTxt('category')):
                    $out['c'] = ckEx('category', $u2) ? $u2 : '';
                    break;
                case urlencode(gTxt('author')):
                    $author_name = !empty($u2) ? urldecode($u2) : '';
                    $out['author'] = safe_field('name', 'txp_users', "RealName like '{$author_name}'");
                    break;
                case strtolower(gTxt('file_download')):
                    $out['s'] = 'file_download';
                    $out['id'] = !empty($u2) ? $u2 : '';
                    break;
                case 'p':
                    $out['p'] = is_numeric($u2) ? $u2 : '';
                    break;
                default:
                    // then see if the prefs-defined permlink scheme is usable
                    switch ($permlink_mode) {
                        case 'section_id_title':
                            $out['s'] = ckEx('section', $u1) ? $u1 : 'default';
                            $out['id'] = is_numeric($u2) && ckExID($u2) ? $u2 : '';
                            break;
                        case 'year_month_day_title':
                            if (empty($u4)) {
                                $out['month'] = "{$u1}-{$u2}";
                                if (!empty($u3)) {
                                    $out['month'] .= "-{$u3}";
                                }
                                $out['s'] = 'default';
                            } else {
                                $when = safe_strftime('%Y-%m-%d', strtotime("{$u1}-{$u2}-{$u3}"));
                                $rs = lookupByDateTitle($when, $u4);
                                $out['id'] = !empty($rs['ID']) ? $rs['ID'] : '';
                                $out['s'] = !empty($rs['Section']) ? $rs['Section'] : '';
                            }
                            break;
                        case 'section_title':
                            $rs = lookupByTitleSection($u2, $u1);
                            $out['id'] = !empty($rs['ID']) ? $rs['ID'] : '';
                            $out['s'] = ckEx('section', $u1) ? $u1 : 'default';
                            break;
                        case 'title_only':
                            $rs = lookupByTitle($u1);
                            $out['id'] = !empty($rs['ID']) ? $rs['ID'] : '';
                            $out['s'] = !empty($rs['Section']) ? $rs['Section'] : ckEx('section', $u1) ? $u1 : 'default';
                            break;
                        case 'id_title':
                            if (is_numeric($u1) && ckExID($u1)) {
                                $rs = lookupByID($u1);
                                $out['id'] = !empty($rs['ID']) ? $rs['ID'] : '';
                                $out['s'] = !empty($rs['Section']) ? $rs['Section'] : 'default';
                            } else {
                                # We don't want to miss the /section/ pages
                                $out['s'] = ckEx('section', $u1) ? $u1 : 'default';
                            }
                            break;
                    }
            }
        } else {
            $out['s'] = 'default';
        }
    } else {
        // Messy mode, but prevent to get the id for file_downloads
        if ($out['id'] && !$out['s']) {
            $out['s'] = safe_field('section', 'textpattern', "ID='" . doSlash($out['id']) . "'");
        }
    }
    if ($out['s'] == 'file_download') {
        // get id of potential filename
        if (!is_numeric($out['id'])) {
            $rs = safe_row("*", "txp_file", "filename='" . $out['id'] . "'");
        } else {
            $rs = safe_row("*", "txp_file", "id='" . $out['id'] . "'");
        }
        $out = $rs ? array_merge($out, $rs) : array('s' => 'file_download', 'file_error' => 404);
        return $out;
    }
    $out['s'] = empty($out['s']) ? 'default' : $out['s'];
    $s = $out['s'];
    $id = $out['id'];
    // hackish
    if (empty($id)) {
        $GLOBALS['is_article_list'] = true;
    }
    // by this point we should know the section, so grab its page and css
    $rs = safe_row("*", "txp_section", "name = '{$s}' limit 1");
    $out['page'] = @$rs['page'];
    $out['css'] = @$rs['css'];
    if (is_numeric($id)) {
        $idrs = safe_row("Posted, AuthorID, Keywords", "textpattern", "ID={$id}");
        extract($idrs);
        if ($np = getNextPrev($id, $Posted, $s)) {
            $out = array_merge($out, $np);
        }
        $out['id_keywords'] = $Keywords;
        $out['id_author'] = get_author_name($AuthorID);
    }
    $out['path_from_root'] = $path_from_root;
    // these are deprecated as of 1.0
    $out['pfr'] = $path_from_root;
    // leaving them here for plugin compat
    $out['path_to_site'] = $path_to_site;
    $out['permlink_mode'] = $permlink_mode;
    $out['sitename'] = htmlspecialchars($sitename);
    return $out;
}
Example #23
0
function rss()
{
    global $prefs, $thisarticle;
    set_error_handler('feedErrorHandler');
    ob_clean();
    extract($prefs);
    extract(doSlash(gpsa(array('limit', 'area'))));
    // build filter criteria from a comma-separated list of sections and categories
    $feed_filter_limit = get_pref('feed_filter_limit', 10);
    $section = gps('section');
    $category = gps('category');
    if (!is_scalar($section) || !is_scalar($category)) {
        txp_die('Not Found', 404);
    }
    $section = $section ? array_slice(array_unique(do_list($section)), 0, $feed_filter_limit) : array();
    $category = $category ? array_slice(array_unique(do_list($category)), 0, $feed_filter_limit) : array();
    $st = array();
    foreach ($section as $s) {
        $st[] = fetch_section_title($s);
    }
    $ct = array();
    foreach ($category as $c) {
        $ct[] = fetch_category_title($c);
    }
    $sitename .= $section ? ' - ' . join(' - ', $st) : '';
    $sitename .= $category ? ' - ' . join(' - ', $ct) : '';
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    // feed header
    $out[] = tag('http://textpattern.com/?v=' . $version, 'generator');
    $out[] = tag(doSpecial($sitename), 'title');
    $out[] = tag(hu, 'link');
    $out[] = '<atom:link href="' . pagelinkurl(array('rss' => 1, 'area' => $area, 'section' => $section, 'category' => $category, 'limit' => $limit)) . '" rel="self" type="application/rss+xml" />';
    $out[] = tag(doSpecial($site_slogan), 'description');
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    $out[] = tag(safe_strftime('rfc822', $last), 'pubDate');
    $out[] = callback_event('rss_head');
    // feed items
    $articles = array();
    $section = doSlash($section);
    $category = doSlash($category);
    if (!$area or $area == 'article') {
        $sfilter = !empty($section) ? "and Section in ('" . join("','", $section) . "')" : '';
        $cfilter = !empty($category) ? "and (Category1 in ('" . join("','", $category) . "') or Category2 in ('" . join("','", $category) . "'))" : '';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $frs = safe_column("name", "txp_section", "in_rss != '1'");
        if ($frs) {
            foreach ($frs as $f) {
                $query[] = "and Section != '" . doSlash($f) . "'";
            }
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $expired = $publish_expired_articles ? '' : ' and (now() <= Expires or Expires = ' . NULLDATETIME . ') ';
        $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, unix_timestamp(LastMod) as uLastMod, unix_timestamp(Expires) as uExpires, ID as thisid", "textpattern", "Status = 4 " . join(' ', $query) . "and Posted < now()" . $expired . "order by Posted desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event('rss_entry');
                $a['posted'] = $uPosted;
                $permlink = permlinkurl($a);
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    # short feed: use body as summary if there's no excerpt
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if ($show_comment_count_in_feed) {
                    $count = $comments_count > 0 ? ' [' . $comments_count . ']' : '';
                } else {
                    $count = '';
                }
                $Title = escape_title(strip_tags($Title)) . $count;
                $thisauthor = get_author_name($AuthorID);
                $item = tag($Title, 'title') . n . (trim($summary) ? tag(n . escape_cdata($summary) . n, 'description') . n : '') . (trim($content) ? tag(n . escape_cdata($content) . n, 'content:encoded') . n : '') . tag($permlink, 'link') . n . tag(safe_strftime('rfc822', $a['posted']), 'pubDate') . n . tag(htmlspecialchars($thisauthor), 'dc:creator') . n . tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'guid', ' isPermaLink="false"') . n . $cb;
                $articles[$ID] = tag($item, 'item');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uPosted;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category in ('" . join("','", $category) . "')" : '1';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $rs = safe_rows_start("*, unix_timestamp(date) as uDate", "txp_link", "{$cfilter} order by date desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $item = tag(doSpecial($linkname), 'title') . n . tag(doSpecial($description), 'description') . n . tag(doSpecial($url), 'link') . n . tag(safe_strftime('rfc822', $uDate), 'pubDate');
                $articles[$id] = tag($item, 'item');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!$articles) {
        if ($section) {
            if (safe_field('name', 'txp_section', "name in ('" . join("','", $section) . "')") == false) {
                txp_die(gTxt('404_not_found'), '404');
            }
        } elseif ($category) {
            switch ($area) {
                case 'link':
                    if (safe_field('id', 'txp_category', "name = '{$category}' and type = 'link'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
                case 'article':
                default:
                    if (safe_field('id', 'txp_category', "name in ('" . join("','", $category) . "') and type = 'article'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
            }
        }
    } else {
        //turn on compression if we aren't using it already
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            // make sure notices/warnings/errors don't fudge up the feed
            // when compression is used
            $buf = '';
            while ($b = @ob_get_clean()) {
                $buf .= $b;
            }
            @ob_start('ob_gzhandler');
            echo $buf;
        }
        handle_lastmod();
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        $imsd = $hims ? strtotime($hims) : 0;
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id]) !== false) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } else {
            if (isset($cut_etag)) {
                header("Vary: If-None-Match");
            } else {
                if (isset($cut_time)) {
                    header("Vary: If-Modified-Since");
                }
            }
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            txp_status_header('304 Not Modified');
            exit(0);
        }
        if ($cutarticles) {
            //header("HTTP/1.1 226 IM Used");
            //This should be used as opposed to 200, but Apache doesn't like it.
            //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
    }
    $out = array_merge($out, $articles);
    header("Content-Type: application/rss+xml; charset=utf-8");
    if (isset($etag)) {
        header('ETag: "' . $etag . '"');
    }
    return '<?xml version="1.0" encoding="utf-8"?>' . n . '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">' . n . tag(join(n, $out), 'channel') . n . '</rss>';
}
Example #24
0
function author_list($message = '')
{
    global $txp_user, $author_list_pageby;
    pagetop(gTxt('tab_site_admin'), $message);
    if (is_disabled('mail')) {
        echo tag(gTxt('warn_mail_unavailable'), 'p', ' class="alert-block warning" ');
    }
    echo '<h1 class="txp-heading">' . gTxt('tab_site_admin') . '</h1>';
    echo '<div id="users_control" class="txp-control-panel">';
    // Change password button
    echo '<p class="txp-buttons">';
    echo sLink('admin', 'new_pass_form', gTxt('change_password'));
    // Change email address button
    if (!has_privs('admin.edit')) {
        echo n . sLink('admin', 'change_email_form', gTxt('change_email_address'));
    }
    // User list
    if (has_privs('admin.list')) {
        extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
        if ($sort === '') {
            $sort = get_pref('admin_sort_column', 'name');
        }
        if ($dir === '') {
            $dir = get_pref('admin_sort_dir', 'asc');
        }
        $dir = $dir == 'desc' ? 'desc' : 'asc';
        if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) {
            $sort = 'name';
        }
        $sort_sql = $sort . ' ' . $dir;
        set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE);
        set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE);
        $switch_dir = $dir == 'desc' ? 'asc' : 'desc';
        $criteria = 1;
        if ($search_method and $crit != '') {
            $crit_escaped = doSlash(str_replace(array('\\', '%', '_', '\''), array('\\\\', '\\%', '\\_', '\\\''), $crit));
            $critsql = array('id' => "user_id in ('" . join("','", do_list($crit_escaped)) . "')", 'login' => "name like '%{$crit_escaped}%'", 'real_name' => "RealName like '%{$crit_escaped}%'", 'email' => "email like '%{$crit_escaped}%'", 'privs' => "privs in ('" . join("','", do_list($crit_escaped)) . "')");
            if (array_key_exists($search_method, $critsql)) {
                $criteria = $critsql[$search_method];
            } else {
                $search_method = '';
                $crit = '';
            }
        } else {
            $search_method = '';
            $crit = '';
        }
        $criteria .= callback_event('admin_criteria', 'author_list', 0, $criteria);
        $total = getCount('txp_users', $criteria);
        // New author button
        if (has_privs('admin.edit')) {
            echo n . sLink('admin', 'author_edit', gTxt('add_new_author'));
        }
        echo '</p>';
        // end txp-buttons
        if ($total < 1) {
            if ($criteria != 1) {
                echo n . author_search_form($crit, $search_method) . n . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>';
            }
            return;
        }
        $limit = max($author_list_pageby, 15);
        list($page, $offset, $numPages) = pager($total, $limit, $page);
        $use_multi_edit = has_privs('admin.edit') && safe_count('txp_users', '1=1') > 1;
        echo author_search_form($crit, $search_method) . '</div>';
        $rs = safe_rows_start('*, unix_timestamp(last_access) as last_login', 'txp_users', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}");
        if ($rs) {
            echo n . '<div id="users_container" class="txp-container">';
            echo '<form action="index.php" id="users_form" class="multi_edit_form" method="post" name="longform">' . n . '<div class="txp-listtables">' . n . startTable('', '', 'txp-list') . n . '<thead>' . n . tr(n . ($use_multi_edit ? hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' title="' . gTxt('toggle_all_selected') . '" class="multi-edit"') : hCell('', '', ' class="multi-edit"')) . n . column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', ('name' == $sort ? "{$dir} " : '') . 'name login-name') . n . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', ('RealName' == $sort ? "{$dir} " : '') . 'name real-name') . n . column_head('email', 'email', 'admin', true, $switch_dir, '', '', ('email' == $sort ? "{$dir} " : '') . 'email') . n . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', ('privs' == $sort ? "{$dir} " : '') . 'privs') . n . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', ('last_login' == $sort ? "{$dir} " : '') . 'date last-login modified')) . n . '</thead>';
            echo '<tbody>';
            while ($a = nextRow($rs)) {
                extract(doSpecial($a));
                echo tr(td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name'], 'checkbox') : '', '', 'multi-edit') . td(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, $name) : $name, '', 'name login-name') . td($RealName, '', 'name real-name') . td('<a href="mailto:' . $email . '">' . $email . '</a>', '', 'email') . td(get_priv_level($privs), '', 'privs') . td($last_login ? safe_strftime('%b&#160;%Y', $last_login) : '', '', 'date last-login modified'));
            }
            echo '</tbody>', n, endTable(), n, '</div>', n, $use_multi_edit ? author_multiedit_form($page, $sort, $dir, $crit, $search_method) : '', n, tInput(), n, '</form>', n, '<div id="users_navigation" class="txp-navigation">', n, nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method), n, pageby_form('admin', $author_list_pageby), n, '</div>', n, '</div>';
        }
    } else {
        echo '</div>';
    }
}
 public function __construct($limit, $reverse)
 {
     $this->limit = $limit;
     $this->reverse = $reverse;
     // for cache comparison
     $this->currentDate = safe_strftime('%Y-%m-%d');
     // use current date if used in a page template
     if ($GLOBALS['is_article_list'] && empty($GLOBALS['thisarticle'])) {
         $this->date = $this->currentDate;
     } else {
         $this->date = posted(array('format' => '%Y-%m-%d'));
     }
     // need the day in "Month_DAY" format
     $this->day = strftime('%B_%e', strtotime($this->date));
     // for days 1-9, remove an extra space
     $this->day = str_replace(' ', '', $this->day);
     // construct URI
     $this->rootUri = 'http://en.wikipedia.org/wiki/';
     $this->uri = $this->rootUri . $this->day;
 }
Example #26
0
function tsi($name, $datevar, $time, $tab = '')
{
    $size = ($name == 'year' or $name == 'exp_year') ? 4 : 2;
    $s = $time == 0 ? '' : safe_strftime($datevar, $time);
    return n . '<input type="text" name="' . $name . '" value="' . $s . '" size="' . $size . '" maxlength="' . $size . '" class="edit ' . $name . '"' . (empty($tab) ? '' : ' tabindex="' . $tab . '"') . ' title="' . gTxt('article_' . $name) . '" />';
}
Example #27
0
function article_edit($message = '', $concurrent = FALSE)
{
    global $vars, $txp_user, $comments_disabled_after, $txpcfg, $prefs;
    extract($prefs);
    extract(gpsa(array('view', 'from_view', 'step')));
    if (!empty($GLOBALS['ID'])) {
        // newly-saved article
        $ID = $GLOBALS['ID'];
        $step = 'edit';
    } else {
        $ID = gps('ID');
    }
    include_once txpath . '/lib/classTextile.php';
    $textile = new Textile();
    // switch to 'text' view upon page load and after article post
    if (!$view || gps('save') || gps('publish')) {
        $view = 'text';
    }
    if (!$step) {
        $step = "create";
    }
    if ($step == "edit" && $view == "text" && !empty($ID) && $from_view != 'preview' && $from_view != 'html' && !$concurrent) {
        $pull = true;
        //-- it's an existing article - off we go to the db
        $ID = assert_int($ID);
        $rs = safe_row("*, unix_timestamp(Posted) as sPosted,\n\t\t\t\tunix_timestamp(Expires) as sExpires,\n\t\t\t\tunix_timestamp(LastMod) as sLastMod", "textpattern", "ID={$ID}");
        extract($rs);
        $reset_time = $publish_now = $Status < 4;
    } else {
        $pull = false;
        //-- assume they came from post
        if ($from_view == 'preview' or $from_view == 'html') {
            $store_out = array();
            $store = unserialize(base64_decode(ps('store')));
            foreach ($vars as $var) {
                if (isset($store[$var])) {
                    $store_out[$var] = $store[$var];
                }
            }
        } else {
            $store_out = gpsa($vars);
            if ($concurrent) {
                $store_out['sLastMod'] = safe_field('unix_timestamp(LastMod) as sLastMod', 'textpattern', 'ID=' . $ID);
            }
        }
        extract($store_out);
    }
    $GLOBALS['step'] = $step;
    if ($step == 'create') {
        $textile_body = $use_textile;
        $textile_excerpt = $use_textile;
    }
    if ($step != 'create') {
        // Previous record?
        $prev_id = checkIfNeighbour('prev', $sPosted);
        // Next record?
        $next_id = checkIfNeighbour('next', $sPosted);
    }
    $page_title = $Title ? $Title : gTxt('write');
    pagetop($page_title, $message);
    echo n . n . '<form name="article" method="post" action="index.php">';
    if (!empty($store_out)) {
        echo hInput('store', base64_encode(serialize($store_out)));
    }
    echo hInput('ID', $ID) . eInput('article') . sInput($step) . '<input type="hidden" name="view" />' . startTable('edit') . '<tr>' . n . '<td id="article-col-1">';
    if ($view == 'text') {
        //-- markup help --------------
        echo side_help($textile_body, $textile_excerpt) . '<h3 class="plain"><a href="#advanced" onclick="toggleDisplay(\'advanced\'); return false;">' . gTxt('advanced_options') . '</a></h3>', '<div id="advanced" class="toggle" style="display:none">', n . graf('<label for="markup-body">' . gTxt('article_markup') . '</label>' . br . pref_text('textile_body', $textile_body, 'markup-body')), n . graf('<label for="markup-excerpt">' . gTxt('excerpt_markup') . '</label>' . br . pref_text('textile_excerpt', $textile_excerpt, 'markup-excerpt')), $allow_form_override ? graf('<label for="override-form">' . gTxt('override_default_form') . '</label>' . sp . popHelp('override_form') . br . form_pop($override_form, 'override-form')) : '', $custom_1_set ? custField(1, $custom_1_set, $custom_1) : '', $custom_2_set ? custField(2, $custom_2_set, $custom_2) : '', $custom_3_set ? custField(3, $custom_3_set, $custom_3) : '', $custom_4_set ? custField(4, $custom_4_set, $custom_4) : '', $custom_5_set ? custField(5, $custom_5_set, $custom_5) : '', $custom_6_set ? custField(6, $custom_6_set, $custom_6) : '', $custom_7_set ? custField(7, $custom_7_set, $custom_7) : '', $custom_8_set ? custField(8, $custom_8_set, $custom_8) : '', $custom_9_set ? custField(9, $custom_9_set, $custom_9) : '', $custom_10_set ? custField(10, $custom_10_set, $custom_10) : '', n . graf('<label for="keywords">' . gTxt('keywords') . '</label>' . sp . popHelp('keywords') . br . n . '<textarea id="keywords" name="Keywords" cols="18" rows="5">' . htmlspecialchars(str_replace(',', ', ', $Keywords)) . '</textarea>'), n . graf('<label for="article-image">' . gTxt('article_image') . '</label>' . sp . popHelp('article_image') . br . fInput('text', 'Image', $Image, 'edit', '', '', 22, '', 'article-image')), n . graf('<label for="url-title">' . gTxt('url_title') . '</label>' . sp . popHelp('url_title') . br . fInput('text', 'url_title', $url_title, 'edit', '', '', 22, '', 'url-title')), '</div>

			<h3 class="plain"><a href="#recent" onclick="toggleDisplay(\'recent\'); return false;">' . gTxt('recent_articles') . '</a>' . '</h3>' . '<div id="recent" class="toggle" style="display:none">';
        $recents = safe_rows_start("Title, ID", 'textpattern', "1=1 order by LastMod desc limit 10");
        if ($recents) {
            echo '<ul class="plain-list">';
            while ($recent = nextRow($recents)) {
                if (!$recent['Title']) {
                    $recent['Title'] = gTxt('untitled') . sp . $recent['ID'];
                }
                echo n . t . '<li><a href="?event=article' . a . 'step=edit' . a . 'ID=' . $recent['ID'] . '">' . escape_title($recent['Title']) . '</a></li>';
            }
            echo '</ul>';
        }
        echo '</div>';
    } else {
        echo sp;
    }
    echo '</td>' . n . '<td id="article-main">';
    //-- title input --------------
    if ($view == 'preview') {
        echo hed(gTxt('preview'), 2) . hed($Title, 1);
    } elseif ($view == 'html') {
        echo hed('XHTML', 2) . hed($Title, 1);
    } elseif ($view == 'text') {
        echo n . '<p><label for="title">' . gTxt('title') . '</label>' . sp . popHelp('title') . br . '<input type="text" id="title" name="Title" value="' . escape_title($Title) . '" class="edit" size="40" tabindex="1" />';
        if ($step != 'create') {
            include_once txpath . '/publish/taghandlers.php';
            $url = permlinkurl_id($ID);
            if ($Status != 4 and $Status != 5) {
                $url .= (strpos($url, '?') === FALSE ? '?' : '&amp;') . 'txpreview=' . intval($ID) . '.' . time();
            }
            echo sp . sp . '<a href="' . $url . '" class="article-view">' . gTxt('view') . '</a>';
        }
        echo '</p>';
    }
    //-- body --------------------
    if ($view == 'preview') {
        if ($textile_body == USE_TEXTILE) {
            echo $textile->TextileThis($Body);
        } else {
            if ($textile_body == CONVERT_LINEBREAKS) {
                echo nl2br($Body);
            } else {
                if ($textile_body == LEAVE_TEXT_UNTOUCHED) {
                    echo $Body;
                }
            }
        }
    } elseif ($view == 'html') {
        if ($textile_body == USE_TEXTILE) {
            $bod = $textile->TextileThis($Body);
        } else {
            if ($textile_body == CONVERT_LINEBREAKS) {
                $bod = nl2br($Body);
            } else {
                if ($textile_body == LEAVE_TEXT_UNTOUCHED) {
                    $bod = $Body;
                }
            }
        }
        echo tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($bod)), 'code');
    } else {
        echo n . graf('<label for="body">' . gTxt('body') . '</label>' . sp . popHelp('body') . br . '<textarea id="body" name="Body" cols="55" rows="31" tabindex="2">' . htmlspecialchars($Body) . '</textarea>');
    }
    //-- excerpt --------------------
    if ($articles_use_excerpts) {
        if ($view == 'text') {
            echo n . graf('<label for="excerpt">' . gTxt('excerpt') . '</label>' . sp . popHelp('excerpt') . br . '<textarea id="excerpt" name="Excerpt" cols="55" rows="5" tabindex="3">' . htmlspecialchars($Excerpt) . '</textarea>');
        } else {
            echo n . '<hr width="50%" />';
            echo $textile_excerpt == USE_TEXTILE ? $view == 'preview' ? graf($textile->textileThis($Excerpt)) : tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($textile->TextileThis($Excerpt))), 'code') : graf($Excerpt);
        }
    }
    //-- author --------------
    if ($view == "text" && $step != "create") {
        echo '<p class="small">' . gTxt('posted_by') . ': ' . htmlspecialchars($AuthorID) . ' &#183; ' . safe_strftime('%d %b %Y &#183; %X', $sPosted);
        if ($sPosted != $sLastMod) {
            echo br . gTxt('modified_by') . ': ' . htmlspecialchars($LastModID) . ' &#183; ' . safe_strftime('%d %b %Y &#183; %X', $sLastMod);
        }
        echo '</p>';
    }
    echo hInput('from_view', $view), '</td>';
    echo '<td id="article-tabs">';
    //-- layer tabs -------------------
    echo $use_textile == USE_TEXTILE || $textile_body == USE_TEXTILE ? '<ul>' . (tab('text', $view) . tab('html', $view) . tab('preview', $view)) . '</ul>' : '&#160;';
    echo '</td>';
    echo '<td id="article-col-2">';
    if ($view == 'text') {
        if ($step != 'create') {
            echo n . graf(href(gtxt('create_new'), 'index.php?event=article'));
        }
        //-- prev/next article links --
        if ($step != 'create' and ($prev_id or $next_id)) {
            echo '<p>', $prev_id ? prevnext_link('&#8249;' . gTxt('prev'), 'article', 'edit', $prev_id, gTxt('prev')) : '', $next_id ? prevnext_link(gTxt('next') . '&#8250;', 'article', 'edit', $next_id, gTxt('next')) : '', '</p>';
        }
        //-- status radios --------------
        echo n . n . '<fieldset id="write-status">' . n . '<legend>' . gTxt('status') . '</legend>' . n . status_radio($Status) . n . '</fieldset>';
        //-- category selects -----------
        echo n . n . '<fieldset id="write-sort">' . n . '<legend>' . gTxt('sort_display') . '</legend>' . n . graf('<label for="category-1">' . gTxt('category1') . '</label> ' . '<span class="small">[' . eLink('category', '', '', '', gTxt('edit')) . ']</span>' . br . n . category_popup('Category1', $Category1, 'category-1')) . n . graf('<label for="category-2">' . gTxt('category2') . '</label>' . br . n . category_popup('Category2', $Category2, 'category-2'));
        //-- section select --------------
        if (!$from_view && !$pull) {
            $Section = getDefaultSection();
        }
        echo n . graf('<label for="section">' . gTxt('section') . '</label> ' . '<span class="small">[' . eLink('section', '', '', '', gTxt('edit')) . ']</span>' . br . section_popup($Section, 'section')) . n . '</fieldset>' . n . n . '<h3 class="plain"><a href="#more" onclick="toggleDisplay(\'more\'); return false;">' . gTxt('more') . '</a></h3>', '<div id="more" class="toggle" style="display:none">';
        //-- comments stuff --------------
        if ($step == "create") {
            //Avoiding invite disappear when previewing
            $AnnotateInvite = !empty($store_out['AnnotateInvite']) ? $store_out['AnnotateInvite'] : $comments_default_invite;
            if ($comments_on_default == 1) {
                $Annotate = 1;
            }
        }
        if ($use_comments == 1) {
            echo n . n . '<fieldset id="write-comments">' . n . '<legend>' . gTxt('comments') . '</legend>';
            $comments_expired = false;
            if ($step != 'create' && $comments_disabled_after) {
                $lifespan = $comments_disabled_after * 86400;
                $time_since = time() - $sPosted;
                if ($time_since > $lifespan) {
                    $comments_expired = true;
                }
            }
            if ($comments_expired) {
                echo n . n . graf(gTxt('expired'));
            } else {
                echo n . n . graf(onoffRadio('Annotate', $Annotate)) . n . n . graf('<label for="comment-invite">' . gTxt('comment_invitation') . '</label>' . br . fInput('text', 'AnnotateInvite', $AnnotateInvite, 'edit', '', '', '', '', 'comment-invite'));
            }
            echo n . n . '</fieldset>';
        }
        if ($step == "create" and empty($GLOBALS['ID'])) {
            //-- timestamp -------------------
            //Avoiding modified date to disappear
            $persist_timestamp = !empty($store_out['year']) ? safe_strtotime($store_out['year'] . '-' . $store_out['month'] . '-' . $store_out['day'] . ' ' . $store_out['hour'] . ':' . $store_out['minute'] . ':' . $store_out['second']) : time();
            echo n . n . '<fieldset id="write-timestamp">' . n . '<legend>' . gTxt('timestamp') . '</legend>' . n . graf(checkbox('publish_now', '1', $publish_now, '', 'publish_now') . '<label for="publish_now">' . gTxt('set_to_now') . '</label>') . n . graf(gTxt('or_publish_at') . sp . popHelp('timestamp')) . n . graf(gtxt('date') . sp . tsi('year', '%Y', $persist_timestamp) . ' / ' . tsi('month', '%m', $persist_timestamp) . ' / ' . tsi('day', '%d', $persist_timestamp)) . n . graf(gTxt('time') . sp . tsi('hour', '%H', $persist_timestamp) . ' : ' . tsi('minute', '%M', $persist_timestamp) . ' : ' . tsi('second', '%S', $persist_timestamp)) . n . '</fieldset>';
            //-- expires -------------------
            $persist_timestamp = !empty($store_out['exp_year']) ? safe_strtotime($store_out['exp_year'] . '-' . $store_out['exp_month'] . '-' . $store_out['exp_day'] . ' ' . $store_out['exp_hour'] . ':' . $store_out['exp_minute'] . ':' . $store_out['second']) : NULLDATETIME;
            echo n . n . '<fieldset id="write-expires">' . n . '<legend>' . gTxt('expires') . '</legend>' . n . graf(gtxt('date') . sp . tsi('exp_year', '%Y', $persist_timestamp) . ' / ' . tsi('exp_month', '%m', $persist_timestamp) . ' / ' . tsi('exp_day', '%d', $persist_timestamp)) . n . graf(gTxt('time') . sp . tsi('exp_hour', '%H', $persist_timestamp) . ' : ' . tsi('exp_minute', '%M', $persist_timestamp) . ' : ' . tsi('exp_second', '%S', $persist_timestamp)) . n . '</fieldset>' . n . n . '</div>';
            //-- publish button --------------
            echo has_privs('article.publish') ? fInput('submit', 'publish', gTxt('publish'), "publish", '', '', '', 4) : fInput('submit', 'publish', gTxt('save'), "publish", '', '', '', 4);
        } else {
            //-- timestamp -------------------
            if (!empty($year)) {
                $sPosted = safe_strtotime($year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minute . ':' . $second);
            }
            echo n . n . '<fieldset id="write-timestamp">' . n . '<legend>' . gTxt('timestamp') . '</legend>' . n . graf(checkbox('reset_time', '1', $reset_time, '', 'reset_time') . '<label for="reset_time">' . gTxt('reset_time') . '</label>') . n . graf(gTxt('published_at') . sp . popHelp('timestamp')) . n . graf(gtxt('date') . sp . tsi('year', '%Y', $sPosted) . ' / ' . tsi('month', '%m', $sPosted) . ' / ' . tsi('day', '%d', $sPosted)) . n . graf(gTxt('time') . sp . tsi('hour', '%H', $sPosted) . ' : ' . tsi('minute', '%M', $sPosted) . ' : ' . tsi('second', '%S', $sPosted)) . n . hInput('sPosted', $sPosted), n . hInput('sLastMod', $sLastMod), n . hInput('AuthorID', $AuthorID), n . hInput('LastModID', $LastModID), n . '</fieldset>';
            //-- expires -------------------
            if (!empty($exp_year)) {
                if (empty($exp_month)) {
                    $exp_month = 1;
                }
                if (empty($exp_day)) {
                    $exp_day = 1;
                }
                if (empty($exp_hour)) {
                    $exp_hour = 0;
                }
                if (empty($exp_minute)) {
                    $exp_minute = 0;
                }
                if (empty($exp_second)) {
                    $exp_second = 0;
                }
                $sExpires = safe_strtotime($exp_year . '-' . $exp_month . '-' . $exp_day . ' ' . $exp_hour . ':' . $exp_minute . ':' . $exp_second);
            }
            echo n . n . '<fieldset id="write-expires">' . n . '<legend>' . gTxt('expires') . '</legend>' . n . graf(gtxt('date') . sp . tsi('exp_year', '%Y', $sExpires) . ' / ' . tsi('exp_month', '%m', $sExpires) . ' / ' . tsi('exp_day', '%d', $sExpires)) . n . graf(gTxt('time') . sp . tsi('exp_hour', '%H', $sExpires) . ' : ' . tsi('exp_minute', '%M', $sExpires) . ' : ' . tsi('exp_second', '%S', $sExpires)) . n . hInput('sExpires', $sExpires) . n . '</fieldset>' . n . n . '</div>';
            //-- save button --------------
            if ($Status >= 4 and has_privs('article.edit.published') or $Status >= 4 and $AuthorID == $txp_user and has_privs('article.edit.own.published') or $Status < 4 and has_privs('article.edit') or $Status < 4 and $AuthorID == $txp_user and has_privs('article.edit.own')) {
                echo fInput('submit', 'save', gTxt('save'), "publish", '', '', '', 4);
            }
        }
    }
    echo '</td></tr></table></form>';
}
Example #28
0
/**
 * Renders author partial.
 *
 * The rendered widget can be customised via the 'article_ui > author'
 * pluggable UI callback event.
 *
 * @param  array $rs Article data
 * @return string HTML
 */
function article_partial_author($rs)
{
    extract($rs);
    $out = n . '<p class="author"><small>' . gTxt('posted_by') . ': ' . txpspecialchars($AuthorID) . ' &#183; ' . safe_strftime('%d %b %Y &#183; %X', $sPosted);
    if ($sPosted != $sLastMod) {
        $out .= br . gTxt('modified_by') . ': ' . txpspecialchars($LastModID) . ' &#183; ' . safe_strftime('%d %b %Y &#183; %X', $sLastMod);
    }
    $out .= '</small></p>';
    return pluggable_ui('article_ui', 'author', $out, $rs);
}
Example #29
0
function handle_lastmod($unix_ts = NULL, $exit = 1)
{
    global $prefs;
    extract($prefs);
    if ($send_lastmod and $production_status == 'live') {
        $unix_ts = get_lastmod($unix_ts);
        # make sure lastmod isn't in the future
        $unix_ts = min($unix_ts, time());
        # or too far in the past (7 days)
        $unix_ts = max($unix_ts, time() - 3600 * 24 * 7);
        $last = safe_strftime('rfc822', $unix_ts, 1);
        header("Last-Modified: {$last}");
        header('Cache-Control: no-cache');
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        if ($hims and @strtotime($hims) >= $unix_ts) {
            log_hit('304');
            if (!$exit) {
                return array('304', $last);
            }
            txp_status_header('304 Not Modified');
            # some mod_deflate versions have a bug that breaks subsequent
            # requests when keepalive is used.  dropping the connection
            # is the only reliable way to fix this.
            if (empty($lastmod_keepalive)) {
                header('Connection: close');
            }
            header('Content-Length: 0');
            # discard all output
            while (@ob_end_clean()) {
            }
            exit;
        }
        if (!$exit) {
            return array('200', $last);
        }
    }
}
Example #30
0
function list_languages($message = '')
{
    global $prefs, $locale, $txpcfg, $textarray;
    require_once txpath . '/lib/IXRClass.php';
    // Select and save active language
    if (!$message && ps('step') == 'list_languages' && ps('language')) {
        $locale = doSlash(getlocale(ps('language')));
        safe_update("txp_prefs", "val='" . doSlash(ps('language')) . "'", "name='language'");
        safe_update("txp_prefs", "val='" . $locale . "'", "name='locale'");
        $textarray = load_lang(doSlash(ps('language')));
        $locale = setlocale(LC_ALL, $locale);
        $message = gTxt('preferences_saved');
    }
    $active_lang = safe_field('val', 'txp_prefs', "name='language'");
    $lang_form = tda(form(gTxt('active_language') . '&nbsp;&nbsp;' . languages('language', $active_lang) . '&nbsp;&nbsp;' . fInput('submit', 'Submit', gTxt('save_button'), '') . eInput('prefs') . sInput('list_languages'), 'display:inline;'), ' style="text-align:center" colspan="3"');
    $client = new IXR_Client(RPC_SERVER);
    #$client->debug = true;
    $available_lang = array();
    $rpc_connect = false;
    $show_files = false;
    # Get items from RPC
    @set_time_limit(90);
    if (gps('force') != 'file' && $client->query('tups.listLanguages', $prefs['blog_uid'])) {
        $rpc_connect = true;
        $response = $client->getResponse();
        foreach ($response as $language) {
            $available_lang[$language['language']]['rpc_lastmod'] = gmmktime($language['lastmodified']->hour, $language['lastmodified']->minute, $language['lastmodified']->second, $language['lastmodified']->month, $language['lastmodified']->day, $language['lastmodified']->year);
        }
    } elseif (gps('force') != 'file') {
        $msg = gTxt('rpc_connect_error') . "<!--" . $client->getErrorCode() . ' ' . $client->getErrorMessage() . "-->";
    }
    # Get items from Filesystem
    $files = get_lang_files();
    if (gps('force') == 'file' || !$rpc_connect) {
        $show_files = true;
    }
    if ($show_files && is_array($files) && !empty($files)) {
        foreach ($files as $file) {
            if ($fp = @fopen(txpath . DS . 'lang' . DS . $file, 'r')) {
                $name = str_replace('.txt', '', $file);
                $firstline = fgets($fp, 4069);
                fclose($fp);
                if (strpos($firstline, '#@version') !== false) {
                    @(list($fversion, $ftime) = explode(';', trim(substr($firstline, strpos($firstline, ' ', 1)))));
                } else {
                    $fversion = $ftime = NULL;
                }
                $available_lang[$name]['file_note'] = isset($fversion) ? $fversion : 0;
                $available_lang[$name]['file_lastmod'] = isset($ftime) ? $ftime : 0;
            }
        }
    }
    # Get installed items from the database
    # I'm affraid we need a value here for the language itself, not for each one of the rows
    $rows = safe_rows('lang, UNIX_TIMESTAMP(MAX(lastmod)) as lastmod', 'txp_lang', "1 GROUP BY lang ORDER BY lastmod DESC");
    foreach ($rows as $language) {
        $available_lang[$language['lang']]['db_lastmod'] = $language['lastmod'];
    }
    $list = '';
    # Show the language table
    foreach ($available_lang as $langname => $langdat) {
        $file_updated = isset($langdat['db_lastmod']) && @$langdat['file_lastmod'] > $langdat['db_lastmod'];
        $rpc_updated = @$langdat['rpc_lastmod'] > @$langdat['db_lastmod'];
        $rpc_install = tda(strong(eLink('prefs', 'get_language', 'lang_code', $langname, isset($langdat['db_lastmod']) ? gTxt('update') : gTxt('install'), 'updating', isset($langdat['db_lastmod']))) . br . safe_strftime('%d %b %Y %X', @$langdat['rpc_lastmod']), isset($langdat['db_lastmod']) ? ' style="color:red;text-align:center;background-color:#FFFFCC;"' : ' style="color:#667;vertical-align:middle;text-align:center"');
        $list .= tr(tda(gTxt($langname) . tag(isset($langdat['db_lastmod']) ? br . '&nbsp;' . safe_strftime('%d %b %Y %X', $langdat['db_lastmod']) : '', 'span', ' style="color:#aaa;font-style:italic"'), isset($langdat['db_lastmod']) && $rpc_updated ? ' nowrap="nowrap" style="color:red;background-color:#FFFFCC;"' : ' nowrap="nowrap" style="vertical-align:middle"') . n . ($rpc_updated ? $rpc_install : tda(isset($langdat['rpc_lastmod']) ? gTxt('updated') : '-', ' style="vertical-align:middle;text-align:center"')) . n . ($show_files ? tda(tag(isset($langdat['file_lastmod']) ? eLink('prefs', 'get_language', 'lang_code', $langname, $file_updated ? gTxt('update') : gTxt('install'), 'force', 'file') . br . '&nbsp;' . safe_strftime($prefs['archive_dateformat'], $langdat['file_lastmod']) : ' &nbsp; ', 'span', $file_updated ? ' style="color:#667;"' : ' style="color:#aaa;font-style:italic"'), ' class="langfile" style="text-align:center;vertical-align:middle"') . n : '')) . n . n;
    }
    // Output Table + Content
    pagetop(gTxt('update_languages'), $message);
    if (isset($msg) && $msg) {
        echo tag($msg, 'p', ' style="text-align:center;color:red;width:50%;margin: 2em auto"');
    }
    echo startTable('list'), tr(tdcs(hed(gTxt('manage_languages'), 1), 3)), tr(tdcs(sLink('prefs', 'prefs_list', gTxt('site_prefs'), 'navlink') . sp . sLink('prefs', 'advanced_prefs', gTxt('advanced_preferences'), 'navlink') . sp . sLink('prefs', 'list_languages', gTxt('manage_languages'), 'navlink-active'), '3')), tr(tda('&nbsp;', ' colspan="3" style="font-size:0.25em"')), tr($lang_form), tr(tda('&nbsp;', ' colspan="3" style="font-size:0.25em"')), tr(tda(gTxt('language')) . tda(gTxt('from_server')) . ($show_files ? tda(gTxt('from_file')) : ''), ' style="font-weight:bold"');
    echo $list;
    if (!$show_files) {
        $linktext = gTxt('from_file') . ' (' . gTxt('experts_only') . ')';
        echo tr(tda('&nbsp;', ' colspan="3" style="font-size:0.25em"')) . tr(tda(strong(eLink('prefs', 'list_languages', 'force', 'file', $linktext)), ' colspan="3" style="text-align:center"'));
    } elseif (gps('force') == 'file') {
        echo tr(tda('&nbsp;', ' colspan="3" style="font-size:0.25em"')) . tr(tda(sLink('prefs', 'list_languages', strong(gTxt('from_server'))), ' colspan="3" style="text-align:center"'));
    }
    echo endTable();
    $install_langfile = gTxt('install_langfile', array('{url}' => strong('<a href="' . RPC_SERVER . '/lang/">' . RPC_SERVER . '/lang/</a>')));
    if ($install_langfile == 'install_langfile') {
        $install_langfile = 'To install new languages from file you can download them from <b><a href="' . RPC_SERVER . '/lang/">' . RPC_SERVER . '/lang/</a></b> and place them inside your ./textpattern/lang/ directory.';
    }
    echo tag($install_langfile, 'p', ' style="text-align:center;width:50%;margin: 2em auto"');
}