Example #1
0
function psas($array)
{
    foreach ($array as $a) {
        $out[$a] = doStripTags(ps($a));
    }
    return $out;
}
Example #2
0
function commentForm($id, $atts = NULL)
{
    global $prefs;
    extract($prefs);
    extract(lAtts(array('isize' => '25', 'msgrows' => '5', 'msgcols' => '25', 'msgstyle' => '', 'form' => 'comment_form'), $atts));
    $namewarn = '';
    $emailwarn = '';
    $commentwarn = '';
    $name = pcs('name');
    $email = pcs('email');
    $web = pcs('web');
    extract(doStripTags(doDeEnt(psa(array('remember', 'forget', 'parentid', 'preview', 'message', 'submit', 'backpage')))));
    if ($preview) {
        $name = ps('name');
        $email = ps('email');
        $web = ps('web');
        $nonce = md5(uniqid(rand(), true));
        $secret = md5(uniqid(rand(), true));
        safe_insert("txp_discuss_nonce", "issue_time=now(), nonce='{$nonce}', secret='{$secret}'");
        $namewarn = $comments_require_name ? !trim($name) ? gTxt('comment_name_required') . br : '' : '';
        $emailwarn = $comments_require_email ? !trim($email) ? gTxt('comment_email_required') . br : '' : '';
        $commentwarn = !trim($message) ? gTxt('comment_required') . br : '';
    }
    // 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;
    if (pcs('name') || pcs('email') || pcs('web')) {
        // Form-input different from Cookie, let's update the Cookie.
        if (cs('name') != ps('name') or cs('email') != ps('email') or cs('web') != ps('web')) {
        }
        $remember = 1;
    }
    if ($remember == 1) {
        setCookies($name, $email, $web);
    }
    if ($forget == 1) {
        destroyCookies();
    }
    $out = '<form method="post" action="#cpreview" id="txpCommentInputForm">';
    $Form = fetch('Form', 'txp_form', 'name', $form);
    $msgstyle = $msgstyle ? ' style="' . $msgstyle . '"' : '';
    $msgrows = ($msgrows and is_numeric($msgrows)) ? ' rows="' . intval($msgrows) . '"' : '';
    $msgcols = ($msgcols and is_numeric($msgcols)) ? ' cols="' . intval($msgcols) . '"' : '';
    $textarea = '<textarea class="txpCommentInputMessage" name="message"' . $msgcols . $msgrows . $msgstyle . ' tabindex="1">' . htmlspecialchars($message) . '</textarea>';
    $comment_submit_button = $preview ? fInput('submit', 'submit', gTxt('submit'), 'button') : '';
    $checkbox = !empty($_COOKIE['txp_name']) ? checkbox('forget', 1, 0) . gTxt('forget') : checkbox('remember', 1, 1) . gTxt('remember');
    $vals = array('comment_name_input' => $namewarn . input('text', 'name', $name, $isize, 'comment_name_input', "2"), 'comment_email_input' => $emailwarn . input('text', 'email', $email, $isize, 'comment_email_input', "3"), 'comment_web_input' => input('text', 'web', $web, $isize, 'comment_web_input', "4"), 'comment_message_input' => $commentwarn . $textarea, 'comment_remember' => $checkbox, 'comment_preview' => input('submit', 'preview', gTxt('preview'), 'comment_preview', 'button'), 'comment_submit' => $comment_submit_button);
    foreach ($vals as $a => $b) {
        $Form = str_replace('<txp:' . $a . ' />', $b, $Form);
    }
    $form = parse($Form);
    $out .= $form;
    $out .= graf(fInput('hidden', 'parentid', $parentid));
    $out .= $preview ? hInput('nonce', $nonce) : '';
    $out .= !$preview ? graf(fInput('hidden', 'backpage', serverset("REQUEST_URI"))) : graf(fInput('hidden', 'backpage', $backpage));
    $out .= '</form>';
    return $out;
}
Example #3
0
function commentForm($id, $atts = NULL)
{
    global $prefs;
    extract($prefs);
    extract(lAtts(array('isize' => '25', 'msgrows' => '5', 'msgcols' => '25', 'msgstyle' => '', 'form' => 'comment_form'), $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(doStripTags(doDeEnt(psa(array('checkbox_type', 'remember', 'forget', 'parentid', 'preview', 'message', 'submit', 'backpage')))));
    if ($message == '') {
        //Second or later preview will have randomized message-field name
        $in = getComment();
        $message = doStripTags(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;
        } else {
            if ($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="' . htmlspecialchars($url) . '#cpreview">' . n . '<div class="comments-wrapper">' . n . n;
    $Form = fetch('Form', 'txp_form', 'name', $form);
    $msgstyle = $msgstyle ? ' style="' . $msgstyle . '"' : '';
    $msgrows = ($msgrows and is_numeric($msgrows)) ? ' rows="' . intval($msgrows) . '"' : '';
    $msgcols = ($msgcols and is_numeric($msgcols)) ? ' cols="' . intval($msgcols) . '"' : '';
    $textarea = '<textarea id="message" name="' . $n_message . '"' . $msgcols . $msgrows . $msgstyle . ' class="txpCommentInputMessage' . ($commentwarn ? ' comments_error"' : '"') . '>' . htmlspecialchars($message) . '</textarea>';
    $comment_submit_button = $preview ? fInput('submit', 'submit', gTxt('submit'), 'button') : '';
    if ($checkbox_type == 'forget') {
        // inhibit default remember
        if ($forget == 1) {
            destroyCookies();
        }
        $checkbox = checkbox('forget', 1, $forget, '', 'forget') . ' ' . tag(gTxt('forget'), 'label', ' for="forget"');
    } else {
        // inhibit default remember
        if ($remember != 1) {
            destroyCookies();
        }
        $checkbox = checkbox('remember', 1, $remember, '', 'remember') . ' ' . tag(gTxt('remember'), 'label', ' for="remember"');
    }
    $checkbox .= ' ' . hInput('checkbox_type', $checkbox_type);
    $vals = array('comment_name_input' => fInput('text', 'name', htmlspecialchars($name), 'comment_name_input' . ($namewarn ? ' comments_error' : ''), '', '', $isize, '', 'comment_name_input'), 'comment_email_input' => fInput('text', 'email', htmlspecialchars($email), 'comment_email_input' . ($emailwarn ? ' comments_error' : ''), '', '', $isize, '', 'comment_email_input'), 'comment_web_input' => fInput('text', 'web', htmlspecialchars($web), 'comment_web_input', '', '', $isize, '', 'comment_web_input'), 'comment_message_input' => $textarea . '<!-- plugin-place-holder -->', 'comment_remember' => $checkbox, 'comment_preview' => fInput('submit', 'preview', gTxt('preview'), 'button'), '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', htmlspecialchars($url)) : n . hInput('backpage', htmlspecialchars($backpage));
    $out = str_replace('<!-- plugin-place-holder -->', callback_event('comment.form'), $out);
    $out .= n . n . '</div>' . n . '</form>';
    return $out;
}
Example #4
0
/**
 * 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>';
}
Example #5
0
function doDiagnostics()
{
    global $prefs, $files, $txpcfg, $event, $step, $theme;
    extract(get_prefs());
    $urlparts = parse_url(hu);
    $mydomain = $urlparts['host'];
    $server_software = @$_SERVER['SERVER_SOFTWARE'] || @$_SERVER['HTTP_HOST'] ? @$_SERVER['SERVER_SOFTWARE'] ? @$_SERVER['SERVER_SOFTWARE'] : $_SERVER['HTTP_HOST'] : '';
    $is_apache = ($server_software and stristr($server_software, 'Apache')) or 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('textpattern_version_update' => $updateInfo['msg'] ? diag_msg_wrap($updateInfo['msg'], 'information') : '', 'php_version_required' => (!is_callable('version_compare') or version_compare(PHP_VERSION, REQUIRED_PHP_VERSION, '<')) ? diag_msg_wrap(gTxt('php_version_required', array('{version}' => REQUIRED_PHP_VERSION))) : '', 'path_to_site_missing' => !isset($path_to_site) ? diag_msg_wrap(gTxt('path_to_site_missing'), 'warning') : '', 'dns_lookup_fails' => @gethostbyname($mydomain) == $mydomain ? diag_msg_wrap(gTxt('dns_lookup_fails') . cs . $mydomain, 'warning') : '', 'path_to_site_inacc' => !@is_dir($path_to_site) ? diag_msg_wrap(gTxt('path_to_site_inacc') . cs . $path_to_site) : '', 'site_trailing_slash' => rtrim($siteurl, '/') != $siteurl ? diag_msg_wrap(gTxt('site_trailing_slash') . cs . $path_to_site, 'warning') : '', 'index_inaccessible' => (!@is_file($path_to_site . "/index.php") or !@is_readable($path_to_site . "/index.php")) ? diag_msg_wrap("{$path_to_site}/index.php " . gTxt('is_inaccessible')) : '', 'dir_not_writable' => trim((!@is_writable($path_to_site . '/' . $img_dir) ? diag_msg_wrap(str_replace('{dirtype}', gTxt('img_dir'), gTxt('dir_not_writable')) . ": {$path_to_site}/{$img_dir}", 'warning') . n : '') . (!@is_writable($file_base_path) ? diag_msg_wrap(str_replace('{dirtype}', gTxt('file_base_path'), gTxt('dir_not_writable')) . ": {$file_base_path}", 'warning') . n : '') . (!@is_writable($tempdir) ? diag_msg_wrap(str_replace('{dirtype}', gTxt('tempdir'), gTxt('dir_not_writable')) . ": {$tempdir}", 'warning') . n : '')), 'cleanurl_only_apache' => ($permlink_mode != 'messy' and !$is_apache) ? diag_msg_wrap(gTxt('cleanurl_only_apache'), 'information') : '', 'htaccess_missing' => ($permlink_mode != 'messy' and !@is_readable($path_to_site . '/.htaccess')) ? diag_msg_wrap(gTxt('htaccess_missing')) : '', 'mod_rewrite_missing' => ($permlink_mode != 'messy' and is_callable('apache_get_modules') and !apache_module('mod_rewrite')) ? diag_msg_wrap(gTxt('mod_rewrite_missing')) : '', 'file_uploads_disabled' => !ini_get('file_uploads') ? diag_msg_wrap(gTxt('file_uploads_disabled'), 'information') : '', 'setup_still_exists' => @is_dir(txpath . DS . 'setup') ? diag_msg_wrap(txpath . DS . "setup" . DS . ' ' . gTxt('still_exists'), 'warning') : '', 'no_temp_dir' => empty($tempdir) ? diag_msg_wrap(gTxt('no_temp_dir'), 'warning') : '', 'warn_mail_unavailable' => is_disabled('mail') ? diag_msg_wrap(gTxt('warn_mail_unavailable'), 'warning') : '', 'warn_register_globals_or_update' => $is_register_globals && (version_compare(phpversion(), '4.4.0', '<=') or version_compare(phpversion(), '5.0.0', '>=') and version_compare(phpversion(), '5.0.5', '<=')) ? 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}");
            }
        }
    }
    $missing = array();
    foreach ($files as $f) {
        $realpath = realpath(txpath . $f);
        if (is_readable($realpath)) {
            $found[] = $realpath;
        } else {
            $missing[] = txpath . $f;
        }
    }
    $files = $found;
    unset($found);
    if ($missing) {
        $fail['missing_files'] = diag_msg_wrap(gTxt('missing_files') . cs . n . t . join(', ' . n . t, $missing));
    }
    foreach ($fail as $k => $v) {
        if (empty($v)) {
            unset($fail[$k]);
        }
    }
    # Find the highest revision number
    $file_revs = $file_md5 = array();
    $rev = 0;
    foreach ($files as $f) {
        $content = @file_get_contents($f);
        if ($content !== FALSE) {
            if (preg_match('/^\\$' . 'LastChangedRevision: (\\d+) \\$/m', $content, $match)) {
                $file_revs[$f] = $match[1];
                if ($match[1] > $rev) {
                    $rev = $match[1];
                }
            }
            $file_md5[$f] = md5(str_replace('$' . 'HeadURL: http:', '$' . 'HeadURL: https:', str_replace("\r\n", "\n", $content)));
        }
    }
    # Check revs & md5 against stable release, if possible
    $dev_files = $old_files = $modified_files = array();
    if ($cs = @file(txpath . '/checksums.txt')) {
        foreach ($cs as $c) {
            if (preg_match('@^(\\S+): r?(\\S+) \\((.*)\\)$@', trim($c), $m)) {
                list(, $file, $r, $md5) = $m;
                $file = realpath(txpath . $file);
                if (!empty($file_revs[$file]) and $r and $file_revs[$file] < $r) {
                    $old_files[] = $file;
                } elseif (!empty($file_revs[$file]) and $r and $file_revs[$file] > $r) {
                    $dev_files[] = $file;
                } elseif (!empty($file_md5[$file]) and $file_md5[$file] != $md5) {
                    $modified_files[] = $file;
                }
            }
        }
    }
    # files that haven't been updated
    if ($old_files) {
        $fail['old_files'] = diag_msg_wrap(gTxt('old_files') . cs . n . t . join(', ' . n . t, $old_files));
    }
    # files that don't match their checksums
    if ($modified_files) {
        $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 ($dev_files and $production_status == 'live') {
        $fail['dev_version_live'] = diag_msg_wrap(gTxt('dev_version_live') . cs . n . t . join(', ' . n . t, $dev_files), 'warning');
    }
    # 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', 'exec', 'system', 'dl', 'passthru', 'chown', 'shell_exec', 'popen', 'proc_open'));
        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'));
    }
    echo pagetop(gTxt('tab_diagnostics'), ''), '<h1 class="txp-heading">' . gTxt('tab_diagnostics') . '</h1>', '<div id="' . $event . '_container" class="txp-container">', '<div id="pre_flight_check">', hed(gTxt('preflight_check'), 2);
    if ($fail) {
        foreach ($fail as $help => $message) {
            echo graf(nl2br($message) . sp . 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 id="diagnostics-detail" cols="' . INPUT_LARGE . '" rows="' . INPUT_MEDIUM . '" readonly="readonly">', gTxt('txp_version') . cs . txp_version . ' (' . ($rev ? 'r' . $rev : 'unknown revision') . ')' . 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: ' . (timezone::is_supported() ? @date_default_timezone_get() : (getenv('TZ') ? getenv('TZ') : '-')) . 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('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') {
        $mysql_client_encoding = is_callable('mysql_client_encoding') ? mysql_client_encoding() : '-';
        $out[] = n . 'Charset (default/config)' . cs . $mysql_client_encoding . '/' . @$txpcfg['dbcharset'] . 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;
        foreach ($files as $f) {
            $checksum = isset($file_md5[$f]) ? $file_md5[$f] : gTxt('unknown');
            $revision = isset($file_revs[$f]) ? 'r' . $file_revs[$f] : gTxt('unknown');
            $out[] = "{$f}" . cs . n . t . $revision . ' (' . $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>' . n . selectInput('step', $dets, $step, 0, 1)));
    echo join('', $out), '</div>', '</div>';
}
Example #6
0
function commentForm($id, $atts = NULL)
{
    global $prefs;
    extract($prefs);
    extract(lAtts(array('isize' => '25', 'msgrows' => '5', 'msgcols' => '25', 'msgstyle' => '', 'form' => 'comment_form'), $atts));
    $namewarn = false;
    $emailwarn = false;
    $commentwarn = false;
    $name = pcs('name');
    $email = clean_url(pcs('email'));
    $web = clean_url(pcs('web'));
    extract(doStripTags(doDeEnt(psa(array('remember', 'forget', 'parentid', 'preview', 'message', 'submit', 'backpage')))));
    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='{$nonce}', secret='{$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'));
        }
    }
    // 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;
    if (pcs('name') || pcs('email') || pcs('web')) {
        // Form-input different from Cookie, let's update the Cookie.
        if (cs('name') != ps('name') or cs('email') != ps('email') or cs('web') != ps('web')) {
        }
        $remember = 1;
    }
    if ($remember == 1) {
        setCookies($name, $email, $web);
    }
    if ($forget == 1) {
        destroyCookies();
    }
    $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 method="post" action="' . $url . '#cpreview" id="txpCommentInputForm">';
    $Form = fetch('Form', 'txp_form', 'name', $form);
    $msgstyle = $msgstyle ? ' style="' . $msgstyle . '"' : '';
    $msgrows = ($msgrows and is_numeric($msgrows)) ? ' rows="' . intval($msgrows) . '"' : '';
    $msgcols = ($msgcols and is_numeric($msgcols)) ? ' cols="' . intval($msgcols) . '"' : '';
    $textarea = '<textarea class="txpCommentInputMessage' . ($commentwarn ? ' comments_error"' : '"') . ' name="message" id="message" ' . $msgcols . $msgrows . $msgstyle . '>' . htmlspecialchars($message) . '</textarea>';
    $comment_submit_button = $preview ? fInput('submit', 'submit', gTxt('submit'), 'button') : '';
    $checkbox = !empty($_COOKIE['txp_name']) ? checkbox('forget', 1, 0) . tag(gTxt('forget'), 'label', ' for="forget"') : checkbox('remember', 1, 1) . tag(gTxt('remember'), 'label', ' for="remember"');
    $vals = array('comment_name_input' => input('text', 'name', htmlspecialchars($name), $isize, 'comment_name_input' . ($namewarn ? ' comments_error' : ''), ""), 'comment_email_input' => input('text', 'email', htmlspecialchars($email), $isize, 'comment_email_input' . ($emailwarn ? ' comments_error' : ''), ""), 'comment_web_input' => input('text', 'web', htmlspecialchars($web), $isize, 'comment_web_input', ""), 'comment_message_input' => $textarea . '<!-- plugin-place-holder -->', 'comment_remember' => $checkbox, 'comment_preview' => input('submit', 'preview', gTxt('preview'), '', 'button'), 'comment_submit' => $comment_submit_button);
    foreach ($vals as $a => $b) {
        $Form = str_replace('<txp:' . $a . ' />', $b, $Form);
    }
    $form = parse($Form);
    $out .= $form;
    $out .= fInput('hidden', 'parentid', $parentid);
    $split = rand(1, 31);
    $out .= $preview ? hInput(substr($nonce, 0, $split), substr($nonce, $split)) : '';
    $out .= !$preview ? fInput('hidden', 'backpage', serverset("REQUEST_URI")) : fInput('hidden', 'backpage', $backpage);
    $out = substr_replace($out, callback_event('comment.form'), strpos($out, '<!-- plugin-place-holder -->'), strlen('<!-- plugin-place-holder -->'));
    $out .= '</form>';
    return $out;
}