function css_edit_raw() { global $event, $step; $default_name = safe_field('css', 'txp_section', "name = 'default'"); extract(gpsa(array('name', 'newname', 'copy', 'savenew'))); if ($step == 'css_delete' || empty($name) && $step != 'pour' && !$savenew) { $name = $default_name; } elseif (($copy || $savenew) && trim(preg_replace('/[<>&"\']/', '', $newname))) { $name = $newname; } if (empty($name)) { $buttons = '<div class="edit-title">' . gTxt('name_for_this_style') . ': ' . fInput('text', 'newname', '', '', '', '', INPUT_REGULAR) . hInput('savenew', 'savenew') . '</div>'; $thecss = gps('css'); } else { $buttons = '<div class="edit-title">' . gTxt('you_are_editing_css') . sp . strong(txpspecialchars($name)) . '</div>'; $thecss = fetch("css", 'txp_css', 'name', $name); } if (!empty($name)) { $copy = n . '<p class="copy-as"><label for="copy-css">' . gTxt('copy_css_as') . '</label>' . n . fInput('text', 'newname', '', 'input-medium', '', '', INPUT_MEDIUM, '', 'copy-css') . n . fInput('submit', 'copy', gTxt('copy')) . '</p>'; } else { $copy = ''; } $right = '<div id="content_switcher">' . hed(gTxt('all_stylesheets'), 2) . graf(sLink('css', 'pour', gTxt('create_new_css')), ' class="action-create"') . css_list($name, $default_name) . '</div>'; echo '<h1 class="txp-heading">' . gTxt('tab_style') . '</h1>' . '<div id="' . $event . '_container" class="txp-container">' . startTable('', '', 'txp-columntable') . tr(td(form('<div id="main_content">' . $buttons . '<textarea id="css" class="code" name="css" cols="' . INPUT_LARGE . '" rows="' . INPUT_REGULAR . '">' . txpspecialchars($thecss) . '</textarea>' . '<p>' . fInput('submit', '', gTxt('save'), 'publish') . eInput('css') . sInput('css_save') . hInput('name', $name) . '</p>' . $copy . '</div>', '', '', 'post', 'edit-form', '', 'style_form'), '', 'column') . tdtl($right, ' class="column"')) . endTable() . '</div>'; }
function footer() { global $txp_user; $out[] = href('Textpattern CMS', 'http://textpattern.com', ' title="' . gTxt('go_txp_com') . '" rel="external" target="_blank"') . n . span('·', array('role' => 'separator')) . n . txp_version; if ($txp_user) { $out[] = graf(gTxt('logged_in_as') . ' ' . span(txpspecialchars($txp_user)) . br . href(gTxt('logout'), 'index.php?logout=1', ' onclick="return verify(\'' . gTxt('are_you_sure') . '\')"'), ' id="moniker"'); } return join(n, $out); }
function footer() { global $txp_user; $out[] = '<a id="mothership" href="http://textpattern.com/" title="' . gTxt('go_txp_com') . '" rel="external"><img src="' . $this->url . 'carver.png" width="40" height="40" alt="Textpattern" /></a>' . n . graf('Textpattern CMS · ' . txp_version); if ($txp_user) { $out[] = graf(gTxt('logged_in_as') . ' ' . span(txpspecialchars($txp_user)) . br . '<a href="index.php?logout=1">' . gTxt('logout') . '</a>', ' id="moniker"'); } return join(n, $out); }
function reset_author_pass($name) { $email = safe_field('email', 'txp_users', "name = '" . doSlash($name) . "'"); $new_pass = generate_password(PASSWORD_LENGTH); $hash = doSlash(txp_hash_password($new_pass)); $rs = safe_update('txp_users', "pass = '******'", "name = '" . doSlash($name) . "'"); if ($rs) { if (send_new_password($new_pass, $email, $name)) { return gTxt('password_sent_to') . ' ' . $email; } else { return gTxt('could_not_mail') . ' ' . $email; } } else { return gTxt('could_not_update_author') . ' ' . txpspecialchars($name); } }
/** * The main Page editor panel. * * @param string|array $message The activity message */ function page_edit($message = '') { global $event, $step; pagetop(gTxt('edit_pages'), $message); extract(array_map('assert_string', gpsa(array('copy', 'save_error', 'savenew')))); $name = sanitizeForPage(assert_string(gps('name'))); $newname = sanitizeForPage(assert_string(gps('newname'))); if ($step == 'page_delete' || empty($name) && $step != 'page_new' && !$savenew) { $name = safe_field("page", 'txp_section', "name = 'default'"); } elseif ((($copy || $savenew) && $newname || $newname && $newname != $name) && !$save_error) { $name = $newname; } $titleblock = inputLabel('new_page', fInput('text', 'newname', $name, 'input-medium', '', '', INPUT_MEDIUM, '', 'new_page', false, true), 'page_name', array('', 'instructions_page_name'), array('class' => 'txp-form-field')); if ($name === '') { $titleblock .= hInput('savenew', 'savenew'); } else { $titleblock .= hInput('name', $name); } $titleblock .= eInput('page') . sInput('page_save'); $html = !$save_error ? fetch('user_html', 'txp_page', 'name', $name) : gps('html'); // Format of each entry is popTagLink -> array ( gTxt() string, class/ID). $tagbuild_items = array('page_article' => array('page_article_hed', 'article-tags'), 'page_article_nav' => array('page_article_nav_hed', 'article-nav-tags'), 'page_nav' => array('page_nav_hed', 'nav-tags'), 'page_xml' => array('page_xml_hed', 'xml-tags'), 'page_misc' => array('page_misc_hed', 'misc-tags'), 'page_file' => array('page_file_hed', 'file-tags')); $tagbuild_links = ''; foreach ($tagbuild_items as $tb => $item) { $tagbuild_links .= wrapRegion($item[1] . '_group', taglinks($tb), $item[1], $item[0], 'page_' . $item[1]); } // Pages code columm. echo n . tag(hed(gTxt('tab_pages'), 1, array('class' => 'txp-heading')) . form($titleblock . inputLabel('html', '<textarea class="code" id="html" name="html" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_LARGE . '" dir="ltr">' . txpspecialchars($html) . '</textarea>', 'page_code', array('', 'instructions_page_code'), array('class' => 'txp-form-field')), '', '', 'post', '', '', 'page_form'), 'div', array('class' => 'txp-layout-4col-cell-1-2-3', 'id' => 'main_content', 'role' => 'region')); // Pages create/switcher column. $buttonExtras = ''; if ($name) { $buttonExtras .= href('<span class="ui-icon ui-icon-copy"></span> ' . gTxt('duplicate'), '#', array('class' => 'txp-clone', 'data-form' => 'page_form')); } $buttons = graf(tag_void('input', array('class' => 'publish', 'type' => 'submit', 'method' => 'post', 'value' => gTxt('save'), 'form' => 'page_form')), ' class="txp-save"') . graf(sLink('page', 'page_new', '<span class="ui-icon ui-extra-icon-new-document"></span> ' . gTxt('create_new_page'), 'txp-new') . $buttonExtras, array('class' => 'txp-actions')); echo n . tag($buttons . page_list($name) . n, 'div', array('class' => 'txp-layout-4col-cell-4alt', 'id' => 'content_switcher', 'role' => 'region')); // Pages tag builder column. TODO: make this a modal? // echo n.tag( // hed(gTxt('tagbuilder'), 2). // $tagbuild_links // , 'div', array( // 'class' => '', // 'id' => 'tagbuild_links', // )); }
function page_edit_form($name) { global $step; if ($name) { $html = safe_field('user_html', 'txp_page', "name='" . doSlash($name) . "'"); } else { $html = gps('html'); } if (empty($name)) { $buttons = '<div class="edit-title">' . gTxt('name_for_this_page') . ': ' . fInput('text', 'newname', '', '', '', '', INPUT_REGULAR) . hInput('savenew', 'savenew') . '</div>'; } else { $buttons = '<div class="edit-title">' . gTxt('you_are_editing_page') . sp . strong(txpspecialchars($name)) . '</div>'; } $out[] = '<div id="main_content">' . $buttons . '<textarea id="html" class="code" name="html" cols="' . INPUT_LARGE . '" rows="' . INPUT_REGULAR . '">' . txpspecialchars($html) . '</textarea>' . n . '<p>' . fInput('submit', 'save', gTxt('save'), 'publish') . n . eInput('page') . n . sInput('page_save') . n . hInput('name', $name) . '</p>'; if (!empty($name)) { $out[] = n . '<p class="copy-as"><label for="copy-page">' . gTxt('copy_page_as') . '</label>' . n . fInput('text', 'newname', '', 'input-medium', '', '', INPUT_MEDIUM, '', 'copy-page') . n . fInput('submit', 'copy', gTxt('copy')) . '</p>'; } $out[] = '</div>'; return form(join('', $out), '', '', 'post', '', '', 'page_form'); }
/** * The main panel listing all articles. * * @param string|array $message The activity message * @param string $post Not used */ function list_list($message = '', $post = '') { global $statuses, $use_comments, $comments_disabled_after, $step, $txp_user, $article_list_pageby, $event; pagetop(gTxt('tab_list'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('article_sort_column', 'posted'); } else { if (!in_array($sort, array('id', 'title', 'expires', 'section', 'category1', 'category2', 'status', 'author', 'comments', 'lastmod'))) { $sort = 'posted'; } set_pref('article_sort_column', $sort, 'list', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('article_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('article_sort_dir', $dir, 'list', 2, '', 0, PREF_PRIVATE); } $sesutats = array_flip($statuses); switch ($sort) { case 'id': $sort_sql = "textpattern.ID {$dir}"; break; case 'title': $sort_sql = "textpattern.Title {$dir}, textpattern.Posted DESC"; break; case 'expires': $sort_sql = "textpattern.Expires {$dir}"; break; case 'section': $sort_sql = "section.title {$dir}, textpattern.Posted DESC"; break; case 'category1': $sort_sql = "category1.title {$dir}, textpattern.Posted DESC"; break; case 'category2': $sort_sql = "category2.title {$dir}, textpattern.Posted DESC"; break; case 'status': $sort_sql = "textpattern.Status {$dir}, textpattern.Posted DESC"; break; case 'author': $sort_sql = "user.RealName {$dir}, textpattern.Posted DESC"; break; case 'comments': $sort_sql = "textpattern.comments_count {$dir}, textpattern.Posted DESC"; break; case 'lastmod': $sort_sql = "textpattern.LastMod {$dir}, textpattern.Posted DESC"; break; default: $sort = 'posted'; $sort_sql = "textpattern.Posted {$dir}"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('id' => array('column' => 'textpattern.ID', 'label' => gTxt('ID'), 'type' => 'integer'), 'title_body_excerpt' => array('column' => array('textpattern.Title', 'textpattern.Body', 'textpattern.Excerpt'), 'label' => gTxt('title_body_excerpt')), 'section' => array('column' => array('textpattern.Section', 'section.title'), 'label' => gTxt('section')), 'keywords' => array('column' => 'textpattern.Keywords', 'label' => gTxt('keywords'), 'type' => 'find_in_set'), 'categories' => array('column' => array('textpattern.Category1', 'textpattern.Category2', 'category1.title', 'category2.title'), 'label' => gTxt('categories')), 'status' => array('column' => array('textpattern.Status'), 'label' => gTxt('status'), 'type' => 'boolean'), 'author' => array('column' => array('textpattern.AuthorID', 'user.RealName'), 'label' => gTxt('author')), 'article_image' => array('column' => array('textpattern.Image'), 'label' => gTxt('article_image'), 'type' => 'integer'), 'posted' => array('column' => array('textpattern.Posted'), 'label' => gTxt('posted')), 'lastmod' => array('column' => array('textpattern.LastMod'), 'label' => gTxt('article_modified')))); $search->setAliases('status', $statuses); list($criteria, $crit, $search_method) = $search->getFilter(array('id' => array('can_list' => true), 'article_image' => array('can_list' => true), 'title_body_excerpt' => array('always_like' => true))); $search_render_options = array('placeholder' => 'search_articles'); $sql_from = safe_pfx('textpattern') . " textpattern\n LEFT JOIN " . safe_pfx('txp_category') . " category1 ON category1.name = textpattern.Category1 AND category1.type = 'article'\n LEFT JOIN " . safe_pfx('txp_category') . " category2 ON category2.name = textpattern.Category2 AND category2.type = 'article'\n LEFT JOIN " . safe_pfx('txp_section') . " section ON section.name = textpattern.Section\n LEFT JOIN " . safe_pfx('txp_users') . " user ON user.name = textpattern.AuthorID"; if ($criteria === 1) { $total = safe_count('textpattern', $criteria); } else { $total = getThing("SELECT COUNT(*) FROM {$sql_from} WHERE {$criteria}"); } echo n . tag(hed(gTxt('tab_list'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $createBlock = array(); if (has_privs('article.edit')) { $createBlock[] = n . tag(sLink('article', '', gTxt('add_new_article'), 'txp-button'), 'div', array('class' => 'txp-control-panel')); } $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_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')); } else { echo $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_articles_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } $limit = max($article_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart . $createBlock; $rs = safe_query("SELECT\n textpattern.ID, textpattern.Title, textpattern.url_title, textpattern.Section,\n textpattern.Category1, textpattern.Category2,\n textpattern.Status, textpattern.Annotate, textpattern.AuthorID,\n UNIX_TIMESTAMP(textpattern.Posted) AS posted,\n UNIX_TIMESTAMP(textpattern.LastMod) AS lastmod,\n UNIX_TIMESTAMP(textpattern.Expires) AS expires,\n category1.title AS category1_title,\n category2.title AS category2_title,\n section.title AS section_title,\n user.RealName AS RealName,\n (SELECT COUNT(*) FROM " . safe_pfx('txp_discuss') . " WHERE parentid = textpattern.ID) AS total_comments\n FROM {$sql_from} WHERE {$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { $show_authors = !has_single_author('textpattern', 'AuthorID'); echo n . tag(toggle_box('articles_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'articles_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('ID', 'id', 'list', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('title', 'title', 'list', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('posted', 'posted', 'list', true, $switch_dir, $crit, $search_method, ('posted' == $sort ? "{$dir} " : '') . 'txp-list-col-created date') . column_head('article_modified', 'lastmod', 'list', true, $switch_dir, $crit, $search_method, ('lastmod' == $sort ? "{$dir} " : '') . 'txp-list-col-lastmod date articles_detail') . column_head('expires', 'expires', 'list', true, $switch_dir, $crit, $search_method, ('expires' == $sort ? "{$dir} " : '') . 'txp-list-col-expires date articles_detail') . column_head('section', 'section', 'list', true, $switch_dir, $crit, $search_method, ('section' == $sort ? "{$dir} " : '') . 'txp-list-col-section') . column_head('category1', 'category1', 'list', true, $switch_dir, $crit, $search_method, ('category1' == $sort ? "{$dir} " : '') . 'txp-list-col-category1 category articles_detail') . column_head('category2', 'category2', 'list', true, $switch_dir, $crit, $search_method, ('category2' == $sort ? "{$dir} " : '') . 'txp-list-col-category2 category articles_detail') . column_head('status', 'status', 'list', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status') . ($show_authors ? column_head('author', 'author', 'list', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '') . ($use_comments == 1 ? column_head('comments', 'comments', 'list', true, $switch_dir, $crit, $search_method, ('comments' == $sort ? "{$dir} " : '') . 'txp-list-col-comments articles_detail') : '')) . n . tag_end('thead'); include_once txpath . '/publish/taghandlers.php'; echo n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); if ($Title === '') { $Title = '<em>' . eLink('article', 'edit', 'ID', $ID, gTxt('untitled')) . '</em>'; } else { $Title = eLink('article', 'edit', 'ID', $ID, $Title); } // Valid section and categories? $validator->setConstraints(array(new SectionConstraint($Section))); $vs = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category1, array('type' => 'article')))); $vc[1] = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category2, array('type' => 'article')))); $vc[2] = $validator->validate() ? '' : ' error'; $Category1 = $Category1 ? span(txpspecialchars($category1_title), array('title' => $Category1)) : ''; $Category2 = $Category2 ? span(txpspecialchars($category2_title), array('title' => $Category2)) : ''; if ($Status != STATUS_LIVE and $Status != STATUS_STICKY) { $view_url = '?txpreview=' . intval($ID) . '.' . time(); } else { $view_url = permlinkurl($a); } if (isset($statuses[$Status])) { $Status = $statuses[$Status]; } $comments = '(' . $total_comments . ')'; if ($total_comments) { $comments = href($comments, array('event' => 'discuss', 'step' => 'list', 'search_method' => 'parent', 'crit' => $ID), array('title' => gTxt('manage'))); } $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 = tag($comment_status, 'span', array('class' => 'comments-status')) . ' ' . tag($comments, 'span', array('class' => 'comments-manage')); echo tr(td(($a['Status'] >= STATUS_LIVE and has_privs('article.edit.published') or $a['Status'] >= STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own.published') or $a['Status'] < STATUS_LIVE and has_privs('article.edit') or $a['Status'] < STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own')) ? fInput('checkbox', 'selected[]', $ID, 'checkbox') : '', '', 'txp-list-col-multi-edit') . hCell(eLink('article', 'edit', 'ID', $ID, $ID) . sp . span(span('[', array('aria-hidden' => 'true')) . href(gTxt('view'), $view_url) . span(']', array('aria-hidden' => 'true')), array('class' => 'txp-option-link articles_detail')), '', ' class="txp-list-col-id" scope="row"') . td($Title, '', 'txp-list-col-title') . td(gTime($posted), '', 'txp-list-col-created date' . ($posted < time() ? '' : ' unpublished')) . td(gTime($lastmod), '', 'txp-list-col-lastmod date articles_detail' . ($posted === $lastmod ? ' not-modified' : '')) . td($expires ? gTime($expires) : '', '', 'txp-list-col-expires date articles_detail') . td(span(txpspecialchars($section_title), array('title' => $Section)), '', 'txp-list-col-section' . $vs) . td($Category1, '', 'txp-list-col-category1 category articles_detail' . $vc[1]) . td($Category2, '', 'txp-list-col-category2 category articles_detail' . $vc[2]) . td(href($Status, $view_url, join_atts(array('title' => gTxt('view')))), '', 'txp-list-col-status') . ($show_authors ? td(span(txpspecialchars($RealName), array('title' => $AuthorID)), '', 'txp-list-col-author name') : '') . ($use_comments ? td($comments, '', 'txp-list-col-comments articles_detail') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . list_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . n . tag_start('div', array('class' => 'txp-navigation', 'id' => $event . '_navigation')) . pageby_form('list', $article_list_pageby) . nav_form('list', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * Render a link element to hook up txpAsyncHref() with request parameters * * @param string $item Link text * @param array $parms Request parameters; array keys are 'event', 'step', 'thing', 'property' * @param string $atts HTML attributes * @return string HTML * @since 4.5.0 * @see textpattern.js: txpAsyncHref */ function asyncHref($item, $parms, $atts = '') { extract(doSpecial(lAtts(array('event' => $GLOBALS['event'], 'step' => $GLOBALS['step'], 'thing' => '', 'property' => ''), $parms))); $class = "{$step} async"; $href = "?event={$event}&step={$step}&thing={$thing}&property={$property}"; if (AJAXALLY_CHALLENGED) { $href .= '&value=' . txpspecialchars($item) . '&_txp_token=' . form_token(); } return href($item, $href, $atts . " class=\"{$class}\""); }
function log_list($message = '') { global $event, $log_list_pageby, $expire_logs_after; pagetop(gTxt('tab_logs'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('log_sort_column', 'time'); } if ($dir === '') { $dir = get_pref('log_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; $expire_logs_after = assert_int($expire_logs_after); safe_delete('txp_log', "time < date_sub(now(), interval {$expire_logs_after} day)"); switch ($sort) { case 'ip': $sort_sql = 'ip ' . $dir; break; case 'host': $sort_sql = 'host ' . $dir; break; case 'page': $sort_sql = 'page ' . $dir; break; case 'refer': $sort_sql = 'refer ' . $dir; break; case 'method': $sort_sql = 'method ' . $dir; break; case 'status': $sort_sql = 'status ' . $dir; break; default: $sort = 'time'; $sort_sql = 'time ' . $dir; break; } set_pref('log_sort_column', $sort, 'log', 2, '', 0, PREF_PRIVATE); set_pref('log_sort_dir', $dir, 'log', 2, '', 0, PREF_PRIVATE); $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $criteria = 1; if ($search_method and $crit != '') { $verbatim = preg_match('/^"(.*)"$/', $crit, $m); $crit_escaped = doSlash($verbatim ? $m[1] : str_replace(array('\\', '%', '_', '\''), array('\\\\', '\\%', '\\_', '\\\''), $crit)); $critsql = $verbatim ? array('ip' => "ip = '{$crit_escaped}'", 'host' => "host = '{$crit_escaped}'", 'page' => "page = '{$crit_escaped}'", 'refer' => "refer = '{$crit_escaped}'", 'method' => "method = '{$crit_escaped}'", 'status' => "status = '{$crit_escaped}'") : array('ip' => "ip like '%{$crit_escaped}%'", 'host' => "host like '%{$crit_escaped}%'", 'page' => "page like '%{$crit_escaped}%'", 'refer' => "refer like '%{$crit_escaped}%'", 'method' => "method like '%{$crit_escaped}%'", 'status' => "status like '%{$crit_escaped}%'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'log_list', 0, $criteria); $total = safe_count('txp_log', "{$criteria}"); echo '<h1 class="txp-heading">' . gTxt('tab_logs') . '</h1>'; echo '<div id="' . $event . '_control" class="txp-control-panel">'; if ($total < 1) { if ($criteria != 1) { echo n . log_search_form($crit, $search_method) . n . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } else { echo graf(gTxt('no_refers_recorded'), ' class="indicator"') . '</div>'; } return; } $limit = max($log_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo n . log_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, unix_timestamp(time) as uTime', 'txp_log', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { echo n . '<div id="' . $event . '_container" class="txp-container">'; echo n . n . '<form action="index.php" id="log_form" class="multi_edit_form" method="post" name="longform">' . n . '<div class="txp-listtables">' . n . startTable('', '', 'txp-list') . n . '<thead>' . n . tr(n . hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' title="' . gTxt('toggle_all_selected') . '" class="multi-edit"') . n . column_head('time', 'time', 'log', true, $switch_dir, $crit, $search_method, ('time' == $sort ? "{$dir} " : '') . 'date time') . n . column_head('IP', 'ip', 'log', true, $switch_dir, $crit, $search_method, ('ip' == $sort ? "{$dir} " : '') . 'log_detail ip') . n . column_head('host', 'host', 'log', true, $switch_dir, $crit, $search_method, ('host' == $sort ? "{$dir} " : '') . 'host') . n . column_head('page', 'page', 'log', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'page') . n . column_head('referrer', 'refer', 'log', true, $switch_dir, $crit, $search_method, ('refer' == $sort ? "{$dir} " : '') . 'refer') . n . column_head('method', 'method', 'log', true, $switch_dir, $crit, $search_method, ('method' == $sort ? "{$dir} " : '') . 'log_detail method') . n . column_head('status', 'status', 'log', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'log_detail status')) . n . '</thead>'; echo '<tbody>'; while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'log'); if ($log_refer) { $log_refer = 'http://' . $log_refer; $log_refer = '<a href="' . txpspecialchars($log_refer) . '" target="_blank">' . txpspecialchars(soft_wrap($log_refer, 30)) . '</a>'; } if ($log_page) { $log_anchor = preg_replace('/\\/$/', '', $log_page); $log_anchor = soft_wrap(substr($log_anchor, 1), 30); $log_page = '<a href="' . txpspecialchars($log_page) . '" target="_blank">' . txpspecialchars($log_anchor) . '</a>'; if ($log_method == 'POST') { $log_page = '<strong>' . $log_page . '</strong>'; } } echo tr(n . td(fInput('checkbox', 'selected[]', $log_id), '', 'multi-edit') . td(gTime($log_uTime), '', 'date time') . td(txpspecialchars($log_ip), '', 'log_detail ip') . td(txpspecialchars(soft_wrap($log_host, 30)), '', 'host') . td($log_page, '', 'page') . td($log_refer, '', 'refer') . td(txpspecialchars($log_method), '', 'log_detail method') . td($log_status, '', 'log_detail status')); } echo '</tbody>', n, endTable(), n, '</div>', n, log_multiedit_form($page, $sort, $dir, $crit, $search_method), n, tInput(), n, '</form>', n, graf(toggle_box('log_detail'), ' class="detail-toggle"'), n, '<div id="' . $event . '_navigation" class="txp-navigation">', n, nav_form('log', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit), n, pageby_form('log', $log_list_pageby), n, '</div>', n, '</div>'; } }
/** * The main panel listing all sections. * * So-named to avoid clashing with the <txp:section_list /> tag. * * @param string|array $message The activity message */ function sec_section_list($message = '') { global $event, $section_list_pageby; pagetop(gTxt('tab_sections'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('section_sort_column', 'time'); } if ($dir === '') { $dir = get_pref('section_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; switch ($sort) { case 'title': $sort_sql = 'title ' . $dir; break; case 'page': $sort_sql = 'page ' . $dir; break; case 'css': $sort_sql = 'css ' . $dir; break; case 'in_rss': $sort_sql = 'in_rss ' . $dir; break; case 'on_frontpage': $sort_sql = 'on_frontpage ' . $dir; break; case 'searchable': $sort_sql = 'searchable ' . $dir; break; case 'article_count': $sort_sql = 'article_count ' . $dir; break; default: $sort_sql = 'name ' . $dir; break; } set_pref('section_sort_column', $sort, 'section', 2, '', 0, PREF_PRIVATE); set_pref('section_sort_dir', $dir, 'section', 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('name' => "name = '{$crit_escaped}'", 'title' => "title = '{$crit_escaped}'", 'page' => "page = '{$crit_escaped}'", 'css' => "css = '{$crit_escaped}'", 'description' => "description = '{$crit_escaped}'") : array('name' => "name like '%{$crit_escaped}%'", 'title' => "title like '%{$crit_escaped}%'", 'page' => "page like '%{$crit_escaped}%'", 'css' => "css like '%{$crit_escaped}%'", 'description' => "description like '%{$crit_escaped}%'"); if ($verbatim) { $critsql['in_rss'] = "('{$crit_escaped}' in ('" . doSlash(gTxt('yes')) . "', 1) and in_rss = 1) or\n ('{$crit_escaped}' in ('" . doSlash(gTxt('no')) . "', '0') and in_rss = 0)"; $critsql['on_frontpage'] = "('{$crit_escaped}' in ('" . doSlash(gTxt('yes')) . "', 1) and on_frontpage = 1) or\n ('{$crit_escaped}' in ('" . doSlash(gTxt('no')) . "', '0') and on_frontpage = 0)"; $critsql['searchable'] = "('{$crit_escaped}' in ('" . doSlash(gTxt('yes')) . "', 1) and searchable = 1) or\n ('{$crit_escaped}' in ('" . doSlash(gTxt('no')) . "', '0') and searchable = 0)"; } else { $critsql['in_rss'] = "(('" . doSlash(gTxt('yes')) . "' like '%{$crit_escaped}%' or '{$crit_escaped}' = 1) and in_rss = 1) or\n (('" . doSlash(gTxt('no')) . "' like '%{$crit_escaped}%' or '{$crit_escaped}' = '0') and in_rss = 0)"; $critsql['on_frontpage'] = "(('" . doSlash(gTxt('yes')) . "' like '%{$crit_escaped}%' or '{$crit_escaped}' = 1) and on_frontpage = 1) or\n (('" . doSlash(gTxt('no')) . "' like '%{$crit_escaped}%' or '{$crit_escaped}' = '0') and on_frontpage = 0)"; $critsql['searchable'] = "(('" . doSlash(gTxt('yes')) . "' like '%{$crit_escaped}%' or '{$crit_escaped}' = 1) and searchable = 1) or\n (('" . doSlash(gTxt('no')) . "' like '%{$crit_escaped}%' or '{$crit_escaped}' = '0') and searchable = 0)"; } $search_sql = array(); foreach ((array) $search_method as $method) { if (isset($critsql[$method])) { $search_sql[] = $critsql[$method]; } } if ($search_sql) { $criteria = join(' or ', $search_sql); $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'section_list', 0, $criteria); $total = safe_count('txp_section', $criteria); echo hed(gTxt('tab_sections') . popHelp('section_category'), 1, array('class' => 'txp-heading')) . n . tag_start('div', array('id' => $event . '_control', 'class' => 'txp-control-panel')) . graf(sLink('section', 'section_edit', gTxt('create_section')), array('class' => 'txp-buttons')) . n . tag_start('form', array('id' => 'default_section_form', 'name' => 'default_section_form', 'method' => 'post', 'action' => 'index.php', 'class' => 'async')) . graf(tag(gTxt('default_write_section'), 'label', array('for' => 'default_section')) . popHelp('section_default') . section_select_list()) . eInput('section') . sInput('section_set_default') . n . tag_end('form'); if ($total < 1) { if ($criteria != 1) { echo section_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } return; } $limit = max($section_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo section_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, (select count(*) from ' . safe_pfx_j('textpattern') . ' where textpattern.Section = txp_section.name) as article_count', 'txp_section', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'section_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') . column_head('name', 'name', 'section', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('title', 'title', 'section', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('page', 'page', 'section', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'txp-list-col-page') . column_head('css', 'css', 'section', true, $switch_dir, $crit, $search_method, ('css' == $sort ? "{$dir} " : '') . 'txp-list-col-style') . column_head('on_front_page', 'on_frontpage', 'section', true, $switch_dir, $crit, $search_method, ('on_frontpage' == $sort ? "{$dir} " : '') . 'txp-list-col-frontpage section_detail') . column_head('syndicate', 'in_rss', 'section', true, $switch_dir, $crit, $search_method, ('in_rss' == $sort ? "{$dir} " : '') . 'txp-list-col-syndicate section_detail') . column_head('include_in_search', 'searchable', 'section', true, $switch_dir, $crit, $search_method, ('searchable' == $sort ? "{$dir} " : '') . 'txp-list-col-searchable section_detail') . column_head('articles', 'article_count', 'section', true, $switch_dir, $crit, $search_method, ('article_count' == $sort ? "{$dir} " : '') . 'txp-list-col-article_count section_detail')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'sec'); $edit_url = array('event' => 'section', 'step' => 'section_edit', 'name' => $sec_name, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); if ($sec_name == 'default') { $articles = $sec_searchable = $sec_in_rss = $sec_on_frontpage = '-'; } else { $sec_on_frontpage = asyncHref(yes_no($sec_on_frontpage), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'on_frontpage')); $sec_in_rss = asyncHref(yes_no($sec_in_rss), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'in_rss')); $sec_searchable = asyncHref(yes_no($sec_searchable), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'searchable')); if ($sec_article_count > 0) { $articles = href($sec_article_count, array('event' => 'list', 'search_method' => 'section', 'crit' => '"' . $sec_name . '"'), array('title' => gTxt('article_count', array('{num}' => $sec_article_count)))); } else { $articles = 0; } } $sec_page = href(txpspecialchars($sec_page), array('event' => 'page', 'name' => $sec_page), array('title' => gTxt('edit'))); $sec_css = href(txpspecialchars($sec_css), array('event' => 'css', 'name' => $sec_css), array('title' => gTxt('edit'))); echo tr(td(fInput('checkbox', 'selected[]', $sec_name), '', 'txp-list-col-multi-edit') . hCell(href(txpspecialchars($sec_name), $edit_url, array('title' => gTxt('edit'))) . sp . span(span('[', array('aria-hidden' => 'true')) . href(gTxt('view'), pagelinkurl(array('s' => $sec_name))) . span(']', array('aria-hidden' => 'true')), array('class' => 'section_detail')), '', array('scope' => 'row', 'class' => 'txp-list-col-name')) . td(txpspecialchars($sec_title), '', 'txp-list-col-title') . td($sec_page, '', 'txp-list-col-page') . td($sec_css, '', 'txp-list-col-style') . td($sec_on_frontpage, '', 'txp-list-col-frontpage section_detail') . td($sec_in_rss, '', 'txp-list-col-syndicate section_detail') . td($sec_searchable, '', 'txp-list-col-searchable section_detail') . td($articles, '', 'txp-list-col-article_count section_detail'), array('id' => 'txp_section_' . $sec_name)); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . section_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . graf(toggle_box('section_detail'), array('class' => 'detail-toggle')) . n . tag_start('div', array('id' => $event . '_navigation', 'class' => 'txp-navigation')) . pageby_form('section', $section_list_pageby) . nav_form('section', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div') . n . tag_end('div'); } }
/** * Processes multi-edit actions. * * Accessing requires 'admin.edit' privileges. */ function admin_multi_edit() { global $txp_user; require_privs('admin.edit'); $selected = ps('selected'); $method = ps('edit_method'); $changed = array(); $msg = ''; if (!$selected or !is_array($selected)) { return author_list(); } $clause = ''; if ($method === 'resetpassword') { $clause = " AND last_access IS NOT NULL"; } elseif ($method === 'resendactivation') { $clause = " AND last_access IS NULL"; } $names = safe_column("name", 'txp_users', "name IN (" . join(',', quote_list($selected)) . ") AND name != '" . doSlash($txp_user) . "'" . $clause); if (!$names) { return author_list(); } switch ($method) { case 'delete': $assign_assets = ps('assign_assets'); if (!$assign_assets) { $msg = array('must_reassign_assets', E_ERROR); } elseif (in_array($assign_assets, $names)) { $msg = array('cannot_assign_assets_to_deletee', E_ERROR); } elseif (remove_user($names, $assign_assets)) { $changed = $names; callback_event('authors_deleted', '', 0, $changed); $msg = 'author_deleted'; } break; case 'changeprivilege': if (change_user_group($names, ps('privs'))) { $changed = $names; $msg = 'author_updated'; } break; case 'resetpassword': foreach ($names as $name) { send_reset_confirmation_request($name); $changed[] = $name; } $msg = 'password_reset_confirmation_request_sent'; break; case 'resendactivation': foreach ($names as $name) { send_account_activation($name); $changed[] = $name; } $msg = 'resend_activation_request_sent'; break; } if ($changed) { return author_list(gTxt($msg, array('{name}' => txpspecialchars(join(', ', $changed))))); } author_list($msg); }
function image_list($message = '') { global $txpcfg, $extensions, $img_dir, $file_max_upload_size, $image_list_pageby, $txp_user, $event; pagetop(gTxt('tab_image'), $message); extract($txpcfg); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('image_sort_column', 'id'); } if ($dir === '') { $dir = get_pref('image_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; echo hed(gTxt('tab_image'), 1, array('class' => 'txp-heading')); echo n . '<div id="' . $event . '_control" class="txp-control-panel">'; if (!is_dir(IMPATH) or !is_writeable(IMPATH)) { echo graf(span(null, array('class' => 'ui-icon ui-icon-alert')) . ' ' . gTxt('img_dir_not_writeable', array('{imgdir}' => IMPATH)), array('class' => 'alert-block warning')); } elseif (has_privs('image.edit.own')) { echo upload_form(gTxt('upload_image'), 'upload_image', 'image_insert', 'image', '', $file_max_upload_size); } switch ($sort) { case 'name': $sort_sql = 'name ' . $dir; break; case 'thumbnail': $sort_sql = 'thumbnail ' . $dir . ', id asc'; break; case 'category': $sort_sql = 'category ' . $dir . ', id asc'; break; case 'date': $sort_sql = 'date ' . $dir . ', id asc'; break; case 'author': $sort_sql = 'author ' . $dir . ', id asc'; break; default: $sort = 'id'; $sort_sql = 'id ' . $dir; break; } set_pref('image_sort_column', $sort, 'image', 2, '', 0, PREF_PRIVATE); set_pref('image_sort_dir', $dir, 'image', 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' => "ID in ('" . join("','", do_list($crit_escaped)) . "')", 'name' => "name = '{$crit_escaped}'", 'category' => "category = '{$crit_escaped}'", 'author' => "author = '{$crit_escaped}'", 'alt' => "alt = '{$crit_escaped}'", 'caption' => "caption = '{$crit_escaped}'") : array('id' => "ID in ('" . join("','", do_list($crit_escaped)) . "')", 'name' => "name like '%{$crit_escaped}%'", 'category' => "category like '%{$crit_escaped}%'", 'author' => "author like '%{$crit_escaped}%'", 'alt' => "alt like '%{$crit_escaped}%'", 'caption' => "caption like '%{$crit_escaped}%'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'image_list', 0, $criteria); $total = safe_count('txp_image', "{$criteria}"); if ($total < 1) { if ($criteria != 1) { echo n . image_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } else { echo graf(gTxt('no_images_recorded'), ' class="indicator"') . '</div>'; } return; } $limit = max($image_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo image_search_form($crit, $search_method); $rs = safe_rows_start('*, unix_timestamp(date) as uDate', 'txp_image', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}\n "); echo pluggable_ui('image_ui', 'extend_controls', '', $rs); echo '</div>'; // End txp-control-panel. if ($rs) { $show_authors = !has_single_author('txp_image'); echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'images_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') . column_head('ID', 'id', 'image', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('name', 'name', 'image', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('date', 'date', 'image', true, $switch_dir, $crit, $search_method, ('date' == $sort ? "{$dir} " : '') . 'txp-list-col-created date images_detail') . column_head('thumbnail', 'thumbnail', 'image', true, $switch_dir, $crit, $search_method, ('thumbnail' == $sort ? "{$dir} " : '') . 'txp-list-col-thumbnail') . hCell(gTxt('tags'), '', ' scope="col" class="txp-list-col-tag-build images_detail"') . column_head('image_category', 'category', 'image', true, $switch_dir, $crit, $search_method, ('category' == $sort ? "{$dir} " : '') . 'txp-list-col-category category') . ($show_authors ? column_head('author', 'author', 'image', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '')) . n . tag_end('thead') . n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); $edit_url = array('event' => 'image', 'step' => 'image_edit', 'id' => $id, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); $name = empty($name) ? gTxt('unnamed') : txpspecialchars($name); if ($thumbnail) { if ($ext != '.swf') { $thumbnail = '<img class="content-image" src="' . imagesrcurl($id, $ext, true) . "?{$uDate}" . '" alt="" ' . "title='{$id}{$ext} ({$w} × {$h})'" . ($thumb_w ? " width='{$thumb_w}' height='{$thumb_h}'" : '') . ' />'; } else { $thumbnail = ''; } } else { $thumbnail = gTxt('no'); } if ($ext != '.swf') { $tag_url = '?event=tag' . a . 'tag_name=image' . a . 'id=' . $id . a . 'ext=' . $ext . a . 'w=' . $w . a . 'h=' . $h . a . 'alt=' . urlencode($alt) . a . 'caption=' . urlencode($caption); $tagbuilder = href('Textile', $tag_url . a . 'type=textile', ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('Textpattern', $tag_url . a . 'type=textpattern', ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('HTML', $tag_url . a . 'type=html', ' target="_blank" onclick="popWin(this.href); return false;"'); } else { $tagbuilder = sp; } $validator->setConstraints(array(new CategoryConstraint($category, array('type' => 'image')))); $vc = $validator->validate() ? '' : ' error'; $category = $category ? span($category, array('title' => fetch_category_title($category, 'image'))) : ''; $can_edit = has_privs('image.edit') || $author === $txp_user && has_privs('image.edit.own'); echo tr(td($can_edit ? fInput('checkbox', 'selected[]', $id) : ' ', '', 'txp-list-col-multi-edit') . hCell(($can_edit ? href($id, $edit_url, array('title' => gTxt('edit'))) : $id) . sp . span(span('[', array('aria-hidden' => 'true')) . href(gTxt('view'), imagesrcurl($id, $ext)) . span(']', array('aria-hidden' => 'true')), array('class' => 'images_detail')), '', ' scope="row" class="txp-list-col-id"') . td($can_edit ? href($name, $edit_url, ' title="' . gTxt('edit') . '"') : $name, '', 'txp-list-col-name') . td(gTime($uDate), '', 'txp-list-col-created date images_detail') . td(pluggable_ui('image_ui', 'thumbnail', $can_edit ? href($thumbnail, $edit_url) : $thumbnail, $a), '', 'txp-list-col-thumbnail') . td($tagbuilder, '', 'txp-list-col-tag-build images_detail') . td($category, '', 'txp-list-col-category category' . $vc) . ($show_authors ? td(span(txpspecialchars($author), array('title' => get_author_name($author))), '', 'txp-list-col-author name') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . image_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . graf(toggle_box('images_detail'), array('class' => 'detail-toggle')) . n . tag_start('div', array('id' => $event . '_navigation', 'class' => 'txp-navigation')) . pageby_form('image', $image_list_pageby) . nav_form('image', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div') . n . tag_end('div'); } }
function link_edit($message = '') { global $vars, $event, $step, $txp_user; pagetop(gTxt('tab_link'), $message); echo '<div id="' . $event . '_container" class="txp-container">'; extract(array_map('assert_string', gpsa($vars))); $is_edit = $id && $step == 'link_edit'; $rs = array(); if ($is_edit) { $id = assert_int($id); $rs = safe_row('*', 'txp_link', "id = {$id}"); if ($rs) { extract($rs); if (!has_privs('link.edit') && !($author == $txp_user && has_privs('link.edit.own'))) { link_list(gTxt('restricted_area')); return; } } } if (has_privs('link.edit') || has_privs('link.edit.own')) { $caption = gTxt($is_edit ? 'edit_link' : 'add_new_link'); echo form('<div class="txp-edit">' . n . hed($caption, 2) . n . inputLabel('linkname', fInput('text', 'linkname', $linkname, '', '', '', INPUT_REGULAR, '', 'linkname'), 'title') . n . inputLabel('linksort', fInput('text', 'linksort', $linksort, '', '', '', INPUT_REGULAR, '', 'linksort'), 'sort_value', 'link_sort') . n . inputLabel('url', fInput('text', 'url', $url, '', '', '', INPUT_REGULAR, '', 'url'), 'url', 'link_url', 'edit-link-url') . n . inputLabel('link_category', linkcategory_popup($category) . ' [' . eLink('category', 'list', '', '', gTxt('edit')) . ']', 'link_category', 'link_category') . n . inputLabel('link_description', '<textarea id="link_description" name="description" cols="' . INPUT_LARGE . '" rows="' . INPUT_SMALL . '">' . txpspecialchars($description) . '</textarea>', 'description', 'link_description', '', '') . n . pluggable_ui('link_ui', 'extend_detail_form', '', $rs) . n . graf(fInput('submit', '', gTxt('save'), 'publish')) . eInput('link') . sInput('link_save') . hInput('id', $id) . hInput('search_method', gps('search_method')) . hInput('crit', gps('crit')) . '</div>', '', '', 'post', 'edit-form', '', 'link_details'); } echo '</div>'; }
/** * Outputs a diagnostics report. * * This is the main panel. */ function doDiagnostics() { global $prefs, $files, $txpcfg, $event, $step, $theme, $DB; extract(get_prefs()); $urlparts = parse_url(hu); $mydomain = $urlparts['host']; $is_apache = stristr(serverSet('SERVER_SOFTWARE'), 'Apache') || is_callable('apache_get_version'); $real_doc_root = isset($_SERVER['DOCUMENT_ROOT']) ? realpath($_SERVER['DOCUMENT_ROOT']) : ''; // ini_get() returns string values passed via php_value as a string, not boolean. $is_register_globals = (strcasecmp(ini_get('register_globals'), 'on') === 0 or ini_get('register_globals') === '1'); // Check for Textpattern updates, at most once every 24 hours. $now = time(); $updateInfo = unserialize(get_pref('last_update_check', '')); if (!$updateInfo || $now > $updateInfo['when'] + 60 * 60 * 24) { $updates = checkUpdates(); $updateInfo['msg'] = $updates ? gTxt($updates['msg'], array('{version}' => $updates['version'])) : ''; $updateInfo['when'] = $now; set_pref('last_update_check', serialize($updateInfo), 'publish', PREF_HIDDEN, 'text_input'); } $fail = array(); if (!empty($updateInfo['msg'])) { $fail['textpattern_version_update'] = diag_msg_wrap($updateInfo['msg'], 'information'); } if (!is_callable('version_compare') || version_compare(PHP_VERSION, REQUIRED_PHP_VERSION, '<')) { $fail['php_version_required'] = diag_msg_wrap(gTxt('php_version_required', array('{version}' => REQUIRED_PHP_VERSION))); } if (!isset($path_to_site)) { $fail['path_to_site_missing'] = diag_msg_wrap(gTxt('path_to_site_missing'), 'warning'); } if (@gethostbyname($mydomain) === $mydomain) { $fail['dns_lookup_fails'] = diag_msg_wrap(gTxt('dns_lookup_fails') . cs . $mydomain, 'warning'); } if (!@is_dir($path_to_site)) { $fail['path_to_site_inacc'] = diag_msg_wrap(gTxt('path_to_site_inacc') . cs . $path_to_site); } if (rtrim($siteurl, '/') != $siteurl) { $fail['site_trailing_slash'] = diag_msg_wrap(gTxt('site_trailing_slash') . cs . $path_to_site, 'warning'); } if (!@is_file($path_to_site . "/index.php") || !@is_readable($path_to_site . "/index.php")) { $fail['index_inaccessible'] = diag_msg_wrap("{$path_to_site}/index.php " . gTxt('is_inaccessible')); } $not_readable = array(); if (!@is_writable($path_to_site . '/' . $img_dir)) { $not_readable[] = diag_msg_wrap(str_replace('{dirtype}', gTxt('img_dir'), gTxt('dir_not_writable')) . ": {$path_to_site}/{$img_dir}", 'warning'); } if (!@is_writable($file_base_path)) { $not_readable[] = diag_msg_wrap(str_replace('{dirtype}', gTxt('file_base_path'), gTxt('dir_not_writable')) . ": {$file_base_path}", 'warning'); } if (!@is_writable($tempdir)) { $not_readable[] = diag_msg_wrap(str_replace('{dirtype}', gTxt('tempdir'), gTxt('dir_not_writable')) . ": {$tempdir}", 'warning'); } if ($not_readable) { $fail['dir_not_writable'] = join(n, $not_readable); } if ($permlink_mode != 'messy' && !$is_apache) { $fail['cleanurl_only_apache'] = diag_msg_wrap(gTxt('cleanurl_only_apache'), 'information'); } if ($permlink_mode != 'messy' and !@is_readable($path_to_site . '/.htaccess')) { $fail['htaccess_missing'] = diag_msg_wrap(gTxt('htaccess_missing')); } if ($permlink_mode != 'messy' and is_callable('apache_get_modules') and !apache_module('mod_rewrite')) { $fail['mod_rewrite_missing'] = diag_msg_wrap(gTxt('mod_rewrite_missing')); } if (!ini_get('file_uploads')) { $fail['file_uploads_disabled'] = diag_msg_wrap(gTxt('file_uploads_disabled'), 'information'); } if (@is_dir(txpath . DS . 'setup')) { $fail['setup_still_exists'] = diag_msg_wrap(txpath . DS . "setup" . DS . ' ' . gTxt('still_exists'), 'warning'); } if (empty($tempdir)) { $fail['no_temp_dir'] = diag_msg_wrap(gTxt('no_temp_dir'), 'warning'); } if (is_disabled('mail')) { $fail['warn_mail_unavailable'] = diag_msg_wrap(gTxt('warn_mail_unavailable'), 'warning'); } if ($is_register_globals) { $fail['warn_register_globals_or_update'] = diag_msg_wrap(gTxt('warn_register_globals_or_update'), 'warning'); } if ($permlink_mode != 'messy') { $rs = safe_column("name", "txp_section", "1"); foreach ($rs as $name) { if ($name and @file_exists($path_to_site . '/' . $name)) { $fail['old_placeholder_exists'] = diag_msg_wrap(gTxt('old_placeholder') . ": {$path_to_site}/{$name}"); } } } $cs = check_file_integrity(INTEGRITY_REALPATH); if (!$cs) { $cs = array(); } // Files that don't match their checksums. if ($modified_files = array_keys($cs, INTEGRITY_MODIFIED)) { $fail['modified_files'] = diag_msg_wrap(gTxt('modified_files') . cs . n . t . join(', ' . n . t, $modified_files), 'warning'); } // Running development code in live mode is not recommended. if (preg_match('/-dev$/', txp_version) and $production_status == 'live') { $fail['dev_version_live'] = diag_msg_wrap(gTxt('dev_version_live'), 'warning'); } // Missing files. if ($missing = array_merge(array_keys($cs, INTEGRITY_MISSING), array_keys($cs, INTEGRITY_NOT_FILE), array_keys($cs, INTEGRITY_NOT_READABLE))) { $fail['missing_files'] = diag_msg_wrap(gTxt('missing_files') . cs . n . t . join(', ' . n . t, $missing)); } // Anything might break if arbitrary functions are disabled. if (ini_get('disable_functions')) { $disabled_funcs = array_map('trim', explode(',', ini_get('disable_functions'))); // Commonly disabled functions that we don't need. $disabled_funcs = array_diff($disabled_funcs, array('imagefilltoborder', 'escapeshellarg', 'escapeshellcmd', 'exec', 'passthru', 'proc_close', 'proc_get_status', 'proc_nice', 'proc_open', 'proc_terminate', 'shell_exec', 'system', 'popen', 'dl', 'chown')); if ($disabled_funcs) { $fail['some_php_functions_disabled'] = diag_msg_wrap(gTxt('some_php_functions_disabled') . cs . join(', ', $disabled_funcs), 'warning'); } } // Not sure about this one. // if (strncmp(php_sapi_name(), 'cgi', 3) == 0 and ini_get('cgi.rfc2616_headers')) // $fail['cgi_header_config'] = gTxt('cgi_header_config'); $guess_site_url = $_SERVER['HTTP_HOST'] . preg_replace('#[/\\\\]$#', '', dirname(dirname($_SERVER['SCRIPT_NAME']))); if ($siteurl and strip_prefix($siteurl, 'www.') != strip_prefix($guess_site_url, 'www.')) { $fail['site_url_mismatch'] = diag_msg_wrap(gTxt('site_url_mismatch') . cs . $guess_site_url, 'warning'); } // Test clean URL server vars. if (hu) { if (ini_get('allow_url_fopen') and $permlink_mode != 'messy') { $s = md5(uniqid(rand(), true)); ini_set('default_socket_timeout', 10); $pretext_data = @file(hu . $s . '/?txpcleantest=1'); if ($pretext_data) { $pretext_req = trim(@$pretext_data[0]); if ($pretext_req != md5('/' . $s . '/?txpcleantest=1')) { $fail['clean_url_data_failed'] = diag_msg_wrap(gTxt('clean_url_data_failed') . cs . txpspecialchars($pretext_req), 'warning'); } } else { $fail['clean_url_test_failed'] = diag_msg_wrap(gTxt('clean_url_test_failed'), 'warning'); } } } if ($tables = list_txp_tables()) { $table_errors = check_tables($tables); if ($table_errors) { $fail['mysql_table_errors'] = diag_msg_wrap(gTxt('mysql_table_errors') . cs . n . t . join(', ' . n . t, $table_errors)); } } $active_plugins = array(); if ($rows = safe_rows('name, version, code_md5, md5(code) as md5', 'txp_plugin', 'status > 0')) { foreach ($rows as $row) { $n = $row['name'] . '-' . $row['version']; if (strtolower($row['md5']) != strtolower($row['code_md5'])) { $n .= 'm'; } $active_plugins[] = $n; } } $theme_manifest = $theme->manifest(); // Check GD info. if (function_exists('gd_info')) { $gd_info = gd_info(); $gd_support = array(); if ($gd_info['GIF Create Support']) { $gd_support[] = 'GIF'; } // Aside: In PHP 5.3, they chose to add a previously unemployed capital "E" to the array key. if (!empty($gd_info['JPEG Support']) || !empty($gd_info['JPG Support'])) { $gd_support[] = 'JPG'; } if ($gd_info['PNG Support']) { $gd_support[] = 'PNG'; } if ($gd_support) { $gd_support = join(', ', $gd_support); } else { $gd_support = gTxt('none'); } $gd = gTxt('gd_info', array('{version}' => $gd_info['GD Version'], '{supported}' => $gd_support)); } else { $gd = gTxt('gd_unavailable'); } if (realpath($prefs['tempdir']) === realpath($prefs['plugin_cache_dir'])) { $fail['tmp_plugin_paths_match'] = diag_msg_wrap(gTxt('tmp_plugin_paths_match')); } // Database server time. extract(doSpecial(getRow('select @@global.time_zone as db_global_timezone, @@session.time_zone as db_session_timezone, now() as db_server_time, unix_timestamp(now()) as db_server_timestamp'))); $db_server_timeoffset = $db_server_timestamp - $now; echo pagetop(gTxt('tab_diagnostics'), ''); echo hed(gTxt('tab_diagnostics'), 1, array('class' => 'txp-heading')); echo n . '<div id="' . $event . '_container" class="txp-container">' . n . '<div id="pre_flight_check">' . hed(gTxt('preflight_check'), 2); if ($fail) { foreach ($fail as $help => $message) { echo graf(nl2br($message) . popHelp($help)); } } else { echo graf(diag_msg_wrap(gTxt('all_checks_passed'), 'success')); } echo '</div>'; echo '<div id="diagnostics">', hed(gTxt('diagnostic_info'), 2); $fmt_date = '%Y-%m-%d %H:%M:%S'; $out = array('<p><textarea class="code" id="diagnostics-detail" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_LARGE . '" dir="ltr" readonly>', gTxt('txp_version') . cs . txp_version . ' (' . check_file_integrity(INTEGRITY_DIGEST) . ')' . n, gTxt('last_update') . cs . gmstrftime($fmt_date, $dbupdatetime) . '/' . gmstrftime($fmt_date, @filemtime(txpath . '/update/_update.php')) . n, gTxt('document_root') . cs . @$_SERVER['DOCUMENT_ROOT'] . ($real_doc_root != @$_SERVER['DOCUMENT_ROOT'] ? ' (' . $real_doc_root . ')' : '') . n, '$path_to_site' . cs . $path_to_site . n, gTxt('txp_path') . cs . txpath . n, gTxt('permlink_mode') . cs . $permlink_mode . n, ini_get('open_basedir') ? 'open_basedir: ' . ini_get('open_basedir') . n : '', ini_get('upload_tmp_dir') ? 'upload_tmp_dir: ' . ini_get('upload_tmp_dir') . n : '', gTxt('tempdir') . cs . $tempdir . n, gTxt('web_domain') . cs . $siteurl . n, gTxt('php_version') . cs . phpversion() . n, $is_register_globals ? gTxt('register_globals') . cs . $is_register_globals . n : '', gTxt('gd_library') . cs . $gd . n, gTxt('server') . ' TZ: ' . Txp::get('Textpattern_Date_Timezone')->getTimeZone() . n, gTxt('server_time') . cs . strftime('%Y-%m-%d %H:%M:%S') . n, strip_tags(gTxt('is_dst')) . cs . $is_dst . n, strip_tags(gTxt('auto_dst')) . cs . $auto_dst . n, strip_tags(gTxt('gmtoffset')) . cs . $timezone_key . sp . "({$gmtoffset})" . n, 'MySQL' . cs . mysql_get_server_info() . n, gTxt('db_server_time') . cs . $db_server_time . n, gTxt('db_server_timeoffset') . cs . $db_server_timeoffset . ' s' . n, gTxt('db_global_timezone') . cs . $db_global_timezone . n, gTxt('db_session_timezone') . cs . $db_session_timezone . n, gTxt('locale') . cs . $locale . n, isset($_SERVER['SERVER_SOFTWARE']) ? gTxt('server') . cs . $_SERVER['SERVER_SOFTWARE'] . n : '', is_callable('apache_get_version') ? gTxt('apache_version') . cs . @apache_get_version() . n : '', gTxt('php_sapi_mode') . cs . PHP_SAPI . n, gTxt('rfc2616_headers') . cs . ini_get('cgi.rfc2616_headers') . n, gTxt('os_version') . cs . php_uname('s') . ' ' . php_uname('r') . n, $active_plugins ? gTxt('active_plugins') . cs . join(', ', $active_plugins) . n : '', gTxt('theme_name') . cs . $theme_name . sp . $theme_manifest['version'] . n, $fail ? n . gTxt('preflight_check') . cs . n . ln . join("\n", doStripTags($fail)) . n . ln : '', is_readable($path_to_site . '/.htaccess') ? n . gTxt('htaccess_contents') . cs . n . ln . txpspecialchars(join('', file($path_to_site . '/.htaccess'))) . n . ln : ''); if ($step == 'high') { $out[] = n . 'Charset (default/config)' . cs . $DB->default_charset . '/' . $DB->charset . n; $result = safe_query("SHOW variables like 'character_se%'"); while ($row = mysql_fetch_row($result)) { $out[] = $row[0] . cs . $row[1] . n; if ($row[0] == 'character_set_connection') { $conn_char = $row[1]; } } $table_names = array(PFX . 'textpattern'); $result = safe_query("SHOW TABLES LIKE '" . PFX . "txp\\_%'"); while ($row = mysql_fetch_row($result)) { $table_names[] = $row[0]; } $table_msg = array(); foreach ($table_names as $table) { $ctr = safe_query("SHOW CREATE TABLE " . $table . ""); if (!$ctr) { unset($table_names[$table]); continue; } $ctcharset = preg_replace('#^CREATE TABLE.*SET=([^ ]+)[^)]*$#is', '\\1', mysql_result($ctr, 0, 'Create Table')); if (isset($conn_char) && !stristr($ctcharset, 'CREATE') && $conn_char != $ctcharset) { $table_msg[] = "{$table} is {$ctcharset}"; } $ctr = safe_query("CHECK TABLE " . $table); if (in_array(mysql_result($ctr, 0, 'Msg_type'), array('error', 'warning'))) { $table_msg[] = $table . cs . mysql_result($ctr, 0, 'Msg_Text'); } } if ($table_msg == array()) { $table_msg = count($table_names) < 17 ? array('-') : array('OK'); } $out[] = count($table_names) . ' Tables' . cs . implode(', ', $table_msg) . n; $cf = preg_grep('/^custom_\\d+/', getThings('describe `' . PFX . 'textpattern`')); $out[] = n . get_pref('max_custom_fields', 10) . sp . gTxt('custom') . cs . implode(', ', $cf) . sp . '(' . count($cf) . ')' . n; $extns = get_loaded_extensions(); $extv = array(); foreach ($extns as $e) { $extv[] = $e . (phpversion($e) ? '/' . phpversion($e) : ''); } $out[] = n . gTxt('php_extensions') . cs . join(', ', $extv) . n; if (is_callable('apache_get_modules')) { $out[] = n . gTxt('apache_modules') . cs . join(', ', apache_get_modules()) . n; } if (@is_array($pretext_data) and count($pretext_data) > 1) { $out[] = n . gTxt('pretext_data') . cs . txpspecialchars(join('', array_slice($pretext_data, 1, 20))) . n; } $out[] = n; if ($md5s = check_file_integrity(INTEGRITY_MD5)) { foreach ($md5s as $f => $checksum) { $out[] = $f . cs . n . t . (!$checksum ? gTxt('unknown') : $checksum) . n; } } $out[] = n . ln; } $out[] = callback_event('diag_results', $step) . n; $out[] = '</textarea></p>'; $dets = array('low' => gTxt('low'), 'high' => gTxt('high')); $out[] = form(graf(eInput('diag') . n . '<label>' . gTxt('detail') . '</label>' . selectInput('step', $dets, $step, 0, 1))); echo join('', $out), '</div>', '</div>'; }
function form_edit($message = '') { global $event, $step, $essential_forms; pagetop(gTxt('edit_forms'), $message); extract(gpsa(array('Form', 'name', 'type'))); $name = trim(preg_replace('/[<>&"\']/', '', $name)); if ($step == 'form_create') { $inputs = fInput('submit', 'savenew', gTxt('save_new'), 'publish') . eInput("form") . sInput('form_save'); } else { $name = (!$name or $step == 'form_delete') ? 'default' : $name; $rs = safe_row("*", "txp_form", "name='" . doSlash($name) . "'"); extract($rs); $inputs = fInput('submit', 'save', gTxt('save'), 'publish') . eInput("form") . sInput('form_save') . hInput('oldname', $name); } if (!in_array($name, $essential_forms)) { $changename = graf(gTxt('form_name') . br . fInput('text', 'name', $name, 'edit', '', '', INPUT_REGULAR)); } else { $changename = graf(gTxt('form_name') . br . tag($name, 'em') . hInput('name', $name)); } // Generate the tagbuilder links // Format of each entry is popTagLink -> array ( gTxt string, class/ID ) $tagbuild_items = array('article' => array('articles', 'article-tags'), 'link' => array('links', 'link-tags'), 'comment' => array('comments', 'comment-tags'), 'comment_details' => array('comment_details', 'comment-detail-tags'), 'comment_form' => array('comment_form', 'comment-form-tags'), 'search_result' => array('search_results_form', 'search-result-tags'), 'file_download' => array('file_download_tags', 'file-tags'), 'category' => array('category_tags', 'category-tags'), 'section' => array('section_tags', 'section-tags')); $tagbuild_links = ''; foreach ($tagbuild_items as $tb => $item) { $tagbuild_links .= '<div class="' . $item[1] . '">' . hed('<a href="#' . $item[1] . '">' . gTxt($item[0]) . '</a>', 3, ' class="lever' . (get_pref('pane_form_' . $item[1] . '_visible') ? ' expanded' : '') . '"') . '<div id="' . $item[1] . '" class="toggle on" style="display:' . (get_pref('pane_form_' . $item[1] . '_visible') ? 'block' : 'none') . '">' . popTagLinks($tb) . '</div></div>'; } $out = '<h1 class="txp-heading">' . gTxt('tab_forms') . sp . popHelp('forms_overview') . '</h1>' . '<div id="' . $event . '_container" class="txp-container">' . startTable('', '', 'txp-columntable') . tr(tdtl('<div id="tagbuild_links">' . hed(gTxt('tagbuilder'), 2) . $tagbuild_links . '</div>', ' class="column"') . tdtl('<form action="index.php" method="post" id="form_form">' . '<div id="main_content">' . '<div class="edit-title">' . gTxt('you_are_editing_form') . sp . strong($name ? $name : gTxt('untitled')) . '</div>' . '<textarea id="form" class="code" name="Form" cols="' . INPUT_LARGE . '" rows="' . INPUT_REGULAR . '">' . txpspecialchars($Form) . '</textarea>' . $changename . graf(gTxt('form_type') . br . formtypes($type)) . (empty($type) ? graf(gTxt('only_articles_can_be_previewed')) : '') . (empty($type) || $type == 'article' ? fInput('submit', 'form_preview', gTxt('preview')) : '') . graf($inputs) . '</div>' . n . tInput() . n . '</form>', ' class="column"') . tdtl('<div id="content_switcher">' . hed(gTxt('all_forms'), 2) . form_list($name) . '</div>', ' class="column"')) . endTable() . '</div>'; echo $out; }
/** * Renders the main Form editor panel. * * @param string|array $message The activity message */ function form_edit($message = '') { global $event, $step, $essential_forms; pagetop(gTxt('edit_forms'), $message); extract(array_map('assert_string', gpsa(array('copy', 'save_error', 'savenew')))); $name = sanitizeForPage(assert_string(gps('name'))); $type = assert_string(gps('type')); $newname = sanitizeForPage(assert_string(gps('newname'))); if ($step == 'form_delete' || empty($name) && $step != 'form_create' && !$savenew) { $name = 'default'; } elseif ((($copy || $savenew) && $newname || $newname && $newname !== $name) && !$save_error) { $name = $newname; } $Form = gps('Form'); if (!$save_error) { $rs = safe_row('*', 'txp_form', "name='" . doSlash($name) . "'"); extract($rs); } if (in_array($name, $essential_forms)) { $name_widgets = span(gTxt('form_name'), array('class' => 'txp-label-fixed')) . br . span($name, array('class' => 'txp-value-fixed')); $type_widgets = span(gTxt('form_type'), array('class' => 'txp-label-fixed')) . br . span($type, array('class' => 'txp-value-fixed')); } else { $name_widgets = tag(gTxt('form_name'), 'label', 'for="new_form"') . br . fInput('text', 'newname', $name, 'input-medium', '', '', INPUT_MEDIUM, '', 'new_form', false, true); $type_widgets = tag(gTxt('form_type'), 'label', 'for="type"') . br . formTypes($type, false); } $buttons = href(gTxt('duplicate'), '#', array('id' => 'txp_clone', 'class' => 'clone', 'title' => gTxt('form_clone'))); if (empty($type) || $type == 'article') { $buttons .= href(gTxt('preview'), '#', array('id' => 'form_preview', 'class' => 'form-preview')); } if ($name) { $name_widgets .= n . span($buttons, array('class' => 'txp-actions')); } else { $name_widgets .= hInput('savenew', 'savenew'); } // Generate the tagbuilder links. // Format of each entry is popTagLink -> array ( gTxt string, class/ID ). $tagbuild_items = array('article' => array('articles', 'article-tags'), 'link' => array('links', 'link-tags'), 'comment' => array('comments', 'comment-tags'), 'comment_details' => array('comment_details', 'comment-detail-tags'), 'comment_form' => array('comment_form', 'comment-form-tags'), 'search_result' => array('search_results_form', 'search-result-tags'), 'file_download' => array('file_download_tags', 'file-tags'), 'category' => array('category_tags', 'category-tags'), 'section' => array('section_tags', 'section-tags')); $tagbuild_links = ''; foreach ($tagbuild_items as $tb => $item) { $tagbuild_links .= wrapRegion($item[1] . '_group', popTagLinks($tb), $item[1], $item[0], $item[1]); } echo hed(gTxt('tab_forms') . popHelp('forms_overview'), 1, array('class' => 'txp-heading')); echo n . tag(n . tag(hed(gTxt('tagbuilder'), 2) . $tagbuild_links . n, 'div', array('id' => 'tagbuild_links', 'class' => 'txp-layout-cell txp-layout-1-4')) . n . tag(form(graf($name_widgets) . graf(tag(gTxt('form_code'), 'label', array('for' => 'form')) . br . '<textarea class="code" id="form" name="Form" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_LARGE . '" dir="ltr">' . txpspecialchars($Form) . '</textarea>') . graf($type_widgets) . (empty($type) ? graf(gTxt('only_articles_can_be_previewed')) : '') . graf(fInput('submit', 'save', gTxt('save'), 'publish') . eInput('form') . sInput('form_save') . hInput('name', $name)), '', '', 'post', 'edit-form', '', 'form_form') . n, 'div', array('id' => 'main_content', 'class' => 'txp-layout-cell txp-layout-2-4')) . n . tag(graf(sLink('form', 'form_create', gTxt('create_new_form')), ' class="action-create"') . form_list($name) . n, 'div', array('id' => 'content_switcher', 'class' => 'txp-layout-cell txp-layout-1-4')) . n, 'div', array('id' => $event . '_container', 'class' => 'txp-layout-grid')); }
/** * Renders a HTML comment form. * * @param int $id The Article ID * @param array $atts An array of attributes * @return string HTML */ function commentForm($id, $atts = null) { global $prefs; extract($prefs); $h5 = $doctype == 'html5'; extract(lAtts(array('isize' => '25', 'msgrows' => '5', 'msgcols' => '25', 'msgstyle' => '', 'form' => 'comment_form', 'previewlabel' => gTxt('preview'), 'submitlabel' => gTxt('submit'), 'rememberlabel' => gTxt('remember'), 'forgetlabel' => gTxt('forget')), $atts, 0)); $namewarn = false; $emailwarn = false; $commentwarn = false; $name = pcs('name'); $email = clean_url(pcs('email')); $web = clean_url(pcs('web')); $n_message = 'message'; extract(doDeEnt(psa(array('checkbox_type', 'remember', 'forget', 'parentid', 'preview', 'message', 'submit', 'backpage')))); if ($message == '') { // Second or later preview will have randomised message-field name. $in = getComment(); $message = doDeEnt($in['message']); } if ($preview) { $name = ps('name'); $email = clean_url(ps('email')); $web = clean_url(ps('web')); $nonce = getNextNonce(); $secret = getNextSecret(); safe_insert("txp_discuss_nonce", "issue_time=now(), nonce='" . doSlash($nonce) . "', secret='" . doSlash($secret) . "'"); $n_message = md5('message' . $secret); $namewarn = $comments_require_name && !trim($name); $emailwarn = $comments_require_email && !trim($email); $commentwarn = !trim($message); $evaluator =& get_comment_evaluator(); if ($namewarn) { $evaluator->add_estimate(RELOAD, 1, gTxt('comment_name_required')); } if ($emailwarn) { $evaluator->add_estimate(RELOAD, 1, gTxt('comment_email_required')); } if ($commentwarn) { $evaluator->add_estimate(RELOAD, 1, gTxt('comment_required')); } } else { $rememberCookie = cs('txp_remember'); if ($rememberCookie === '') { $checkbox_type = 'remember'; $remember = 1; } elseif ($rememberCookie == 1) { $checkbox_type = 'forget'; } else { $checkbox_type = 'remember'; } } // If the form fields are filled (anything other than blank), pages really // should not be saved by a public cache (rfc2616/14.9.1). if ($name || $email || $web) { header('Cache-Control: private'); } $parentid = !$parentid ? $id : $parentid; $url = $GLOBALS['pretext']['request_uri']; // Experimental clean URLs with only 404-error-document on Apache possibly // requires messy URLs for POST requests. if (defined('PARTLY_MESSY') and PARTLY_MESSY) { $url = hu . '?id=' . intval($parentid); } $out = '<form id="txpCommentInputForm" method="post" action="' . txpspecialchars($url) . '#cpreview">' . n . '<div class="comments-wrapper">' . n . n; $Form = fetch('Form', 'txp_form', 'name', $form); $required = $h5 ? ' required' : ''; $msgcols = ($msgcols and is_numeric($msgcols)) ? ' cols="' . intval($msgcols) . '"' : ''; $msgrows = ($msgrows and is_numeric($msgrows)) ? ' rows="' . intval($msgrows) . '"' : ''; $msgstyle = $msgstyle ? ' style="' . $msgstyle . '"' : ''; $textarea = '<textarea class="txpCommentInputMessage' . ($commentwarn ? ' comments_error"' : '"') . ' id="message" name="' . $n_message . '"' . $msgcols . $msgrows . $msgstyle . $required . '>' . txpspecialchars(substr(trim($message), 0, 65535)) . '</textarea>'; // By default, the submit button is visible but disabled. $comment_submit_button = fInput('submit', 'submit', $submitlabel, 'button disabled', '', '', '', '', 'txpCommentSubmit', true); // If all fields check out, the submit button is active/clickable. if ($preview) { $comment_submit_button = fInput('submit', 'submit', $submitlabel, 'button', '', '', '', '', 'txpCommentSubmit', false); } if ($checkbox_type == 'forget') { // Inhibit default remember. if ($forget == 1) { destroyCookies(); } $checkbox = checkbox('forget', 1, $forget, '', 'forget') . ' ' . tag(txpspecialchars($forgetlabel), 'label', ' for="forget"'); } else { // Inhibit default remember. if ($remember != 1) { destroyCookies(); } $checkbox = checkbox('remember', 1, $remember, '', 'remember') . ' ' . tag(txpspecialchars($rememberlabel), 'label', ' for="remember"'); } $checkbox .= ' ' . hInput('checkbox_type', $checkbox_type); $vals = array('comment_name_input' => fInput('text', 'name', $name, 'comment_name_input' . ($namewarn ? ' comments_error' : ''), '', '', $isize, '', 'name', false, $h5 && $comments_require_name), 'comment_email_input' => fInput($h5 ? 'email' : 'text', 'email', $email, 'comment_email_input' . ($emailwarn ? ' comments_error' : ''), '', '', $isize, '', 'email', false, $h5 && $comments_require_email), 'comment_web_input' => fInput($h5 ? 'text' : 'text', 'web', $web, 'comment_web_input', '', '', $isize, '', 'web', false, false), 'comment_message_input' => $textarea . '<!-- plugin-place-holder -->', 'comment_remember' => $checkbox, 'comment_preview' => fInput('submit', 'preview', $previewlabel, 'button', '', '', '', '', 'txpCommentPreview', false), 'comment_submit' => $comment_submit_button); foreach ($vals as $a => $b) { $Form = str_replace('<txp:' . $a . ' />', $b, $Form); } $form = parse($Form); $out .= $form . n . hInput('parentid', $parentid); $split = rand(1, 31); $out .= $preview ? n . hInput(substr($nonce, 0, $split), substr($nonce, $split)) : ''; $out .= !$preview ? n . hInput('backpage', $url) : n . hInput('backpage', $backpage); $out = str_replace('<!-- plugin-place-holder -->', callback_event('comment.form'), $out); $out .= n . n . '</div>' . n . '</form>'; return $out; }
function file_edit($message = '', $id = '') { global $file_base_path, $levels, $file_statuses, $txp_user, $event, $all_file_cats; extract(gpsa(array('name', 'title', 'category', 'permissions', 'description', 'sort', 'dir', 'page', 'crit', 'search_method', 'publish_now'))); if (!$id) { $id = gps('id'); } $id = assert_int($id); $rs = safe_row('*, unix_timestamp(created) as created, unix_timestamp(modified) as modified', 'txp_file', "id = {$id}"); if ($rs) { extract($rs); $filename = sanitizeForFile($filename); if (!has_privs('file.edit') && !($author === $txp_user && has_privs('file.edit.own'))) { require_privs(); } pagetop(gTxt('edit_file'), $message); if ($permissions == '') { $permissions = '-1'; } if (!has_privs('file.publish') && $status >= STATUS_LIVE) { $status = STATUS_PENDING; } $file_exists = file_exists(build_file_path($file_base_path, $filename)); $existing_files = get_filenames(); $replace = $file_exists ? wrapGroup('file_upload_group', file_upload_form('', '', 'file_replace', $id, 'file_replace'), 'replace_file', 'replace-file', 'file_replace') : wrapGroup('file_upload_group', file_upload_form('', '', 'file_replace', $id, 'file_reassign'), 'file_relink', 'upload-file', 'file_reassign'); $condition = span($file_exists ? gTxt('file_status_ok') : gTxt('file_status_missing'), array('class' => $file_exists ? 'success' : 'error')); $downloadlink = $file_exists ? make_download_link($id, txpspecialchars($filename), $filename) : txpspecialchars($filename); $created = graf(checkbox('publish_now', '1', $publish_now, '', 'publish_now') . n . '<label for="publish_now">' . gTxt('set_to_now') . '</label>', ' class="edit-file-publish-now"') . graf(gTxt('or_publish_at') . popHelp('timestamp'), ' class="edit-file-publish-at"') . graf(span(gTxt('date'), array('class' => 'txp-label-fixed')) . br . tsi('year', '%Y', $rs['created'], '', gTxt('yyyy')) . ' / ' . tsi('month', '%m', $rs['created'], '', gTxt('mm')) . ' / ' . tsi('day', '%d', $rs['created'], '', gTxt('dd')), ' class="edit-file-published"') . graf(span(gTxt('time'), array('class' => 'txp-label-fixed')) . br . tsi('hour', '%H', $rs['created'], '', gTxt('hh')) . ' : ' . tsi('minute', '%M', $rs['created'], '', gTxt('mm')) . ' : ' . tsi('second', '%S', $rs['created'], '', gTxt('ss')), ' class="edit-file-created"'); echo n . '<div id="' . $event . '_container" class="txp-container">'; echo n . '<section class="txp-edit">' . hed(gTxt('edit_file'), 2) . inputLabel('condition', $condition) . inputLabel('name', $downloadlink) . inputLabel('download_count', $downloads) . $replace . n . '<div class="file-detail ' . ($file_exists ? '' : 'not-') . 'exists">' . form(($file_exists ? inputLabel('file_status', selectInput('status', $file_statuses, $status, false, '', 'file_status'), 'file_status') . inputLabel('file_title', fInput('text', 'title', $title, '', '', '', INPUT_REGULAR, '', 'file_title'), 'title') . inputLabel('file_category', treeSelectInput('category', $all_file_cats, $category, 'file_category'), 'file_category') . inputLabel('file_description', '<textarea id="file_description" name="description" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_SMALL . '">' . $description . '</textarea>', 'description', '', '', '') . wrapRegion('file_created', $created, '', gTxt('timestamp'), '', 'file-created') . pluggable_ui('file_ui', 'extend_detail_form', '', $rs) . graf(fInput('submit', '', gTxt('Save'), 'publish')) . hInput('filename', $filename) : (empty($existing_files) ? '' : gTxt('existing_file') . selectInput('filename', $existing_files, '', 1)) . pluggable_ui('file_ui', 'extend_detail_form', '', $rs) . graf(fInput('submit', '', gTxt('Save'), 'publish')) . hInput('category', $category) . hInput('perms', $permissions == '-1' ? '' : $permissions) . hInput('title', $title) . hInput('description', $description) . hInput('status', $status)) . eInput('file') . sInput('file_save') . hInput('id', $id) . hInput('sort', $sort) . hInput('dir', $dir) . hInput('page', $page) . hInput('crit', $crit) . hInput('search_method', $search_method), '', '', 'post', 'edit-form', '', $file_exists ? 'file_details' : 'assign_file') . n . '</div>' . n . '</section>' . n . '</div>'; } }
/** * 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).*)=/", "&\\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>'; }
/** * Processes multi-edit actions. * * Accessing requires 'admin.edit' privileges. */ function admin_multi_edit() { global $txp_user; require_privs('admin.edit'); $selected = ps('selected'); $method = ps('edit_method'); $changed = array(); $msg = ''; if (!$selected or !is_array($selected)) { return author_list(); } $names = safe_column('name', 'txp_users', "name IN (" . join(',', quote_list($selected)) . ") AND name != '" . doSlash($txp_user) . "'"); if (!$names) { return author_list(); } switch ($method) { case 'delete': $assign_assets = ps('assign_assets'); if (!$assign_assets) { $msg = array('must_reassign_assets', E_ERROR); } elseif (in_array($assign_assets, $names)) { $msg = array('cannot_assign_assets_to_deletee', E_ERROR); } elseif (remove_user($names, $assign_assets)) { $changed = $names; callback_event('authors_deleted', '', 0, $changed); $msg = 'author_deleted'; } break; case 'changeprivilege': if (change_user_group($names, ps('privs'))) { $changed = $names; $msg = 'author_updated'; } break; case 'resetpassword': foreach ($names as $name) { $passwd = generate_password(PASSWORD_LENGTH); if (change_user_password($name, $passwd)) { $email = safe_field('email', 'txp_users', "name = '" . doSlash($name) . "'"); if (send_new_password($passwd, $email, $name)) { $changed[] = $name; $msg = 'author_updated'; } else { return author_list(array(gTxt('could_not_mail') . ' ' . txpspecialchars($name), E_ERROR)); } } } break; } if ($changed) { return author_list(gTxt($msg, array('{name}' => txpspecialchars(join(', ', $changed))))); } author_list($msg); }
/** * Render HTML SELECT element for choosing a timezone * @param string $name Element name * @param string $value Selected timezone * @param boolean $blank_first Add empty first option * @param boolean|string $onchange n/a * @param string $select_id HTML id attribute * @return string HTML markup */ function selectInput($name = '', $value = '', $blank_first = '', $onchange = '', $select_id = '') { if (!empty($this->_details)) { $thiscontinent = ''; $selected = false; ksort($this->_details); foreach ($this->_details as $timezone_id => $tz) { extract($tz); if ($value == $timezone_id) { $selected = true; } if ($continent !== $thiscontinent) { if ($thiscontinent !== '') { $out[] = n . t . '</optgroup>'; } $out[] = n . t . '<optgroup label="' . gTxt($continent) . '">'; $thiscontinent = $continent; } $where = gTxt(str_replace('_', ' ', $city)) . (!empty($subcity) ? '/' . gTxt(str_replace('_', ' ', $subcity)) : '') . t; $out[] = n . t . t . '<option value="' . txpspecialchars($timezone_id) . '"' . ($value == $timezone_id ? ' selected="selected"' : '') . '>' . $where . '</option>'; } $out[] = n . t . '</optgroup>'; return n . '<select' . ($select_id ? ' id="' . $select_id . '"' : '') . ' name="' . $name . '"' . ($onchange == 1 ? ' onchange="submit(this.form);"' : $onchange) . '>' . ($blank_first ? n . t . '<option value=""' . ($selected == false ? ' selected="selected"' : '') . '></option>' : '') . join('', $out) . n . '</select>'; } return ''; }
function setup_gTxt($var, $atts = array(), $escape = 'html') { global $en_gb_strings; // Try to translate the string in chosen native language $xlate = gTxt($var, $atts, $escape); if (!is_array($atts)) { $atts = array(); } if ($escape == 'html') { foreach ($atts as $key => $value) { $atts[$key] = txpspecialchars($value); } } $v = strtolower($var); // Find out if the translated string is the same as the $var input if ($atts) { $compare = $xlate == $v . ': ' . join(', ', $atts); } else { $compare = $xlate == $v; } if ($compare) { // No translation string available, so grab an english string we know exists as fallback $xlate = strtr($en_gb_strings[$v], $atts); } return $xlate; }
function admin_multi_edit() { global $txp_user; require_privs('admin.edit'); $selected = ps('selected'); $method = ps('edit_method'); $changed = array(); if (!$selected or !is_array($selected)) { return author_list(); } $names = safe_column('name', 'txp_users', "name IN ('" . join("','", doSlash($selected)) . "') AND name != '" . doSlash($txp_user) . "'"); if (!$names) { return author_list(); } switch ($method) { case 'delete': $assign_assets = ps('assign_assets'); if ($assign_assets === '') { $msg = array('must_reassign_assets', E_ERROR); } elseif (in_array($assign_assets, $names)) { $msg = array('cannot_assign_assets_to_deletee', E_ERROR); } elseif (safe_delete('txp_users', "name IN ('" . join("','", doSlash($names)) . "')")) { $changed = $names; $assign_assets = doSlash($assign_assets); $names = join("','", doSlash($names)); // delete private prefs safe_delete('txp_prefs', "user_name IN ('{$names}')"); // assign dangling assets to their new owner $reassign = array('textpattern' => 'AuthorID', 'txp_file' => 'author', 'txp_image' => 'author', 'txp_link' => 'author'); foreach ($reassign as $table => $col) { safe_update($table, "{$col}='{$assign_assets}'", "{$col} IN ('{$names}')"); } callback_event('authors_deleted', '', 0, $changed); $msg = 'author_deleted'; } break; case 'changeprivilege': global $levels; $privilege = ps('privs'); if (!isset($levels[$privilege])) { return author_list(); } if (safe_update('txp_users', 'privs = ' . intval($privilege), "name IN ('" . join("','", doSlash($names)) . "')")) { $changed = $names; $msg = 'author_updated'; } break; case 'resetpassword': $failed = array(); foreach ($names as $name) { $passwd = generate_password(PASSWORD_LENGTH); $hash = doSlash(txp_hash_password($passwd)); if (safe_update('txp_users', "pass = '******'", "name = '" . doSlash($name) . "'")) { $email = safe_field('email', 'txp_users', "name = '" . doSlash($name) . "'"); if (send_new_password($passwd, $email, $name)) { $changed[] = $name; $msg = 'author_updated'; } else { return author_list(array(gTxt('could_not_mail') . ' ' . txpspecialchars($name), E_ERROR)); } } } break; } if ($changed) { return author_list(gTxt($msg, array('{name}' => txpspecialchars(join(', ', $changed))))); } author_list($msg); }
/** * Renders article excerpt field. * * The rendered widget can be customised via the 'article_ui > excerpt' * pluggable UI callback event. * * @param array $rs Article data * @return string HTML */ function article_partial_excerpt($rs) { $out = graf('<label for="excerpt">' . gTxt('excerpt') . '</label>' . popHelp('excerpt') . br . n . '<textarea id="excerpt" name="Excerpt" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_MEDIUM . '">' . txpspecialchars($rs['Excerpt']) . '</textarea>', ' class="excerpt"'); return pluggable_ui('article_ui', 'excerpt', $out, $rs); }
function sec_section_list($message = '') { global $event, $section_list_pageby; pagetop(gTxt('tab_sections'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('section_sort_column', 'time'); } if ($dir === '') { $dir = get_pref('section_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; switch ($sort) { case 'title': $sort_sql = 'title ' . $dir; break; case 'page': $sort_sql = 'page ' . $dir; break; case 'css': $sort_sql = 'css ' . $dir; break; case 'in_rss': $sort_sql = 'in_rss ' . $dir; break; case 'on_frontpage': $sort_sql = 'on_frontpage ' . $dir; break; case 'searchable': $sort_sql = 'searchable ' . $dir; break; case 'article_count': $sort_sql = 'article_count ' . $dir; break; default: $sort_sql = 'name ' . $dir; break; } set_pref('section_sort_column', $sort, 'section', 2, '', 0, PREF_PRIVATE); set_pref('section_sort_dir', $dir, 'section', 2, '', 0, PREF_PRIVATE); $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $criteria = 1; if ($search_method and $crit != '') { $verbatim = preg_match('/^"(.*)"$/', $crit, $m); $crit_escaped = doSlash($verbatim ? $m[1] : str_replace(array('\\', '%', '_', '\''), array('\\\\', '\\%', '\\_', '\\\''), $crit)); $critsql = $verbatim ? array('name' => "name = '{$crit_escaped}'", 'title' => "title = '{$crit_escaped}'", 'page' => "page = '{$crit_escaped}'", 'css' => "css = '{$crit_escaped}'", 'in_rss' => "in_rss = '{$crit_escaped}'", 'on_frontpage' => "on_frontpage = '{$crit_escaped}'", 'searchable' => "searchable = '{$crit_escaped}'") : array('name' => "name like '%{$crit_escaped}%'", 'title' => "title like '%{$crit_escaped}%'", 'page' => "page like '%{$crit_escaped}%'", 'css' => "css like '%{$crit_escaped}%'", 'in_rss' => "in_rss = '{$crit_escaped}'", 'on_frontpage' => "on_frontpage = '{$crit_escaped}'", 'searchable' => "searchable = '{$crit_escaped}'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'section_list', 0, $criteria); $total = safe_count('txp_section', "{$criteria}"); echo '<h1 class="txp-heading">' . gTxt('tab_sections') . sp . popHelp('section_category') . '</h1>'; echo '<div id="' . $event . '_control" class="txp-control-panel">'; echo graf(sLink('section', 'section_edit', gTxt('create_section')), ' class="txp-buttons"'); echo n . '<form id="default_section_form" name="default_section_form" method="post" action="index.php" class="async">'; echo graf('<label>' . gTxt('default_write_section') . '</label>' . sp . popHelp('section_default') . n . section_select_list()) . eInput('section') . sInput('section_set_default'); echo '</form>'; if ($total < 1) { if ($criteria != 1) { echo n . section_search_form($crit, $search_method) . n . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } return; } $limit = max($section_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo n . section_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, (SELECT count(*) FROM ' . safe_pfx('textpattern') . ' articles WHERE articles.Section = txp_section.name) AS article_count', 'txp_section', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { echo n . '<div id="' . $event . '_container" class="txp-container">'; echo n . n . '<form action="index.php" id="section_form" class="multi_edit_form" method="post" name="longform">' . n . '<div class="txp-listtables">' . n . n . startTable('', '', 'txp-list') . n . '<thead>' . n . tr(n . hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' title="' . gTxt('toggle_all_selected') . '" class="multi-edit"') . n . column_head('name', 'name', 'section', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'name') . n . column_head('title', 'title', 'section', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'title') . n . column_head('page', 'page', 'section', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'page') . n . column_head('css', 'css', 'section', true, $switch_dir, $crit, $search_method, ('css' == $sort ? "{$dir} " : '') . 'style') . n . column_head('on_front_page', 'on_frontpage', 'section', true, $switch_dir, $crit, $search_method, ('on_frontpage' == $sort ? "{$dir} " : '') . 'section_detail frontpage') . n . column_head('syndicate', 'in_rss', 'section', true, $switch_dir, $crit, $search_method, ('in_rss' == $sort ? "{$dir} " : '') . 'section_detail syndicate') . n . column_head('include_in_search', 'searchable', 'section', true, $switch_dir, $crit, $search_method, ('searchable' == $sort ? "{$dir} " : '') . 'section_detail searchable') . n . column_head('articles', 'article_count', 'section', true, $switch_dir, $crit, $search_method, ('article_count' == $sort ? "{$dir} " : '') . 'section_detail article_count')) . n . '</thead>'; echo '<tbody>'; while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'sec'); $is_default_section = $sec_name == 'default'; $edit_url = '?event=section' . a . 'step=section_edit' . a . 'name=' . $sec_name . a . 'sort=' . $sort . a . 'dir=' . $dir . a . 'page=' . $page . a . 'search_method=' . $search_method . a . 'crit=' . $crit; $page_url = '?event=page' . a . 'name=' . $sec_page; $style_url = '?event=css' . a . 'name=' . $sec_css; $articles = $sec_article_count > 0 ? href($sec_article_count, '?event=list' . a . 'search_method=section' . a . 'crit="' . txpspecialchars($sec_name) . '"', ' title="' . gTxt('article_count', array('{num}' => $sec_article_count)) . '"') : ($is_default_section ? '' : '0'); // $can_delete = ($sec_name != 'default' && $sec_article_count == 0); $parms = array('step' => 'section_toggle_option', 'thing' => $sec_name); echo tr(td(fInput('checkbox', 'selected[]', $sec_name), '', 'multi-edit') . td('<a href="' . $edit_url . '" title="' . gTxt('edit') . '">' . $sec_name . '</a>' . n . '<span class="section_detail">[<a href="' . hu . $sec_name . '">' . gTxt('view') . '</a>]</span>', '', 'name') . td(txpspecialchars($sec_title), '', 'title') . td('<a href="' . $page_url . '" title="' . gTxt('edit') . '">' . $sec_page . '</a>', '', 'page') . td('<a href="' . $style_url . '" title="' . gTxt('edit') . '">' . $sec_css . '</a>', '', 'style') . td($is_default_section ? '-' : asyncHref($sec_on_frontpage ? gTxt('yes') : gTxt('no'), $parms + array('property' => 'on_frontpage')), '', 'section_detail frontpage') . td($is_default_section ? '-' : asyncHref($sec_in_rss ? gTxt('yes') : gTxt('no'), $parms + array('property' => 'in_rss')), '', 'section_detail syndicate') . td($is_default_section ? '-' : asyncHref($sec_searchable ? gTxt('yes') : gTxt('no'), $parms + array('property' => 'searchable')), '', 'section_detail searchable') . td($is_default_section ? '' : $articles, '', 'section_detail article_count'), ' id="txp_section_' . $sec_name . '"'); } echo '</tbody>', n, endTable(), n, '</div>', n, section_multiedit_form($page, $sort, $dir, $crit, $search_method), n, tInput(), n, '</form>', n, graf(toggle_box('section_detail'), ' class="detail-toggle"'), n, '<div id="' . $event . '_navigation" class="txp-navigation">', n, nav_form('section', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit), n, pageby_form('section', $section_list_pageby), n, '</div>', n, '</div>'; echo script_js(<<<EOS \t\t\t\$('#default_section').change(function() { \t\t\t\t\$('#default_section_form').submit(); \t\t\t}); EOS ); } }
/** * Renders article excerpt field. * * The rendered widget can be customised via the 'article_ui > excerpt' * pluggable UI callback event. * * @param array $rs Article data * @return string HTML */ function article_partial_excerpt($rs) { $out = inputLabel('excerpt', '<textarea id="excerpt" name="Excerpt" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_SMALL . '">' . txpspecialchars($rs['Excerpt']) . '</textarea>', 'excerpt', array('excerpt', 'instructions_excerpt'), array('class' => 'txp-form-field txp-form-field-textarea excerpt')); return pluggable_ui('article_ui', 'excerpt', $out, $rs); }
/** * The main panel listing all log hits. * * @param string|array $message The activity message */ function log_list($message = '') { global $event, $log_list_pageby, $expire_logs_after; pagetop(gTxt('tab_logs'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('log_sort_column', 'time'); } else { if (!in_array($sort, array('ip', 'host', 'page', 'refer', 'method', 'status'))) { $sort = 'time'; } set_pref('log_sort_column', $sort, 'log', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('log_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('log_sort_dir', $dir, 'log', 2, '', 0, PREF_PRIVATE); } $expire_logs_after = assert_int($expire_logs_after); safe_delete('txp_log', "time < DATE_SUB(NOW(), INTERVAL {$expire_logs_after} DAY)"); switch ($sort) { case 'ip': $sort_sql = "ip {$dir}"; break; case 'host': $sort_sql = "host {$dir}"; break; case 'page': $sort_sql = "page {$dir}"; break; case 'refer': $sort_sql = "refer {$dir}"; break; case 'method': $sort_sql = "method {$dir}"; break; case 'status': $sort_sql = "status {$dir}"; break; default: $sort = 'time'; $sort_sql = "time {$dir}"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('ip' => array('column' => 'txp_log.ip', 'label' => gTxt('IP')), 'host' => array('column' => 'txp_log.host', 'label' => gTxt('host')), 'page' => array('column' => 'txp_log.page', 'label' => gTxt('page')), 'refer' => array('column' => 'txp_log.refer', 'label' => gTxt('referrer')), 'method' => array('column' => 'txp_log.method', 'label' => gTxt('method')), 'status' => array('column' => 'txp_log.status', 'label' => gTxt('status'), 'type' => 'integer'))); list($criteria, $crit, $search_method) = $search->getFilter(array('status' => array('can_list' => true))); $search_render_options = array('placeholder' => 'search_logs'); $total = safe_count('txp_log', "{$criteria}"); echo n . tag(hed(gTxt('tab_logs'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('log_list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')); if ($total < 1) { if ($criteria != 1) { echo $searchBlock . $contentBlockStart . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')); } else { echo $contentBlockStart . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_refers_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } $limit = max($log_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart; $rs = safe_rows_start("*, UNIX_TIMESTAMP(time) AS uTime", 'txp_log', "{$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { echo n . tag(toggle_box('log_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'log_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('time', 'time', 'log', true, $switch_dir, $crit, $search_method, ('time' == $sort ? "{$dir} " : '') . 'txp-list-col-time') . column_head('IP', 'ip', 'log', true, $switch_dir, $crit, $search_method, ('ip' == $sort ? "{$dir} " : '') . 'txp-list-col-ip') . column_head('host', 'host', 'log', true, $switch_dir, $crit, $search_method, ('host' == $sort ? "{$dir} " : '') . 'txp-list-col-host log_detail') . column_head('page', 'page', 'log', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'txp-list-col-page') . column_head('referrer', 'refer', 'log', true, $switch_dir, $crit, $search_method, ('refer' == $sort ? "{$dir} " : '') . 'txp-list-col-refer') . column_head('method', 'method', 'log', true, $switch_dir, $crit, $search_method, ('method' == $sort ? "{$dir} " : '') . 'txp-list-col-method log_detail') . column_head('status', 'status', 'log', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status log_detail')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'log'); if ($log_refer) { $log_refer = href(txpspecialchars(soft_wrap(preg_replace('#^http://#', '', $log_refer), 30)), txpspecialchars($log_refer), ' target="_blank"'); } if ($log_page) { $log_anchor = preg_replace('/\\/$/', '', $log_page); $log_anchor = soft_wrap(substr($log_anchor, 1), 30); $log_page = href(txpspecialchars($log_anchor), txpspecialchars($log_page), ' target="_blank"'); if ($log_method == 'POST') { $log_page = strong($log_page); } } echo tr(td(fInput('checkbox', 'selected[]', $log_id), '', 'txp-list-col-multi-edit') . hCell(gTime($log_uTime), '', ' class="txp-list-col-time" scope="row"') . td(href(txpspecialchars($log_ip), 'https://whois.domaintools.com/' . rawurlencode($log_ip), array('rel' => 'external', 'target' => '_blank')), '', 'txp-list-col-ip') . td(txpspecialchars($log_host), '', 'txp-list-col-host log_detail') . td($log_page, '', 'txp-list-col-page') . td($log_refer, '', 'txp-list-col-refer') . td(txpspecialchars($log_method), '', 'txp-list-col-method log_detail') . td($log_status, '', 'txp-list-col-status log_detail')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . log_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . n . tag_start('div', array('class' => 'txp-navigation', 'id' => $event . '_navigation')) . pageby_form('log', $log_list_pageby) . nav_form('log', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * Parse a tag for attributes and hand over to the tag handler function. * * @param string $tag The tag name * @param string $atts The attribute string * @param string|null $thing The tag's content in case of container tags * @return string Parsed tag result * @package TagParser */ function processTags($tag, $atts, $thing = null) { global $production_status, $txp_current_tag, $txp_current_form; static $registry = null; if ($production_status !== 'live') { $old_tag = $txp_current_tag; $txp_current_tag = '<txp:' . $tag . $atts . (isset($thing) ? '>' : '/>'); trace_add($txp_current_tag, 1, "Form='{$txp_current_form}', Tag='{$txp_current_tag}'"); } if ($registry === null) { $registry = Txp::get('\\Textpattern\\Tag\\Registry'); } if ($registry->isRegistered($tag)) { $out = $registry->process($tag, splat($atts), $thing); } elseif (maybe_tag($tag)) { $out = $tag(splat($atts), $thing); trigger_error(gTxt('unregistered_tag'), E_USER_NOTICE); } elseif (isset($GLOBALS['pretext'][$tag])) { $out = txpspecialchars($pretext[$tag]); trigger_error(gTxt('deprecated_tag'), E_USER_NOTICE); } else { $out = ''; trigger_error(gTxt('unknown_tag'), E_USER_WARNING); } if ($production_status !== 'live') { trace_add('', -1); if (isset($thing)) { trace_add("</txp:{$tag}>"); } $txp_current_tag = $old_tag; } return $out; }
/** * Parse a tag for attributes and hand over to the tag handler function. * * @param string $tag The tag name without '<txp:' * @param string $atts The attribute string * @param string|null $thing The tag's content in case of container tags (optional) * @return string Parsed tag result */ function processTags($tag, $atts, $thing = NULL) { global $production_status, $txptrace, $txptracelevel, $txp_current_tag; if ($production_status !== 'live') { $old_tag = $txp_current_tag; $txp_current_tag = '<txp:' . $tag . $atts . (isset($thing) ? '>' : '/>'); trace_add($txp_current_tag); ++$txptracelevel; if ($production_status === 'debug') { maxMemUsage($txp_current_tag); } } if ($tag === 'link') { $tag = 'tpt_' . $tag; } if (maybe_tag($tag)) { $out = $tag(splat($atts), $thing); } elseif (isset($GLOBALS['pretext'][$tag])) { $out = txpspecialchars($pretext[$tag]); trigger_error(gTxt('deprecated_tag'), E_USER_NOTICE); } else { $out = ''; trigger_error(gTxt('unknown_tag'), E_USER_WARNING); } if ($production_status !== 'live') { --$txptracelevel; if (isset($thing)) { trace_add('</txp:' . $tag . '>'); } $txp_current_tag = $old_tag; } return $out; }
/** * The main panel listing all sections. * * So-named to avoid clashing with the <txp:section_list /> tag. * * @param string|array $message The activity message */ function sec_section_list($message = '') { global $event, $section_list_pageby; pagetop(gTxt('tab_sections'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('section_sort_column', 'name'); } else { if (!in_array($sort, array('title', 'page', 'css', 'in_rss', 'on_frontpage', 'searchable', 'article_count'))) { $sort = 'name'; } set_pref('section_sort_column', $sort, 'section', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('section_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('section_sort_dir', $dir, 'section', 2, '', 0, PREF_PRIVATE); } switch ($sort) { case 'title': $sort_sql = "title {$dir}"; break; case 'page': $sort_sql = "page {$dir}"; break; case 'css': $sort_sql = "css {$dir}"; break; case 'in_rss': $sort_sql = "in_rss {$dir}"; break; case 'on_frontpage': $sort_sql = "on_frontpage {$dir}"; break; case 'searchable': $sort_sql = "searchable {$dir}"; break; case 'article_count': $sort_sql = "article_count {$dir}"; break; default: $sort_sql = "name {$dir}"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('name' => array('column' => 'txp_section.name', 'label' => gTxt('name')), 'title' => array('column' => 'txp_section.title', 'label' => gTxt('title')), 'page' => array('column' => 'txp_section.page', 'label' => gTxt('page')), 'css' => array('column' => 'txp_section.css', 'label' => gTxt('css')), 'on_frontpage' => array('column' => 'txp_section.on_frontpage', 'label' => gTxt('on_front_page'), 'type' => 'boolean'), 'in_rss' => array('column' => 'txp_section.in_rss', 'label' => gTxt('syndicate'), 'type' => 'boolean'), 'searchable' => array('column' => 'txp_section.searchable', 'label' => gTxt('include_in_search'), 'type' => 'boolean'))); $alias_yes = '1, Yes'; $alias_no = '0, No'; $search->setAliases('on_frontpage', array($alias_no, $alias_yes)); $search->setAliases('in_rss', array($alias_no, $alias_yes)); $search->setAliases('searchable', array($alias_no, $alias_yes)); list($criteria, $crit, $search_method) = $search->getFilter(); $search_render_options = array('placeholder' => 'search_sections'); $total = safe_count('txp_section', $criteria); echo n . tag(hed(gTxt('tab_sections'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('sec_section', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $createBlock = array(); if (has_privs('section.edit')) { $createBlock[] = n . tag(sLink('section', 'section_edit', gTxt('create_section'), 'txp-button') . n . tag_start('form', array('class' => 'async', 'id' => 'default_section_form', 'name' => 'default_section_form', 'method' => 'post', 'action' => 'index.php')) . tag(gTxt('default_write_section'), 'label', array('for' => 'default_section')) . popHelp('section_default') . section_select_list() . eInput('section') . sInput('section_set_default') . n . tag_end('form'), 'div', array('class' => 'txp-control-panel')); } $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_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($section_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart . $createBlock; $rs = safe_rows_start("*, (SELECT COUNT(*) FROM " . safe_pfx_j('textpattern') . " WHERE textpattern.Section = txp_section.name) AS article_count", 'txp_section', "{$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { echo n . tag(toggle_box('section_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'section_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('name', 'name', 'section', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('title', 'title', 'section', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('page', 'page', 'section', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'txp-list-col-page') . column_head('css', 'css', 'section', true, $switch_dir, $crit, $search_method, ('css' == $sort ? "{$dir} " : '') . 'txp-list-col-style') . column_head('on_front_page', 'on_frontpage', 'section', true, $switch_dir, $crit, $search_method, ('on_frontpage' == $sort ? "{$dir} " : '') . 'txp-list-col-frontpage section_detail') . column_head('syndicate', 'in_rss', 'section', true, $switch_dir, $crit, $search_method, ('in_rss' == $sort ? "{$dir} " : '') . 'txp-list-col-syndicate section_detail') . column_head('include_in_search', 'searchable', 'section', true, $switch_dir, $crit, $search_method, ('searchable' == $sort ? "{$dir} " : '') . 'txp-list-col-searchable section_detail') . column_head('articles', 'article_count', 'section', true, $switch_dir, $crit, $search_method, ('article_count' == $sort ? "{$dir} " : '') . 'txp-list-col-article_count section_detail')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'sec'); $edit_url = array('event' => 'section', 'step' => 'section_edit', 'name' => $sec_name, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); if ($sec_name == 'default') { $articles = $sec_searchable = $sec_in_rss = $sec_on_frontpage = '-'; } else { $sec_on_frontpage = asyncHref(yes_no($sec_on_frontpage), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'on_frontpage')); $sec_in_rss = asyncHref(yes_no($sec_in_rss), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'in_rss')); $sec_searchable = asyncHref(yes_no($sec_searchable), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'searchable')); if ($sec_article_count > 0) { $articles = href($sec_article_count, array('event' => 'list', 'search_method' => 'section', 'crit' => '"' . $sec_name . '"'), array('title' => gTxt('article_count', array('{num}' => $sec_article_count)))); } else { $articles = 0; } } $sec_page = href(txpspecialchars($sec_page), array('event' => 'page', 'name' => $sec_page), array('title' => gTxt('edit'))); $sec_css = href(txpspecialchars($sec_css), array('event' => 'css', 'name' => $sec_css), array('title' => gTxt('edit'))); echo tr(td(fInput('checkbox', 'selected[]', $sec_name), '', 'txp-list-col-multi-edit') . hCell(href(txpspecialchars($sec_name), $edit_url, array('title' => gTxt('edit'))) . span(sp . span('|', array('role' => 'separator')) . sp . href(gTxt('view'), pagelinkurl(array('s' => $sec_name))), array('class' => 'txp-option-link section_detail')), '', array('class' => 'txp-list-col-name', 'scope' => 'row')) . td(txpspecialchars($sec_title), '', 'txp-list-col-title') . td($sec_page, '', 'txp-list-col-page') . td($sec_css, '', 'txp-list-col-style') . td($sec_on_frontpage, '', 'txp-list-col-frontpage section_detail') . td($sec_in_rss, '', 'txp-list-col-syndicate section_detail') . td($sec_searchable, '', 'txp-list-col-searchable section_detail') . td($articles, '', 'txp-list-col-article_count section_detail'), array('id' => 'txp_section_' . $sec_name)); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . section_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . n . tag_start('div', array('class' => 'txp-navigation', 'id' => $event . '_navigation')) . pageby_form('section', $section_list_pageby) . nav_form('section', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }