Commit 69f0154b by Scott

Reformat code for users pages, tags page, and base theme

And normalize some line endings
parent e707b833
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-page-message.php File: qa-include/qa-page-message.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Controller for private messaging page Description: Controller for private messaging page
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; require_once QA_INCLUDE_DIR.'qa-db-selects.php';
require_once QA_INCLUDE_DIR.'qa-app-users.php'; require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-format.php'; require_once QA_INCLUDE_DIR.'qa-app-format.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
$loginUserId = qa_get_logged_in_userid(); $loginUserId = qa_get_logged_in_userid();
// Check which box we're showing (inbox/sent), we're not using Q2A's single-sign on integration and that we're logged in // Check which box we're showing (inbox/sent), we're not using Q2A's single-sign on integration and that we're logged in
$showingInbox = qa_request_part(1) !== 'sent'; $showingInbox = qa_request_part(1) !== 'sent';
if (QA_FINAL_EXTERNAL_USERS) if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User accounts are handled by external code'); qa_fatal_error('User accounts are handled by external code');
if (!isset($loginUserId)) { if (!isset($loginUserId)) {
$qa_content = qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['error'] = qa_insert_login_links(qa_lang_html('misc/message_must_login'), qa_request()); $qa_content['error'] = qa_insert_login_links(qa_lang_html('misc/message_must_login'), qa_request());
return $qa_content; return $qa_content;
} }
if ( !qa_opt('allow_private_messages') ) if ( !qa_opt('allow_private_messages') )
return include QA_INCLUDE_DIR.'qa-page-not-found.php'; return include QA_INCLUDE_DIR.'qa-page-not-found.php';
// Find the user profile and questions and answers for this handle // Find the user profile and questions and answers for this handle
$pmSpec = $showingInbox $pmSpec = $showingInbox
? qa_db_messages_inbox_selectspec('private', $loginUserId, true) ? qa_db_messages_inbox_selectspec('private', $loginUserId, true)
: qa_db_messages_outbox_selectspec('private', $loginUserId, true); : qa_db_messages_outbox_selectspec('private', $loginUserId, true);
$userMessages = qa_db_select_with_pending($pmSpec); $userMessages = qa_db_select_with_pending($pmSpec);
// Prepare content for theme // Prepare content for theme
$qa_content = qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['title'] = $showingInbox ? qa_lang_html('misc/pm_inbox_title') : qa_lang_html('misc/pm_outbox_title'); $qa_content['title'] = $showingInbox ? qa_lang_html('misc/pm_inbox_title') : qa_lang_html('misc/pm_outbox_title');
$qa_content['message_list'] = array( $qa_content['message_list'] = array(
'tags' => 'id="privatemessages"', 'tags' => 'id="privatemessages"',
'messages' => array(), 'messages' => array(),
); );
$htmlDefaults = qa_message_html_defaults(); $htmlDefaults = qa_message_html_defaults();
if (!$showingInbox) { if (!$showingInbox) {
$htmlDefaults['towhomview'] = true; $htmlDefaults['towhomview'] = true;
} }
foreach ($userMessages as $message) { foreach ($userMessages as $message) {
$qa_content['message_list']['messages'][] = qa_message_html_fields($message, $htmlDefaults); $qa_content['message_list']['messages'][] = qa_message_html_fields($message, $htmlDefaults);
} }
$qa_content['navigation']['sub'] = array( $qa_content['navigation']['sub'] = array(
'inbox' => array( 'inbox' => array(
'label' => qa_lang_html('misc/inbox'), 'label' => qa_lang_html('misc/inbox'),
'url' => qa_path_html('messages'), 'url' => qa_path_html('messages'),
'selected' => $showingInbox, 'selected' => $showingInbox,
), ),
'outbox' => array( 'outbox' => array(
'label' => qa_lang_html('misc/outbox'), 'label' => qa_lang_html('misc/outbox'),
'url' => qa_path_html('messages/sent'), 'url' => qa_path_html('messages/sent'),
'selected' => !$showingInbox, 'selected' => !$showingInbox,
) )
); );
return $qa_content; return $qa_content;
...@@ -35,49 +35,49 @@ ...@@ -35,49 +35,49 @@
// Get popular tags // Get popular tags
$start=qa_get_start(); $start = qa_get_start();
$userid=qa_get_logged_in_userid(); $userid = qa_get_logged_in_userid();
$populartags=qa_db_select_with_pending( $populartags = qa_db_select_with_pending(
qa_db_popular_tags_selectspec($start, qa_opt_if_loaded('page_size_tags')) qa_db_popular_tags_selectspec($start, qa_opt_if_loaded('page_size_tags'))
); );
$tagcount=qa_opt('cache_tagcount'); $tagcount = qa_opt('cache_tagcount');
$pagesize=qa_opt('page_size_tags'); $pagesize = qa_opt('page_size_tags');
// Prepare content for theme // Prepare content for theme
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['title']=qa_lang_html('main/popular_tags'); $qa_content['title'] = qa_lang_html('main/popular_tags');
$qa_content['ranking']=array( $qa_content['ranking'] = array(
'items' => array(), 'items' => array(),
'rows' => ceil($pagesize/qa_opt('columns_tags')), 'rows' => ceil($pagesize/qa_opt('columns_tags')),
'type' => 'tags' 'type' => 'tags'
); );
if (count($populartags)) { if (count($populartags)) {
$favoritemap=qa_get_favorite_non_qs_map(); $favoritemap = qa_get_favorite_non_qs_map();
$output=0; $output = 0;
foreach ($populartags as $word => $count) { foreach ($populartags as $word => $count) {
$qa_content['ranking']['items'][]=array( $qa_content['ranking']['items'][] = array(
'label' => qa_tag_html($word, false, @$favoritemap['tag'][qa_strtolower($word)]), 'label' => qa_tag_html($word, false, @$favoritemap['tag'][qa_strtolower($word)]),
'count' => number_format($count), 'count' => number_format($count),
); );
if ((++$output)>=$pagesize) if ((++$output) >= $pagesize)
break; break;
} }
} else } else
$qa_content['title']=qa_lang_html('main/no_tags_found'); $qa_content['title'] = qa_lang_html('main/no_tags_found');
$qa_content['page_links']=qa_html_page_links(qa_request(), $start, $pagesize, $tagcount, qa_opt('pages_prev_next')); $qa_content['page_links'] = qa_html_page_links(qa_request(), $start, $pagesize, $tagcount, qa_opt('pages_prev_next'));
if (empty($qa_content['page_links'])) if (empty($qa_content['page_links']))
$qa_content['suggest_next']=qa_html_suggest_ask(); $qa_content['suggest_next'] = qa_html_suggest_ask();
return $qa_content; return $qa_content;
......
...@@ -42,44 +42,44 @@ ...@@ -42,44 +42,44 @@
// Get list of blocked users // Get list of blocked users
$users=qa_db_select_with_pending(qa_db_users_with_flag_selectspec(QA_USER_FLAGS_USER_BLOCKED)); $users = qa_db_select_with_pending(qa_db_users_with_flag_selectspec(QA_USER_FLAGS_USER_BLOCKED));
// Check we have permission to view this page (moderator or above) // Check we have permission to view this page (moderator or above)
if (qa_get_logged_in_level() < QA_USER_LEVEL_MODERATOR) { if (qa_get_logged_in_level() < QA_USER_LEVEL_MODERATOR) {
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['error']=qa_lang_html('users/no_permission'); $qa_content['error'] = qa_lang_html('users/no_permission');
return $qa_content; return $qa_content;
} }
// Get userids and handles of retrieved users // Get userids and handles of retrieved users
$usershtml=qa_userids_handles_html($users); $usershtml = qa_userids_handles_html($users);
// Prepare content for theme // Prepare content for theme
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['title']=count($users) ? qa_lang_html('users/blocked_users') : qa_lang_html('users/no_blocked_users'); $qa_content['title'] = count($users) ? qa_lang_html('users/blocked_users') : qa_lang_html('users/no_blocked_users');
$qa_content['ranking']=array( $qa_content['ranking'] = array(
'items' => array(), 'items' => array(),
'rows' => ceil(count($users)/qa_opt('columns_users')), 'rows' => ceil(count($users)/qa_opt('columns_users')),
'type' => 'users' 'type' => 'users'
); );
foreach ($users as $user) { foreach ($users as $user) {
$qa_content['ranking']['items'][]=array( $qa_content['ranking']['items'][] = array(
'label' => $usershtml[$user['userid']], 'label' => $usershtml[$user['userid']],
'score' => qa_html(qa_user_level_string($user['level'])), 'score' => qa_html(qa_user_level_string($user['level'])),
'raw' => $user, 'raw' => $user,
); );
} }
$qa_content['navigation']['sub']=qa_users_sub_navigation(); $qa_content['navigation']['sub'] = qa_users_sub_navigation();
return $qa_content; return $qa_content;
......
...@@ -42,44 +42,44 @@ ...@@ -42,44 +42,44 @@
// Get list of special users // Get list of special users
$users=qa_db_select_with_pending(qa_db_users_from_level_selectspec(QA_USER_LEVEL_EXPERT)); $users = qa_db_select_with_pending(qa_db_users_from_level_selectspec(QA_USER_LEVEL_EXPERT));
// Check we have permission to view this page (moderator or above) // Check we have permission to view this page (moderator or above)
if (qa_get_logged_in_level() < QA_USER_LEVEL_MODERATOR) { if (qa_get_logged_in_level() < QA_USER_LEVEL_MODERATOR) {
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['error']=qa_lang_html('users/no_permission'); $qa_content['error'] = qa_lang_html('users/no_permission');
return $qa_content; return $qa_content;
} }
// Get userids and handles of retrieved users // Get userids and handles of retrieved users
$usershtml=qa_userids_handles_html($users); $usershtml = qa_userids_handles_html($users);
// Prepare content for theme // Prepare content for theme
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['title']=qa_lang_html('users/special_users'); $qa_content['title'] = qa_lang_html('users/special_users');
$qa_content['ranking']=array( $qa_content['ranking'] = array(
'items' => array(), 'items' => array(),
'rows' => ceil(qa_opt('page_size_users')/qa_opt('columns_users')), 'rows' => ceil(qa_opt('page_size_users')/qa_opt('columns_users')),
'type' => 'users' 'type' => 'users'
); );
foreach ($users as $user) { foreach ($users as $user) {
$qa_content['ranking']['items'][]=array( $qa_content['ranking']['items'][] = array(
'label' => $usershtml[$user['userid']], 'label' => $usershtml[$user['userid']],
'score' => qa_html(qa_user_level_string($user['level'])), 'score' => qa_html(qa_user_level_string($user['level'])),
'raw' => $user, 'raw' => $user,
); );
} }
$qa_content['navigation']['sub']=qa_users_sub_navigation(); $qa_content['navigation']['sub'] = qa_users_sub_navigation();
return $qa_content; return $qa_content;
......
...@@ -36,22 +36,22 @@ ...@@ -36,22 +36,22 @@
// Get list of all users // Get list of all users
$start=qa_get_start(); $start = qa_get_start();
$users=qa_db_select_with_pending(qa_db_top_users_selectspec($start, qa_opt_if_loaded('page_size_users'))); $users = qa_db_select_with_pending(qa_db_top_users_selectspec($start, qa_opt_if_loaded('page_size_users')));
$usercount=qa_opt('cache_userpointscount'); $usercount = qa_opt('cache_userpointscount');
$pagesize=qa_opt('page_size_users'); $pagesize = qa_opt('page_size_users');
$users=array_slice($users, 0, $pagesize); $users = array_slice($users, 0, $pagesize);
$usershtml=qa_userids_handles_html($users); $usershtml = qa_userids_handles_html($users);
// Prepare content for theme // Prepare content for theme
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['title']=qa_lang_html('main/highest_users'); $qa_content['title'] = qa_lang_html('main/highest_users');
$qa_content['ranking']=array( $qa_content['ranking'] = array(
'items' => array(), 'items' => array(),
'rows' => ceil($pagesize/qa_opt('columns_users')), 'rows' => ceil($pagesize/qa_opt('columns_users')),
'type' => 'users' 'type' => 'users'
...@@ -76,11 +76,11 @@ ...@@ -76,11 +76,11 @@
} }
} }
else else
$qa_content['title']=qa_lang_html('main/no_active_users'); $qa_content['title'] = qa_lang_html('main/no_active_users');
$qa_content['page_links']=qa_html_page_links(qa_request(), $start, $pagesize, $usercount, qa_opt('pages_prev_next')); $qa_content['page_links'] = qa_html_page_links(qa_request(), $start, $pagesize, $usercount, qa_opt('pages_prev_next'));
$qa_content['navigation']['sub']=qa_users_sub_navigation(); $qa_content['navigation']['sub'] = qa_users_sub_navigation();
return $qa_content; return $qa_content;
......
...@@ -71,15 +71,15 @@ ...@@ -71,15 +71,15 @@
*/ */
{ {
foreach ($elements as $element) { foreach ($elements as $element) {
$delta=substr_count($element, '<')-substr_count($element, '<!')-2*substr_count($element, '</')-substr_count($element, '/>'); $delta = substr_count($element, '<') - substr_count($element, '<!') - 2*substr_count($element, '</') - substr_count($element, '/>');
if ($delta<0) if ($delta < 0)
$this->indent+=$delta; $this->indent += $delta;
echo str_repeat("\t", max(0, $this->indent)).str_replace('/>', '>', $element)."\n"; echo str_repeat("\t", max(0, $this->indent)).str_replace('/>', '>', $element)."\n";
if ($delta>0) if ($delta > 0)
$this->indent+=$delta; $this->indent += $delta;
$this->lines++; $this->lines++;
} }
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
Output each passed parameter on a separate line - see output_array() comments Output each passed parameter on a separate line - see output_array() comments
*/ */
{ {
$args=func_get_args(); $args = func_get_args();
$this->output_array($args); $this->output_array($args);
} }
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
with appropriate CSS classes based on $class, using $outertag and $innertag in the markup. with appropriate CSS classes based on $class, using $outertag and $innertag in the markup.
*/ */
{ {
if (empty($parts) && (strtolower($outertag)!='td')) if (empty($parts) && strtolower($outertag) != 'td')
return; return;
$this->output( $this->output(
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
Set some context, which be accessed via $this->context for a function to know where it's being used on the page Set some context, which be accessed via $this->context for a function to know where it's being used on the page
*/ */
{ {
$this->context[$key]=$value; $this->context[$key] = $value;
} }
...@@ -180,12 +180,13 @@ ...@@ -180,12 +180,13 @@
Post-output cleanup. For now, check that the indenting ended right, and if not, output a warning in an HTML comment Post-output cleanup. For now, check that the indenting ended right, and if not, output a warning in an HTML comment
*/ */
{ {
if ($this->indent) if ($this->indent) {
echo "<!--\nIt's no big deal, but your HTML could not be indented properly. To fix, please:\n". echo "<!--\nIt's no big deal, but your HTML could not be indented properly. To fix, please:\n".
"1. Use this->output() to output all HTML.\n". "1. Use this->output() to output all HTML.\n".
"2. Balance all paired tags like <td>...</td> or <div>...</div>.\n". "2. Balance all paired tags like <td>...</td> or <div>...</div>.\n".
"3. Use a slash at the end of unpaired tags like <img/> or <input/>.\n". "3. Use a slash at the end of unpaired tags like <img/> or <input/>.\n".
"Thanks!\n-->\n"; "Thanks!\n-->\n";
}
} }
...@@ -236,8 +237,8 @@ ...@@ -236,8 +237,8 @@
public function head_title() public function head_title()
{ {
$pagetitle=strlen($this->request) ? strip_tags(@$this->content['title']) : ''; $pagetitle = strlen($this->request) ? strip_tags(@$this->content['title']) : '';
$headtitle=(strlen($pagetitle) ? ($pagetitle.' - ') : '').$this->content['site_title']; $headtitle = (strlen($pagetitle) ? ($pagetitle.' - ') : '').$this->content['site_title'];
$this->output('<title>'.$headtitle.'</title>'); $this->output('<title>'.$headtitle.'</title>');
} }
...@@ -270,25 +271,28 @@ ...@@ -270,25 +271,28 @@
public function head_script() public function head_script()
{ {
if (isset($this->content['script'])) if (isset($this->content['script'])) {
foreach ($this->content['script'] as $scriptline) foreach ($this->content['script'] as $scriptline)
$this->output_raw($scriptline); $this->output_raw($scriptline);
}
} }
public function head_css() public function head_css()
{ {
$this->output('<link rel="stylesheet" type="text/css" href="'.$this->rooturl.$this->css_name().'"/>'); $this->output('<link rel="stylesheet" type="text/css" href="'.$this->rooturl.$this->css_name().'"/>');
if (isset($this->content['css_src'])) if (isset($this->content['css_src'])) {
foreach ($this->content['css_src'] as $css_src) foreach ($this->content['css_src'] as $css_src)
$this->output('<link rel="stylesheet" type="text/css" href="'.$css_src.'"/>'); $this->output('<link rel="stylesheet" type="text/css" href="'.$css_src.'"/>');
}
if (!empty($this->content['notices'])) if (!empty($this->content['notices'])) {
$this->output( $this->output(
'<style><!--', '<style><!--',
'.qa-body-js-on .qa-notice {display:none;}', '.qa-body-js-on .qa-notice {display:none;}',
'//--></style>' '//--></style>'
); );
}
} }
public function css_name() public function css_name()
...@@ -298,9 +302,10 @@ ...@@ -298,9 +302,10 @@
public function head_lines() public function head_lines()
{ {
if (isset($this->content['head_lines'])) if (isset($this->content['head_lines'])) {
foreach ($this->content['head_lines'] as $line) foreach ($this->content['head_lines'] as $line)
$this->output_raw($line); $this->output_raw($line);
}
} }
public function head_custom() public function head_custom()
...@@ -380,11 +385,12 @@ ...@@ -380,11 +385,12 @@
public function body_tags() public function body_tags()
{ {
$class='qa-template-'.qa_html($this->template); $class = 'qa-template-'.qa_html($this->template);
if (isset($this->content['categoryids'])) if (isset($this->content['categoryids'])) {
foreach ($this->content['categoryids'] as $categoryid) foreach ($this->content['categoryids'] as $categoryid)
$class.=' qa-category-'.qa_html($categoryid); $class .= ' qa-category-'.qa_html($categoryid);
}
$this->output('class="'.$class.' qa-body-js-off"'); $this->output('class="'.$class.' qa-body-js-off"');
} }
...@@ -401,9 +407,10 @@ ...@@ -401,9 +407,10 @@
public function notices() public function notices()
{ {
if (!empty($this->content['notices'])) if (!empty($this->content['notices'])) {
foreach ($this->content['notices'] as $notice) foreach ($this->content['notices'] as $notice)
$this->notice($notice); $this->notice($notice);
}
} }
public function notice($notice) public function notice($notice)
...@@ -460,7 +467,7 @@ ...@@ -460,7 +467,7 @@
public function search() public function search()
{ {
$search=$this->content['search']; $search = $this->content['search'];
$this->output( $this->output(
'<div class="qa-search">', '<div class="qa-search">',
...@@ -489,20 +496,21 @@ ...@@ -489,20 +496,21 @@
public function nav($navtype, $level=null) public function nav($navtype, $level=null)
{ {
$navigation=@$this->content['navigation'][$navtype]; $navigation = @$this->content['navigation'][$navtype];
if (($navtype=='user') || isset($navigation)) { if ($navtype == 'user' || isset($navigation)) {
$this->output('<div class="qa-nav-'.$navtype.'">'); $this->output('<div class="qa-nav-'.$navtype.'">');
if ($navtype=='user') if ($navtype == 'user')
$this->logged_in(); $this->logged_in();
// reverse order of 'opposite' items since they float right // reverse order of 'opposite' items since they float right
foreach (array_reverse($navigation, true) as $key => $navlink) foreach (array_reverse($navigation, true) as $key => $navlink) {
if (@$navlink['opposite']) { if (@$navlink['opposite']) {
unset($navigation[$key]); unset($navigation[$key]);
$navigation[$key]=$navlink; $navigation[$key] = $navlink;
} }
}
$this->set_context('nav_type', $navtype); $this->set_context('nav_type', $navtype);
$this->nav_list($navigation, 'nav-'.$navtype, $level); $this->nav_list($navigation, 'nav-'.$navtype, $level);
...@@ -517,7 +525,7 @@ ...@@ -517,7 +525,7 @@
{ {
$this->output('<ul class="qa-'.$class.'-list'.(isset($level) ? (' qa-'.$class.'-list-'.$level) : '').'">'); $this->output('<ul class="qa-'.$class.'-list'.(isset($level) ? (' qa-'.$class.'-list-'.$level) : '').'">');
$index=0; $index = 0;
foreach ($navigation as $key => $navlink) { foreach ($navigation as $key => $navlink) {
$this->set_context('nav_key', $key); $this->set_context('nav_key', $key);
...@@ -541,7 +549,7 @@ ...@@ -541,7 +549,7 @@
public function nav_item($key, $navlink, $class, $level=null) public function nav_item($key, $navlink, $class, $level=null)
{ {
$suffix=strtr($key, array( // map special character in navigation key $suffix = strtr($key, array( // map special character in navigation key
'$' => '', '$' => '',
'/' => '-', '/' => '-',
)); ));
...@@ -558,7 +566,7 @@ ...@@ -558,7 +566,7 @@
public function nav_link($navlink, $class) public function nav_link($navlink, $class)
{ {
if (isset($navlink['url'])) if (isset($navlink['url'])) {
$this->output( $this->output(
'<a href="'.$navlink['url'].'" class="qa-'.$class.'-link'. '<a href="'.$navlink['url'].'" class="qa-'.$class.'-link'.
(@$navlink['selected'] ? (' qa-'.$class.'-selected') : ''). (@$navlink['selected'] ? (' qa-'.$class.'-selected') : '').
...@@ -567,14 +575,15 @@ ...@@ -567,14 +575,15 @@
(isset($navlink['target']) ? (' target="'.$navlink['target'].'"') : '').'>'.$navlink['label']. (isset($navlink['target']) ? (' target="'.$navlink['target'].'"') : '').'>'.$navlink['label'].
'</a>' '</a>'
); );
}
else else {
$this->output( $this->output(
'<span class="qa-'.$class.'-nolink'.(@$navlink['selected'] ? (' qa-'.$class.'-selected') : ''). '<span class="qa-'.$class.'-nolink'.(@$navlink['selected'] ? (' qa-'.$class.'-selected') : '').
(@$navlink['favorited'] ? (' qa-'.$class.'-favorited') : '').'"'. (@$navlink['favorited'] ? (' qa-'.$class.'-favorited') : '').'"'.
(strlen(@$navlink['popup']) ? (' title="'.$navlink['popup'].'"') : ''). (strlen(@$navlink['popup']) ? (' title="'.$navlink['popup'].'"') : '').
'>'.$navlink['label'].'</span>' '>'.$navlink['label'].'</span>'
); );
}
if (strlen(@$navlink['note'])) if (strlen(@$navlink['note']))
$this->output('<span class="qa-'.$class.'-note">'.$navlink['note'].'</span>'); $this->output('<span class="qa-'.$class.'-note">'.$navlink['note'].'</span>');
...@@ -609,7 +618,7 @@ ...@@ -609,7 +618,7 @@
public function sidebar() public function sidebar()
{ {
$sidebar=@$this->content['sidebar']; $sidebar = @$this->content['sidebar'];
if (!empty($sidebar)) { if (!empty($sidebar)) {
$this->output('<div class="qa-sidebar">'); $this->output('<div class="qa-sidebar">');
...@@ -620,7 +629,7 @@ ...@@ -620,7 +629,7 @@
public function feed() public function feed()
{ {
$feed=@$this->content['feed']; $feed = @$this->content['feed'];
if (!empty($feed)) { if (!empty($feed)) {
$this->output('<div class="qa-feed">'); $this->output('<div class="qa-feed">');
...@@ -631,7 +640,7 @@ ...@@ -631,7 +640,7 @@
public function main() public function main()
{ {
$content=$this->content; $content = $this->content;
$this->output('<div class="qa-main'.(@$this->content['hidden'] ? ' qa-main-hidden' : '').'">'); $this->output('<div class="qa-main'.(@$this->content['hidden'] ? ' qa-main-hidden' : '').'">');
...@@ -641,14 +650,8 @@ ...@@ -641,14 +650,8 @@
$this->widgets('main', 'high'); $this->widgets('main', 'high');
/*if (isset($content['main_form_tags']))
$this->output('<form '.$content['main_form_tags'].'>');*/
$this->main_parts($content); $this->main_parts($content);
/*if (isset($content['main_form_tags']))
$this->output('</form>');*/
$this->widgets('main', 'low'); $this->widgets('main', 'low');
$this->page_links(); $this->page_links();
...@@ -661,7 +664,7 @@ ...@@ -661,7 +664,7 @@
public function page_title_error() public function page_title_error()
{ {
$favorite=@$this->content['favorite']; $favorite = @$this->content['favorite'];
if (isset($favorite)) if (isset($favorite))
$this->output('<form '.$favorite['form_tags'].'>'); $this->output('<form '.$favorite['form_tags'].'>');
...@@ -682,7 +685,7 @@ ...@@ -682,7 +685,7 @@
public function favorite() public function favorite()
{ {
$favorite=@$this->content['favorite']; $favorite = @$this->content['favorite'];
if (isset($favorite)) { if (isset($favorite)) {
$this->output('<span class="qa-favoriting" '.@$favorite['favorite_tags'].'>'); $this->output('<span class="qa-favoriting" '.@$favorite['favorite_tags'].'>');
...@@ -725,12 +728,13 @@ ...@@ -725,12 +728,13 @@
public function error($error) public function error($error)
{ {
if (strlen($error)) if (strlen($error)) {
$this->output( $this->output(
'<div class="qa-error">', '<div class="qa-error">',
$error, $error,
'</div>' '</div>'
); );
}
} }
public function main_parts($content) public function main_parts($content)
...@@ -745,46 +749,46 @@ ...@@ -745,46 +749,46 @@
public function main_part($key, $part) public function main_part($key, $part)
{ {
$partdiv=( $partdiv = (
(strpos($key, 'custom')===0) || strpos($key, 'custom') === 0 ||
(strpos($key, 'form')===0) || strpos($key, 'form') === 0 ||
(strpos($key, 'q_list')===0) || strpos($key, 'q_list') === 0 ||
(strpos($key, 'q_view')===0) || strpos($key, 'q_view') === 0 ||
(strpos($key, 'a_form')===0) || strpos($key, 'a_form') === 0 ||
(strpos($key, 'a_list')===0) || strpos($key, 'a_list') === 0 ||
(strpos($key, 'ranking')===0) || strpos($key, 'ranking') === 0 ||
(strpos($key, 'message_list')===0) || strpos($key, 'message_list') === 0 ||
(strpos($key, 'nav_list')===0) strpos($key, 'nav_list') === 0
); );
if ($partdiv) if ($partdiv)
$this->output('<div class="qa-part-'.strtr($key, '_', '-').'">'); // to help target CSS to page parts $this->output('<div class="qa-part-'.strtr($key, '_', '-').'">'); // to help target CSS to page parts
if (strpos($key, 'custom')===0) if (strpos($key, 'custom') === 0)
$this->output_raw($part); $this->output_raw($part);
elseif (strpos($key, 'form')===0) elseif (strpos($key, 'form') === 0)
$this->form($part); $this->form($part);
elseif (strpos($key, 'q_list')===0) elseif (strpos($key, 'q_list') === 0)
$this->q_list_and_form($part); $this->q_list_and_form($part);
elseif (strpos($key, 'q_view')===0) elseif (strpos($key, 'q_view') === 0)
$this->q_view($part); $this->q_view($part);
elseif (strpos($key, 'a_form')===0) elseif (strpos($key, 'a_form') === 0)
$this->a_form($part); $this->a_form($part);
elseif (strpos($key, 'a_list')===0) elseif (strpos($key, 'a_list') === 0)
$this->a_list($part); $this->a_list($part);
elseif (strpos($key, 'ranking')===0) elseif (strpos($key, 'ranking') === 0)
$this->ranking($part); $this->ranking($part);
elseif (strpos($key, 'message_list')===0) elseif (strpos($key, 'message_list') === 0)
$this->message_list_and_form($part); $this->message_list_and_form($part);
elseif (strpos($key, 'nav_list')===0) { elseif (strpos($key, 'nav_list') === 0) {
$this->part_title($part); $this->part_title($part);
$this->nav_list($part['nav'], $part['type'], 1); $this->nav_list($part['nav'], $part['type'], 1);
} }
...@@ -852,9 +856,9 @@ ...@@ -852,9 +856,9 @@
public function form_columns($form) public function form_columns($form)
{ {
if (isset($form['ok']) || !empty($form['fields']) ) if (isset($form['ok']) || !empty($form['fields']) )
$columns=($form['style']=='wide') ? 3 : 1; $columns = ($form['style'] == 'wide') ? 3 : 1;
else else
$columns=0; $columns = 0;
return $columns; return $columns;
} }
...@@ -875,7 +879,7 @@ ...@@ -875,7 +879,7 @@
if (@$form['boxed']) if (@$form['boxed'])
$this->output('<div class="qa-form-table-boxed">'); $this->output('<div class="qa-form-table-boxed">');
$columns=$this->form_columns($form); $columns = $this->form_columns($form);
if ($columns) if ($columns)
$this->output('<table class="qa-form-'.$form['style'].'-table">'); $this->output('<table class="qa-form-'.$form['style'].'-table">');
...@@ -895,7 +899,7 @@ ...@@ -895,7 +899,7 @@
public function form_ok($form, $columns) public function form_ok($form, $columns)
{ {
if (!empty($form['ok'])) if (!empty($form['ok'])) {
$this->output( $this->output(
'<tr>', '<tr>',
'<td colspan="'.$columns.'" class="qa-form-'.$form['style'].'-ok">', '<td colspan="'.$columns.'" class="qa-form-'.$form['style'].'-ok">',
...@@ -903,6 +907,7 @@ ...@@ -903,6 +907,7 @@
'</td>', '</td>',
'</tr>' '</tr>'
); );
}
} }
public function form_reorder_fields(&$form, $keys, $beforekey=null, $reorderrelative=true) public function form_reorder_fields(&$form, $keys, $beforekey=null, $reorderrelative=true)
...@@ -923,7 +928,7 @@ ...@@ -923,7 +928,7 @@
foreach ($form['fields'] as $key => $field) { foreach ($form['fields'] as $key => $field) {
$this->set_context('field_key', $key); $this->set_context('field_key', $key);
if (@$field['type']=='blank') if (@$field['type'] == 'blank')
$this->form_spacer($form, $columns); $this->form_spacer($form, $columns);
else else
$this->form_field_rows($form, $columns, $field); $this->form_field_rows($form, $columns, $field);
...@@ -935,56 +940,59 @@ ...@@ -935,56 +940,59 @@
public function form_field_rows($form, $columns, $field) public function form_field_rows($form, $columns, $field)
{ {
$style=$form['style']; $style = $form['style'];
if (isset($field['style'])) { // field has different style to most of form if (isset($field['style'])) { // field has different style to most of form
$style=$field['style']; $style = $field['style'];
$colspan=$columns; $colspan = $columns;
$columns=($style=='wide') ? 3 : 1; $columns = ($style == 'wide') ? 3 : 1;
} else }
$colspan=null; else
$colspan = null;
$prefixed=((@$field['type']=='checkbox') && ($columns==1) && !empty($field['label']));
$suffixed=(((@$field['type']=='select') || (@$field['type']=='number')) && ($columns==1) && !empty($field['label'])) && (!@$field['loose']); $prefixed = (@$field['type'] == 'checkbox') && ($columns == 1) && !empty($field['label']);
$skipdata=@$field['tight']; $suffixed = (@$field['type'] == 'select' || @$field['type'] == 'number') && $columns == 1 && !empty($field['label']) && !@$field['loose'];
$tworows=($columns==1) && (!empty($field['label'])) && (!$skipdata) && $skipdata = @$field['tight'];
$tworows = ($columns == 1) && (!empty($field['label'])) && (!$skipdata) &&
( (!($prefixed||$suffixed)) || (!empty($field['error'])) || (!empty($field['note'])) ); ( (!($prefixed||$suffixed)) || (!empty($field['error'])) || (!empty($field['note'])) );
if (isset($field['id'])) if (isset($field['id'])) {
if ($columns == 1) if ($columns == 1)
$this->output('<tbody id="'.$field['id'].'">', '<tr>'); $this->output('<tbody id="'.$field['id'].'">', '<tr>');
else else
$this->output('<tr id="'.$field['id'].'">'); $this->output('<tr id="'.$field['id'].'">');
}
else else
$this->output('<tr>'); $this->output('<tr>');
if (($columns>1) || !empty($field['label'])) if ($columns > 1 || !empty($field['label']))
$this->form_label($field, $style, $columns, $prefixed, $suffixed, $colspan); $this->form_label($field, $style, $columns, $prefixed, $suffixed, $colspan);
if ($tworows) if ($tworows) {
$this->output( $this->output(
'</tr>', '</tr>',
'<tr>' '<tr>'
); );
}
if (!$skipdata) if (!$skipdata)
$this->form_data($field, $style, $columns, !($prefixed||$suffixed), $colspan); $this->form_data($field, $style, $columns, !($prefixed||$suffixed), $colspan);
$this->output('</tr>'); $this->output('</tr>');
if (($columns==1) && isset($field['id'])) if ($columns == 1 && isset($field['id']))
$this->output('</tbody>'); $this->output('</tbody>');
} }
public function form_label($field, $style, $columns, $prefixed, $suffixed, $colspan) public function form_label($field, $style, $columns, $prefixed, $suffixed, $colspan)
{ {
$extratags=''; $extratags = '';
if ( ($columns>1) && ((@$field['type']=='select-radio') || (@$field['rows']>1)) ) if ($columns > 1 && (@$field['type'] == 'select-radio' || @$field['rows'] > 1))
$extratags.=' style="vertical-align:top;"'; $extratags .= ' style="vertical-align:top;"';
if (isset($colspan)) if (isset($colspan))
$extratags.=' colspan="'.$colspan.'"'; $extratags .= ' colspan="'.$colspan.'"';
$this->output('<td class="qa-form-'.$style.'-label"'.$extratags.'>'); $this->output('<td class="qa-form-'.$style.'-label"'.$extratags.'>');
...@@ -1021,8 +1029,8 @@ ...@@ -1021,8 +1029,8 @@
$this->form_note($field, $style, $columns); $this->form_note($field, $style, $columns);
$this->form_error($field, $style, $columns); $this->form_error($field, $style, $columns);
}
} elseif (!empty($field['note'])) elseif (!empty($field['note']))
$this->form_note($field, $style, $columns); $this->form_note($field, $style, $columns);
$this->output('</td>'); $this->output('</td>');
...@@ -1069,7 +1077,7 @@ ...@@ -1069,7 +1077,7 @@
break; break;
default: default:
if ((@$field['type']=='textarea') || (@$field['rows']>1)) if (@$field['type'] == 'textarea' || @$field['rows'] > 1)
$this->form_text_multi_row($field, $style); $this->form_text_multi_row($field, $style);
else else
$this->form_text_single_row($field, $style); $this->form_text_single_row($field, $style);
...@@ -1096,13 +1104,14 @@ ...@@ -1096,13 +1104,14 @@
public function form_buttons($form, $columns) public function form_buttons($form, $columns)
{ {
if (!empty($form['buttons'])) { if (!empty($form['buttons'])) {
$style=@$form['style']; $style = @$form['style'];
if ($columns) if ($columns) {
$this->output( $this->output(
'<tr>', '<tr>',
'<td colspan="'.$columns.'" class="qa-form-'.$style.'-buttons">' '<td colspan="'.$columns.'" class="qa-form-'.$style.'-buttons">'
); );
}
foreach ($form['buttons'] as $key => $button) { foreach ($form['buttons'] as $key => $button) {
$this->set_context('button_key', $key); $this->set_context('button_key', $key);
...@@ -1117,17 +1126,18 @@ ...@@ -1117,17 +1126,18 @@
$this->clear_context('button_key'); $this->clear_context('button_key');
if ($columns) if ($columns) {
$this->output( $this->output(
'</td>', '</td>',
'</tr>' '</tr>'
); );
}
} }
} }
public function form_button_data($button, $key, $style) public function form_button_data($button, $key, $style)
{ {
$baseclass='qa-form-'.$style.'-button qa-form-'.$style.'-button-'.$key; $baseclass = 'qa-form-'.$style.'-button qa-form-'.$style.'-button-'.$key;
$this->output('<input'.rtrim(' '.@$button['tags']).' value="'.@$button['label'].'" title="'.@$button['popup'].'" type="submit"'. $this->output('<input'.rtrim(' '.@$button['tags']).' value="'.@$button['label'].'" title="'.@$button['popup'].'" type="submit"'.
(isset($style) ? (' class="'.$baseclass.'"') : '').'/>'); (isset($style) ? (' class="'.$baseclass.'"') : '').'/>');
...@@ -1135,13 +1145,14 @@ ...@@ -1135,13 +1145,14 @@
public function form_button_note($button, $style) public function form_button_note($button, $style)
{ {
if (!empty($button['note'])) if (!empty($button['note'])) {
$this->output( $this->output(
'<span class="qa-form-'.$style.'-note">', '<span class="qa-form-'.$style.'-note">',
$button['note'], $button['note'],
'</span>', '</span>',
'<br/>' '<br/>'
); );
}
} }
public function form_button_spacer($style) public function form_button_spacer($style)
...@@ -1156,9 +1167,10 @@ ...@@ -1156,9 +1167,10 @@
public function form_hidden_elements($hidden) public function form_hidden_elements($hidden)
{ {
if (!empty($hidden)) if (!empty($hidden)) {
foreach ($hidden as $name => $value) foreach ($hidden as $name => $value)
$this->output('<input type="hidden" name="'.$name.'" value="'.$value.'"/>'); $this->output('<input type="hidden" name="'.$name.'" value="'.$value.'"/>');
}
} }
public function form_prefix($field, $style) public function form_prefix($field, $style)
...@@ -1198,20 +1210,20 @@ ...@@ -1198,20 +1210,20 @@
$this->output('<select '.@$field['tags'].' class="qa-form-'.$style.'-select">'); $this->output('<select '.@$field['tags'].' class="qa-form-'.$style.'-select">');
foreach ($field['options'] as $tag => $value) foreach ($field['options'] as $tag => $value)
$this->output('<option value="'.$tag.'"'.(($value==@$field['value']) ? ' selected' : '').'>'.$value.'</option>'); $this->output('<option value="'.$tag.'"'.(($value == @$field['value']) ? ' selected' : '').'>'.$value.'</option>');
$this->output('</select>'); $this->output('</select>');
} }
public function form_select_radio($field, $style) public function form_select_radio($field, $style)
{ {
$radios=0; $radios = 0;
foreach ($field['options'] as $tag => $value) { foreach ($field['options'] as $tag => $value) {
if ($radios++) if ($radios++)
$this->output('<br/>'); $this->output('<br/>');
$this->output('<input '.@$field['tags'].' type="radio" value="'.$tag.'"'.(($value==@$field['value']) ? ' checked' : '').' class="qa-form-'.$style.'-radio"/> '.$value); $this->output('<input '.@$field['tags'].' type="radio" value="'.$tag.'"'.(($value == @$field['value']) ? ' checked' : '').' class="qa-form-'.$style.'-radio"/> '.$value);
} }
} }
...@@ -1232,14 +1244,14 @@ ...@@ -1232,14 +1244,14 @@
public function form_error($field, $style, $columns) public function form_error($field, $style, $columns)
{ {
$tag=($columns>1) ? 'span' : 'div'; $tag = ($columns > 1) ? 'span' : 'div';
$this->output('<'.$tag.' class="qa-form-'.$style.'-error">'.$field['error'].'</'.$tag.'>'); $this->output('<'.$tag.' class="qa-form-'.$style.'-error">'.$field['error'].'</'.$tag.'>');
} }
public function form_note($field, $style, $columns) public function form_note($field, $style, $columns)
{ {
$tag=($columns>1) ? 'span' : 'div'; $tag = ($columns > 1) ? 'span' : 'div';
$this->output('<'.$tag.' class="qa-form-'.$style.'-note">'.@$field['note'].'</'.$tag.'>'); $this->output('<'.$tag.' class="qa-form-'.$style.'-note">'.@$field['note'].'</'.$tag.'>');
} }
...@@ -1359,14 +1371,15 @@ ...@@ -1359,14 +1371,15 @@
public function list_vote_disabled($items) public function list_vote_disabled($items)
{ {
$disabled=false; $disabled = false;
if (count($items)) { if (count($items)) {
$disabled=true; $disabled = true;
foreach ($items as $item) foreach ($items as $item) {
if (@$item['vote_on_page']!='disabled') if (@$item['vote_on_page'] != 'disabled')
$disabled=false; $disabled = false;
}
} }
return $disabled; return $disabled;
...@@ -1490,7 +1503,7 @@ ...@@ -1490,7 +1503,7 @@
public function voting($post) public function voting($post)
{ {
if (isset($post['vote_view'])) { if (isset($post['vote_view'])) {
$this->output('<div class="qa-voting '.(($post['vote_view']=='updown') ? 'qa-voting-updown' : 'qa-voting-net').'" '.@$post['vote_tags'].'>'); $this->output('<div class="qa-voting '.(($post['vote_view'] == 'updown') ? 'qa-voting-updown' : 'qa-voting-net').'" '.@$post['vote_tags'].'>');
$this->voting_inner_html($post); $this->voting_inner_html($post);
$this->output('</div>'); $this->output('</div>');
} }
...@@ -1505,7 +1518,7 @@ ...@@ -1505,7 +1518,7 @@
public function vote_buttons($post) public function vote_buttons($post)
{ {
$this->output('<div class="qa-vote-buttons '.(($post['vote_view']=='updown') ? 'qa-vote-buttons-updown' : 'qa-vote-buttons-net').'">'); $this->output('<div class="qa-vote-buttons '.(($post['vote_view'] == 'updown') ? 'qa-vote-buttons-updown' : 'qa-vote-buttons-net').'">');
switch (@$post['vote_state']) switch (@$post['vote_state'])
{ {
...@@ -1549,13 +1562,14 @@ ...@@ -1549,13 +1562,14 @@
// You can also use $post['upvotes_raw'], $post['downvotes_raw'], $post['netvotes_raw'] to get // You can also use $post['upvotes_raw'], $post['downvotes_raw'], $post['netvotes_raw'] to get
// raw integer vote counts, for graphing or showing in other non-textual ways // raw integer vote counts, for graphing or showing in other non-textual ways
$this->output('<div class="qa-vote-count '.(($post['vote_view']=='updown') ? 'qa-vote-count-updown' : 'qa-vote-count-net').'"'.@$post['vote_count_tags'].'>'); $this->output('<div class="qa-vote-count '.(($post['vote_view'] == 'updown') ? 'qa-vote-count-updown' : 'qa-vote-count-net').'"'.@$post['vote_count_tags'].'>');
if ($post['vote_view']=='updown') { if ($post['vote_view'] == 'updown') {
$this->output_split($post['upvotes_view'], 'qa-upvote-count'); $this->output_split($post['upvotes_view'], 'qa-upvote-count');
$this->output_split($post['downvotes_view'], 'qa-downvote-count'); $this->output_split($post['downvotes_view'], 'qa-downvote-count');
} else }
else
$this->output_split($post['netvotes_view'], 'qa-netvote-count'); $this->output_split($post['netvotes_view'], 'qa-netvote-count');
$this->output('</div>'); $this->output('</div>');
...@@ -1652,9 +1666,9 @@ ...@@ -1652,9 +1666,9 @@
if (isset($prefix)) if (isset($prefix))
$this->output($prefix); $this->output($prefix);
$order=explode('^', @$post['meta_order']); $order = explode('^', @$post['meta_order']);
foreach ($order as $element) foreach ($order as $element) {
switch ($element) { switch ($element) {
case 'what': case 'what':
$this->post_meta_what($post, $class); $this->post_meta_what($post, $class);
...@@ -1672,13 +1686,14 @@ ...@@ -1672,13 +1686,14 @@
$this->post_meta_who($post, $class); $this->post_meta_who($post, $class);
break; break;
} }
}
$this->post_meta_flags($post, $class); $this->post_meta_flags($post, $class);
if (!empty($post['what_2'])) { if (!empty($post['what_2'])) {
$this->output($separator); $this->output($separator);
foreach ($order as $element) foreach ($order as $element) {
switch ($element) { switch ($element) {
case 'what': case 'what':
$this->output('<span class="'.$class.'-what">'.$post['what_2'].'</span>'); $this->output('<span class="'.$class.'-what">'.$post['what_2'].'</span>');
...@@ -1692,6 +1707,7 @@ ...@@ -1692,6 +1707,7 @@
$this->output_split(@$post['who_2'], $class.'-who'); $this->output_split(@$post['who_2'], $class.'-who');
break; break;
} }
}
} }
$this->output('</span>'); $this->output('</span>');
...@@ -1700,9 +1716,9 @@ ...@@ -1700,9 +1716,9 @@
public function post_meta_what($post, $class) public function post_meta_what($post, $class)
{ {
if (isset($post['what'])) { if (isset($post['what'])) {
$classes=$class.'-what'; $classes = $class.'-what';
if (@$post['what_your']) if (@$post['what_your'])
$classes.=' '.$class.'-what-your'; $classes .= ' '.$class.'-what-your';
if (isset($post['what_url'])) if (isset($post['what_url']))
$this->output('<a href="'.$post['what_url'].'" class="'.$classes.'">'.$post['what'].'</a>'); $this->output('<a href="'.$post['what_url'].'" class="'.$classes.'">'.$post['what'].'</a>');
...@@ -1738,8 +1754,8 @@ ...@@ -1738,8 +1754,8 @@
// You can also use $post['level'] to get the author's privilege level (as a string) // You can also use $post['level'] to get the author's privilege level (as a string)
if (isset($post['who']['points'])) { if (isset($post['who']['points'])) {
$post['who']['points']['prefix']='('.$post['who']['points']['prefix']; $post['who']['points']['prefix'] = '('.$post['who']['points']['prefix'];
$post['who']['points']['suffix'].=')'; $post['who']['points']['suffix'] .= ')';
$this->output_split($post['who']['points'], $class.'-who-points'); $this->output_split($post['who']['points'], $class.'-who-points');
} }
...@@ -1781,7 +1797,7 @@ ...@@ -1781,7 +1797,7 @@
public function page_links() public function page_links()
{ {
$page_links=@$this->content['page_links']; $page_links = @$this->content['page_links'];
if (!empty($page_links)) { if (!empty($page_links)) {
$this->output('<div class="qa-page-links">'); $this->output('<div class="qa-page-links">');
...@@ -1805,7 +1821,7 @@ ...@@ -1805,7 +1821,7 @@
if (!empty($page_items)) { if (!empty($page_items)) {
$this->output('<ul class="qa-page-links-list">'); $this->output('<ul class="qa-page-links-list">');
$index=0; $index = 0;
foreach ($page_items as $page_link) { foreach ($page_items as $page_link) {
$this->set_context('page_index', $index++); $this->set_context('page_index', $index++);
...@@ -1830,8 +1846,8 @@ ...@@ -1830,8 +1846,8 @@
public function page_link_content($page_link) public function page_link_content($page_link)
{ {
$label=@$page_link['label']; $label = @$page_link['label'];
$url=@$page_link['url']; $url = @$page_link['url'];
switch ($page_link['type']) { switch ($page_link['type']) {
case 'this': case 'this':
...@@ -1866,7 +1882,7 @@ ...@@ -1866,7 +1882,7 @@
public function suggest_next() public function suggest_next()
{ {
$suggest=@$this->content['suggest_next']; $suggest = @$this->content['suggest_next'];
if (!empty($suggest)) { if (!empty($suggest)) {
$this->output('<div class="qa-suggest-next">'); $this->output('<div class="qa-suggest-next">');
...@@ -1957,7 +1973,7 @@ ...@@ -1957,7 +1973,7 @@
public function q_view_closed($q_view) public function q_view_closed($q_view)
{ {
if (!empty($q_view['closed'])) { if (!empty($q_view['closed'])) {
$haslink=isset($q_view['closed']['url']); $haslink = isset($q_view['closed']['url']);
$this->output( $this->output(
'<div class="qa-q-view-closed">', '<div class="qa-q-view-closed">',
...@@ -1972,7 +1988,7 @@ ...@@ -1972,7 +1988,7 @@
public function q_view_extra($q_view) public function q_view_extra($q_view)
{ {
if (!empty($q_view['extra'])) if (!empty($q_view['extra'])) {
$this->output( $this->output(
'<div class="qa-q-view-extra">', '<div class="qa-q-view-extra">',
$q_view['extra']['label'], $q_view['extra']['label'],
...@@ -1981,6 +1997,7 @@ ...@@ -1981,6 +1997,7 @@
'</span>', '</span>',
'</div>' '</div>'
); );
}
} }
public function q_view_buttons($q_view) public function q_view_buttons($q_view)
...@@ -2030,7 +2047,7 @@ ...@@ -2030,7 +2047,7 @@
public function a_list_item($a_item) public function a_list_item($a_item)
{ {
$extraclass=@$a_item['classes'].($a_item['hidden'] ? ' qa-a-list-item-hidden' : ($a_item['selected'] ? ' qa-a-list-item-selected' : '')); $extraclass = @$a_item['classes'].($a_item['hidden'] ? ' qa-a-list-item-hidden' : ($a_item['selected'] ? ' qa-a-list-item-selected' : ''));
$this->output('<div class="qa-a-list-item '.$extraclass.'" '.@$a_item['tags'].'>'); $this->output('<div class="qa-a-list-item '.$extraclass.'" '.@$a_item['tags'].'>');
...@@ -2135,7 +2152,7 @@ ...@@ -2135,7 +2152,7 @@
public function c_list_item($c_item) public function c_list_item($c_item)
{ {
$extraclass=@$c_item['classes'].(@$c_item['hidden'] ? ' qa-c-item-hidden' : ''); $extraclass = @$c_item['classes'].(@$c_item['hidden'] ? ' qa-c-item-hidden' : '');
$this->output('<div class="qa-c-list-item '.$extraclass.'" '.@$c_item['tags'].'>'); $this->output('<div class="qa-c-list-item '.$extraclass.'" '.@$c_item['tags'].'>');
......
<?php <?php
/** /**
* PHPMailer SPL autoloader. * PHPMailer SPL autoloader.
* PHP Version 5.0.0 * PHP Version 5.0.0
* @package PHPMailer * @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ * @link https://github.com/PHPMailer/PHPMailer/
* @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk> * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com> * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder) * @author Brent R. Matzelle (original founder)
* @copyright 2013 Marcus Bointon * @copyright 2013 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski * @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost * @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT * @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. * FITNESS FOR A PARTICULAR PURPOSE.
*/ */
/** /**
* PHPMailer SPL autoloader. * PHPMailer SPL autoloader.
* @param string $classname The name of the class to load * @param string $classname The name of the class to load
*/ */
function PHPMailerAutoload($classname) function PHPMailerAutoload($classname)
{ {
//Can't use __DIR__ as it's only in PHP 5.3+ //Can't use __DIR__ as it's only in PHP 5.3+
$filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php'; $filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
if (is_readable($filename)) { if (is_readable($filename)) {
require $filename; require $filename;
} }
} }
if (version_compare(PHP_VERSION, '5.1.2', '>=')) { if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
//SPL autoloading was introduced in PHP 5.1.2 //SPL autoloading was introduced in PHP 5.1.2
if (version_compare(PHP_VERSION, '5.3.0', '>=')) { if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
spl_autoload_register('PHPMailerAutoload', true, true); spl_autoload_register('PHPMailerAutoload', true, true);
} else { } else {
spl_autoload_register('PHPMailerAutoload'); spl_autoload_register('PHPMailerAutoload');
} }
} else { } else {
/** /**
* Fall back to traditional autoload for old PHP versions * Fall back to traditional autoload for old PHP versions
* @param string $classname The name of the class to load * @param string $classname The name of the class to load
*/ */
function __autoload($classname) function __autoload($classname)
{ {
PHPMailerAutoload($classname); PHPMailerAutoload($classname);
} }
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
<?php <?php
/** /**
* PHPMailer RFC821 SMTP email transport class. * PHPMailer RFC821 SMTP email transport class.
* Version 5.2.7 * Version 5.2.7
* PHP version 5.0.0 * PHP version 5.0.0
* @category PHP * @category PHP
* @package PHPMailer * @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ * @link https://github.com/PHPMailer/PHPMailer/
* @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk> * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com> * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @copyright 2013 Marcus Bointon * @copyright 2013 Marcus Bointon
* @copyright 2004 - 2008 Andy Prevost * @copyright 2004 - 2008 Andy Prevost
* @copyright 2010 - 2012 Jim Jagielski * @copyright 2010 - 2012 Jim Jagielski
* @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
*/ */
/** /**
* PHPMailer RFC821 SMTP email transport class. * PHPMailer RFC821 SMTP email transport class.
* *
* Implements RFC 821 SMTP commands * Implements RFC 821 SMTP commands
* and provides some utility methods for sending mail to an SMTP server. * and provides some utility methods for sending mail to an SMTP server.
* *
* PHP Version 5.0.0 * PHP Version 5.0.0
* *
* @category PHP * @category PHP
* @package PHPMailer * @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/blob/master/class.smtp.php * @link https://github.com/PHPMailer/PHPMailer/blob/master/class.smtp.php
* @author Chris Ryan <unknown@example.com> * @author Chris Ryan <unknown@example.com>
* @author Marcus Bointon <phpmailer@synchromedia.co.uk> * @author Marcus Bointon <phpmailer@synchromedia.co.uk>
* @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
*/ */
class SMTP class SMTP
{ {
/** /**
* The PHPMailer SMTP Version number. * The PHPMailer SMTP Version number.
*/ */
const VERSION = '5.2.7'; const VERSION = '5.2.7';
/** /**
* SMTP line break constant. * SMTP line break constant.
*/ */
const CRLF = "\r\n"; const CRLF = "\r\n";
/** /**
* The SMTP port to use if one is not specified. * The SMTP port to use if one is not specified.
*/ */
const DEFAULT_SMTP_PORT = 25; const DEFAULT_SMTP_PORT = 25;
/** /**
* The maximum line length allowed by RFC 2822 section 2.1.1 * The maximum line length allowed by RFC 2822 section 2.1.1
*/ */
const MAX_LINE_LENGTH = 998; const MAX_LINE_LENGTH = 998;
/** /**
* The PHPMailer SMTP Version number. * The PHPMailer SMTP Version number.
* @type string * @type string
* @deprecated This should be a constant * @deprecated This should be a constant
* @see SMTP::VERSION * @see SMTP::VERSION
*/ */
public $Version = '5.2.7'; public $Version = '5.2.7';
/** /**
* SMTP server port number. * SMTP server port number.
* @type int * @type int
* @deprecated This is only ever ued as default value, so should be a constant * @deprecated This is only ever ued as default value, so should be a constant
* @see SMTP::DEFAULT_SMTP_PORT * @see SMTP::DEFAULT_SMTP_PORT
*/ */
public $SMTP_PORT = 25; public $SMTP_PORT = 25;
/** /**
* SMTP reply line ending * SMTP reply line ending
* @type string * @type string
* @deprecated Use the class constant instead * @deprecated Use the class constant instead
* @see SMTP::CRLF * @see SMTP::CRLF
*/ */
public $CRLF = "\r\n"; public $CRLF = "\r\n";
/** /**
* Debug output level. * Debug output level.
* Options: * Options:
* 0: no output * 0: no output
* 1: commands * 1: commands
* 2: data and commands * 2: data and commands
* 3: as 2 plus connection status * 3: as 2 plus connection status
* 4: low level data output * 4: low level data output
* @type int * @type int
*/ */
public $do_debug = 0; public $do_debug = 0;
/** /**
* The function/method to use for debugging output. * The function/method to use for debugging output.
* Options: 'echo', 'html' or 'error_log' * Options: 'echo', 'html' or 'error_log'
* @type string * @type string
*/ */
public $Debugoutput = 'echo'; public $Debugoutput = 'echo';
/** /**
* Whether to use VERP. * Whether to use VERP.
* @type bool * @type bool
*/ */
public $do_verp = false; public $do_verp = false;
/** /**
* The timeout value for connection, in seconds. * The timeout value for connection, in seconds.
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
* @type int * @type int
*/ */
public $Timeout = 300; public $Timeout = 300;
/** /**
* The SMTP timelimit value for reads, in seconds. * The SMTP timelimit value for reads, in seconds.
* @type int * @type int
*/ */
public $Timelimit = 30; public $Timelimit = 30;
/** /**
* The socket for the server connection. * The socket for the server connection.
* @type resource * @type resource
*/ */
protected $smtp_conn; protected $smtp_conn;
/** /**
* Error message, if any, for the last call. * Error message, if any, for the last call.
* @type string * @type string
*/ */
protected $error = ''; protected $error = '';
/** /**
* The reply the server sent to us for HELO. * The reply the server sent to us for HELO.
* @type string * @type string
*/ */
protected $helo_rply = ''; protected $helo_rply = '';
/** /**
* The most recent reply received from the server. * The most recent reply received from the server.
* @type string * @type string
*/ */
protected $last_reply = ''; protected $last_reply = '';
/** /**
* Constructor. * Constructor.
* @access public * @access public
*/ */
public function __construct() public function __construct()
{ {
$this->smtp_conn = 0; $this->smtp_conn = 0;
$this->error = null; $this->error = null;
$this->helo_rply = null; $this->helo_rply = null;
$this->do_debug = 0; $this->do_debug = 0;
} }
/** /**
* Output debugging info via a user-selected method. * Output debugging info via a user-selected method.
* @param string $str Debug string to output * @param string $str Debug string to output
* @return void * @return void
*/ */
protected function edebug($str) protected function edebug($str)
{ {
switch ($this->Debugoutput) { switch ($this->Debugoutput) {
case 'error_log': case 'error_log':
//Don't output, just log //Don't output, just log
error_log($str); error_log($str);
break; break;
case 'html': case 'html':
//Cleans up output a bit for a better looking, HTML-safe output //Cleans up output a bit for a better looking, HTML-safe output
echo htmlentities( echo htmlentities(
preg_replace('/[\r\n]+/', '', $str), preg_replace('/[\r\n]+/', '', $str),
ENT_QUOTES, ENT_QUOTES,
'UTF-8' 'UTF-8'
) )
. "<br>\n"; . "<br>\n";
break; break;
case 'echo': case 'echo':
default: default:
echo gmdate('Y-m-d H:i:s')."\t".trim($str)."\n"; echo gmdate('Y-m-d H:i:s')."\t".trim($str)."\n";
} }
} }
/** /**
* Connect to an SMTP server. * Connect to an SMTP server.
* @param string $host SMTP server IP or host name * @param string $host SMTP server IP or host name
* @param int $port The port number to connect to * @param int $port The port number to connect to
* @param int $timeout How long to wait for the connection to open * @param int $timeout How long to wait for the connection to open
* @param array $options An array of options for stream_context_create() * @param array $options An array of options for stream_context_create()
* @access public * @access public
* @return bool * @return bool
*/ */
public function connect($host, $port = null, $timeout = 30, $options = array()) public function connect($host, $port = null, $timeout = 30, $options = array())
{ {
// Clear errors to avoid confusion // Clear errors to avoid confusion
$this->error = null; $this->error = null;
// Make sure we are __not__ connected // Make sure we are __not__ connected
if ($this->connected()) { if ($this->connected()) {
// Already connected, generate error // Already connected, generate error
$this->error = array('error' => 'Already connected to a server'); $this->error = array('error' => 'Already connected to a server');
return false; return false;
} }
if (empty($port)) { if (empty($port)) {
$port = self::DEFAULT_SMTP_PORT; $port = self::DEFAULT_SMTP_PORT;
} }
// Connect to the SMTP server // Connect to the SMTP server
if ($this->do_debug >= 3) { if ($this->do_debug >= 3) {
$this->edebug('Connection: opening'); $this->edebug('Connection: opening');
} }
$errno = 0; $errno = 0;
$errstr = ''; $errstr = '';
$socket_context = stream_context_create($options); $socket_context = stream_context_create($options);
//Suppress errors; connection failures are handled at a higher level //Suppress errors; connection failures are handled at a higher level
$this->smtp_conn = @stream_socket_client( $this->smtp_conn = @stream_socket_client(
$host . ":" . $port, $host . ":" . $port,
$errno, $errno,
$errstr, $errstr,
$timeout, $timeout,
STREAM_CLIENT_CONNECT, STREAM_CLIENT_CONNECT,
$socket_context $socket_context
); );
// Verify we connected properly // Verify we connected properly
if (empty($this->smtp_conn)) { if (empty($this->smtp_conn)) {
$this->error = array( $this->error = array(
'error' => 'Failed to connect to server', 'error' => 'Failed to connect to server',
'errno' => $errno, 'errno' => $errno,
'errstr' => $errstr 'errstr' => $errstr
); );
if ($this->do_debug >= 1) { if ($this->do_debug >= 1) {
$this->edebug( $this->edebug(
'SMTP ERROR: ' . $this->error['error'] 'SMTP ERROR: ' . $this->error['error']
. ": $errstr ($errno)" . ": $errstr ($errno)"
); );
} }
return false; return false;
} }
if ($this->do_debug >= 3) { if ($this->do_debug >= 3) {
$this->edebug('Connection: opened'); $this->edebug('Connection: opened');
} }
// SMTP server can take longer to respond, give longer timeout for first read // SMTP server can take longer to respond, give longer timeout for first read
// Windows does not have support for this timeout function // Windows does not have support for this timeout function
if (substr(PHP_OS, 0, 3) != 'WIN') { if (substr(PHP_OS, 0, 3) != 'WIN') {
$max = ini_get('max_execution_time'); $max = ini_get('max_execution_time');
if ($max != 0 && $timeout > $max) { // Don't bother if unlimited if ($max != 0 && $timeout > $max) { // Don't bother if unlimited
@set_time_limit($timeout); @set_time_limit($timeout);
} }
stream_set_timeout($this->smtp_conn, $timeout, 0); stream_set_timeout($this->smtp_conn, $timeout, 0);
} }
// Get any announcement // Get any announcement
$announce = $this->get_lines(); $announce = $this->get_lines();
if ($this->do_debug >= 2) { if ($this->do_debug >= 2) {
$this->edebug('SERVER -> CLIENT: ' . $announce); $this->edebug('SERVER -> CLIENT: ' . $announce);
} }
return true; return true;
} }
/** /**
* Initiate a TLS (encrypted) session. * Initiate a TLS (encrypted) session.
* @access public * @access public
* @return bool * @return bool
*/ */
public function startTLS() public function startTLS()
{ {
if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
return false; return false;
} }
// Begin encrypted connection // Begin encrypted connection
if (!stream_socket_enable_crypto( if (!stream_socket_enable_crypto(
$this->smtp_conn, $this->smtp_conn,
true, true,
STREAM_CRYPTO_METHOD_TLS_CLIENT STREAM_CRYPTO_METHOD_TLS_CLIENT
)) { )) {
return false; return false;
} }
return true; return true;
} }
/** /**
* Perform SMTP authentication. * Perform SMTP authentication.
* Must be run after hello(). * Must be run after hello().
* @see hello() * @see hello()
* @param string $username The user name * @param string $username The user name
* @param string $password The password * @param string $password The password
* @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5) * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5)
* @param string $realm The auth realm for NTLM * @param string $realm The auth realm for NTLM
* @param string $workstation The auth workstation for NTLM * @param string $workstation The auth workstation for NTLM
* @access public * @access public
* @return bool True if successfully authenticated. * @return bool True if successfully authenticated.
*/ */
public function authenticate( public function authenticate(
$username, $username,
$password, $password,
$authtype = 'LOGIN', $authtype = 'LOGIN',
$realm = '', $realm = '',
$workstation = '' $workstation = ''
) { ) {
if (empty($authtype)) { if (empty($authtype)) {
$authtype = 'LOGIN'; $authtype = 'LOGIN';
} }
switch ($authtype) { switch ($authtype) {
case 'PLAIN': case 'PLAIN':
// Start authentication // Start authentication
if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) { if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
return false; return false;
} }
// Send encoded username and password // Send encoded username and password
if (!$this->sendCommand( if (!$this->sendCommand(
'User & Password', 'User & Password',
base64_encode("\0" . $username . "\0" . $password), base64_encode("\0" . $username . "\0" . $password),
235 235
) )
) { ) {
return false; return false;
} }
break; break;
case 'LOGIN': case 'LOGIN':
// Start authentication // Start authentication
if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) { if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
return false; return false;
} }
if (!$this->sendCommand("Username", base64_encode($username), 334)) { if (!$this->sendCommand("Username", base64_encode($username), 334)) {
return false; return false;
} }
if (!$this->sendCommand("Password", base64_encode($password), 235)) { if (!$this->sendCommand("Password", base64_encode($password), 235)) {
return false; return false;
} }
break; break;
case 'NTLM': case 'NTLM':
/* /*
* ntlm_sasl_client.php * ntlm_sasl_client.php
* Bundled with Permission * Bundled with Permission
* *
* How to telnet in windows: * How to telnet in windows:
* http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx * http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
* PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication * PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
*/ */
require_once 'extras/ntlm_sasl_client.php'; require_once 'extras/ntlm_sasl_client.php';
$temp = new stdClass(); $temp = new stdClass();
$ntlm_client = new ntlm_sasl_client_class; $ntlm_client = new ntlm_sasl_client_class;
//Check that functions are available //Check that functions are available
if (!$ntlm_client->Initialize($temp)) { if (!$ntlm_client->Initialize($temp)) {
$this->error = array('error' => $temp->error); $this->error = array('error' => $temp->error);
if ($this->do_debug >= 1) { if ($this->do_debug >= 1) {
$this->edebug( $this->edebug(
'You need to enable some modules in your php.ini file: ' 'You need to enable some modules in your php.ini file: '
. $this->error['error'] . $this->error['error']
); );
} }
return false; return false;
} }
//msg1 //msg1
$msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1 $msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1
if (!$this->sendCommand( if (!$this->sendCommand(
'AUTH NTLM', 'AUTH NTLM',
'AUTH NTLM ' . base64_encode($msg1), 'AUTH NTLM ' . base64_encode($msg1),
334 334
) )
) { ) {
return false; return false;
} }
//Though 0 based, there is a white space after the 3 digit number //Though 0 based, there is a white space after the 3 digit number
//msg2 //msg2
$challenge = substr($this->last_reply, 3); $challenge = substr($this->last_reply, 3);
$challenge = base64_decode($challenge); $challenge = base64_decode($challenge);
$ntlm_res = $ntlm_client->NTLMResponse( $ntlm_res = $ntlm_client->NTLMResponse(
substr($challenge, 24, 8), substr($challenge, 24, 8),
$password $password
); );
//msg3 //msg3
$msg3 = $ntlm_client->TypeMsg3( $msg3 = $ntlm_client->TypeMsg3(
$ntlm_res, $ntlm_res,
$username, $username,
$realm, $realm,
$workstation $workstation
); );
// send encoded username // send encoded username
return $this->sendCommand('Username', base64_encode($msg3), 235); return $this->sendCommand('Username', base64_encode($msg3), 235);
break; break;
case 'CRAM-MD5': case 'CRAM-MD5':
// Start authentication // Start authentication
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) { if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
return false; return false;
} }
// Get the challenge // Get the challenge
$challenge = base64_decode(substr($this->last_reply, 4)); $challenge = base64_decode(substr($this->last_reply, 4));
// Build the response // Build the response
$response = $username . ' ' . $this->hmac($challenge, $password); $response = $username . ' ' . $this->hmac($challenge, $password);
// send encoded credentials // send encoded credentials
return $this->sendCommand('Username', base64_encode($response), 235); return $this->sendCommand('Username', base64_encode($response), 235);
break; break;
} }
return true; return true;
} }
/** /**
* Calculate an MD5 HMAC hash. * Calculate an MD5 HMAC hash.
* Works like hash_hmac('md5', $data, $key) * Works like hash_hmac('md5', $data, $key)
* in case that function is not available * in case that function is not available
* @param string $data The data to hash * @param string $data The data to hash
* @param string $key The key to hash with * @param string $key The key to hash with
* @access protected * @access protected
* @return string * @return string
*/ */
protected function hmac($data, $key) protected function hmac($data, $key)
{ {
if (function_exists('hash_hmac')) { if (function_exists('hash_hmac')) {
return hash_hmac('md5', $data, $key); return hash_hmac('md5', $data, $key);
} }
// The following borrowed from // The following borrowed from
// http://php.net/manual/en/function.mhash.php#27225 // http://php.net/manual/en/function.mhash.php#27225
// RFC 2104 HMAC implementation for php. // RFC 2104 HMAC implementation for php.
// Creates an md5 HMAC. // Creates an md5 HMAC.
// Eliminates the need to install mhash to compute a HMAC // Eliminates the need to install mhash to compute a HMAC
// Hacked by Lance Rushing // Hacked by Lance Rushing
$b = 64; // byte length for md5 $b = 64; // byte length for md5
if (strlen($key) > $b) { if (strlen($key) > $b) {
$key = pack('H*', md5($key)); $key = pack('H*', md5($key));
} }
$key = str_pad($key, $b, chr(0x00)); $key = str_pad($key, $b, chr(0x00));
$ipad = str_pad('', $b, chr(0x36)); $ipad = str_pad('', $b, chr(0x36));
$opad = str_pad('', $b, chr(0x5c)); $opad = str_pad('', $b, chr(0x5c));
$k_ipad = $key ^ $ipad; $k_ipad = $key ^ $ipad;
$k_opad = $key ^ $opad; $k_opad = $key ^ $opad;
return md5($k_opad . pack('H*', md5($k_ipad . $data))); return md5($k_opad . pack('H*', md5($k_ipad . $data)));
} }
/** /**
* Check connection state. * Check connection state.
* @access public * @access public
* @return bool True if connected. * @return bool True if connected.
*/ */
public function connected() public function connected()
{ {
if (!empty($this->smtp_conn)) { if (!empty($this->smtp_conn)) {
$sock_status = stream_get_meta_data($this->smtp_conn); $sock_status = stream_get_meta_data($this->smtp_conn);
if ($sock_status['eof']) { if ($sock_status['eof']) {
// the socket is valid but we are not connected // the socket is valid but we are not connected
if ($this->do_debug >= 1) { if ($this->do_debug >= 1) {
$this->edebug( $this->edebug(
'SMTP NOTICE: EOF caught while checking if connected' 'SMTP NOTICE: EOF caught while checking if connected'
); );
} }
$this->close(); $this->close();
return false; return false;
} }
return true; // everything looks good return true; // everything looks good
} }
return false; return false;
} }
/** /**
* Close the socket and clean up the state of the class. * Close the socket and clean up the state of the class.
* Don't use this function without first trying to use QUIT. * Don't use this function without first trying to use QUIT.
* @see quit() * @see quit()
* @access public * @access public
* @return void * @return void
*/ */
public function close() public function close()
{ {
$this->error = null; // so there is no confusion $this->error = null; // so there is no confusion
$this->helo_rply = null; $this->helo_rply = null;
if (!empty($this->smtp_conn)) { if (!empty($this->smtp_conn)) {
// close the connection and cleanup // close the connection and cleanup
fclose($this->smtp_conn); fclose($this->smtp_conn);
if ($this->do_debug >= 3) { if ($this->do_debug >= 3) {
$this->edebug('Connection: closed'); $this->edebug('Connection: closed');
} }
$this->smtp_conn = 0; $this->smtp_conn = 0;
} }
} }
/** /**
* Send an SMTP DATA command. * Send an SMTP DATA command.
* Issues a data command and sends the msg_data to the server, * Issues a data command and sends the msg_data to the server,
* finializing the mail transaction. $msg_data is the message * finializing the mail transaction. $msg_data is the message
* that is to be send with the headers. Each header needs to be * that is to be send with the headers. Each header needs to be
* on a single line followed by a <CRLF> with the message headers * on a single line followed by a <CRLF> with the message headers
* and the message body being separated by and additional <CRLF>. * and the message body being separated by and additional <CRLF>.
* Implements rfc 821: DATA <CRLF> * Implements rfc 821: DATA <CRLF>
* @param string $msg_data Message data to send * @param string $msg_data Message data to send
* @access public * @access public
* @return bool * @return bool
*/ */
public function data($msg_data) public function data($msg_data)
{ {
if (!$this->sendCommand('DATA', 'DATA', 354)) { if (!$this->sendCommand('DATA', 'DATA', 354)) {
return false; return false;
} }
/* The server is ready to accept data! /* The server is ready to accept data!
* According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF) * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF)
* so we will break the data up into lines by \r and/or \n then if needed we will break each of those into * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
* smaller lines to fit within the limit. * smaller lines to fit within the limit.
* We will also look for lines that start with a '.' and prepend an additional '.'. * We will also look for lines that start with a '.' and prepend an additional '.'.
* NOTE: this does not count towards line-length limit. * NOTE: this does not count towards line-length limit.
*/ */
// Normalize line breaks before exploding // Normalize line breaks before exploding
$lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data)); $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data));
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
* of the first line (':' separated) does not contain a space then it _should_ be a header and we will * of the first line (':' separated) does not contain a space then it _should_ be a header and we will
* process all lines before a blank line as headers. * process all lines before a blank line as headers.
*/ */
$field = substr($lines[0], 0, strpos($lines[0], ':')); $field = substr($lines[0], 0, strpos($lines[0], ':'));
$in_headers = false; $in_headers = false;
if (!empty($field) && strpos($field, ' ') === false) { if (!empty($field) && strpos($field, ' ') === false) {
$in_headers = true; $in_headers = true;
} }
foreach ($lines as $line) { foreach ($lines as $line) {
$lines_out = array(); $lines_out = array();
if ($in_headers and $line == '') { if ($in_headers and $line == '') {
$in_headers = false; $in_headers = false;
} }
// ok we need to break this line up into several smaller lines // ok we need to break this line up into several smaller lines
//This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len) //This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len)
while (isset($line[self::MAX_LINE_LENGTH])) { while (isset($line[self::MAX_LINE_LENGTH])) {
//Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
//so as to avoid breaking in the middle of a word //so as to avoid breaking in the middle of a word
$pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' '); $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
if (!$pos) { //Deliberately matches both false and 0 if (!$pos) { //Deliberately matches both false and 0
//No nice break found, add a hard break //No nice break found, add a hard break
$pos = self::MAX_LINE_LENGTH - 1; $pos = self::MAX_LINE_LENGTH - 1;
$lines_out[] = substr($line, 0, $pos); $lines_out[] = substr($line, 0, $pos);
$line = substr($line, $pos); $line = substr($line, $pos);
} else { } else {
//Break at the found point //Break at the found point
$lines_out[] = substr($line, 0, $pos); $lines_out[] = substr($line, 0, $pos);
//Move along by the amount we dealt with //Move along by the amount we dealt with
$line = substr($line, $pos + 1); $line = substr($line, $pos + 1);
} }
/* If processing headers add a LWSP-char to the front of new line /* If processing headers add a LWSP-char to the front of new line
* RFC822 section 3.1.1 * RFC822 section 3.1.1
*/ */
if ($in_headers) { if ($in_headers) {
$line = "\t" . $line; $line = "\t" . $line;
} }
} }
$lines_out[] = $line; $lines_out[] = $line;
// Send the lines to the server // Send the lines to the server
foreach ($lines_out as $line_out) { foreach ($lines_out as $line_out) {
//RFC2821 section 4.5.2 //RFC2821 section 4.5.2
if (!empty($line_out) and $line_out[0] == '.') { if (!empty($line_out) and $line_out[0] == '.') {
$line_out = '.' . $line_out; $line_out = '.' . $line_out;
} }
$this->client_send($line_out . self::CRLF); $this->client_send($line_out . self::CRLF);
} }
} }
// Message data has been sent, complete the command // Message data has been sent, complete the command
return $this->sendCommand('DATA END', '.', 250); return $this->sendCommand('DATA END', '.', 250);
} }
/** /**
* Send an SMTP HELO or EHLO command. * Send an SMTP HELO or EHLO command.
* Used to identify the sending server to the receiving server. * Used to identify the sending server to the receiving server.
* This makes sure that client and server are in a known state. * This makes sure that client and server are in a known state.
* Implements RFC 821: HELO <SP> <domain> <CRLF> * Implements RFC 821: HELO <SP> <domain> <CRLF>
* and RFC 2821 EHLO. * and RFC 2821 EHLO.
* @param string $host The host name or IP to connect to * @param string $host The host name or IP to connect to
* @access public * @access public
* @return bool * @return bool
*/ */
public function hello($host = '') public function hello($host = '')
{ {
// Try extended hello first (RFC 2821) // Try extended hello first (RFC 2821)
return (bool)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); return (bool)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host));
} }
/** /**
* Send an SMTP HELO or EHLO command. * Send an SMTP HELO or EHLO command.
* Low-level implementation used by hello() * Low-level implementation used by hello()
* @see hello() * @see hello()
* @param string $hello The HELO string * @param string $hello The HELO string
* @param string $host The hostname to say we are * @param string $host The hostname to say we are
* @access protected * @access protected
* @return bool * @return bool
*/ */
protected function sendHello($hello, $host) protected function sendHello($hello, $host)
{ {
$noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250); $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
$this->helo_rply = $this->last_reply; $this->helo_rply = $this->last_reply;
return $noerror; return $noerror;
} }
/** /**
* Send an SMTP MAIL command. * Send an SMTP MAIL command.
* Starts a mail transaction from the email address specified in * Starts a mail transaction from the email address specified in
* $from. Returns true if successful or false otherwise. If True * $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more recipient * the mail transaction is started and then one or more recipient
* commands may be called followed by a data command. * commands may be called followed by a data command.
* Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
* @param string $from Source address of this message * @param string $from Source address of this message
* @access public * @access public
* @return bool * @return bool
*/ */
public function mail($from) public function mail($from)
{ {
$useVerp = ($this->do_verp ? ' XVERP' : ''); $useVerp = ($this->do_verp ? ' XVERP' : '');
return $this->sendCommand( return $this->sendCommand(
'MAIL FROM', 'MAIL FROM',
'MAIL FROM:<' . $from . '>' . $useVerp, 'MAIL FROM:<' . $from . '>' . $useVerp,
250 250
); );
} }
/** /**
* Send an SMTP QUIT command. * Send an SMTP QUIT command.
* Closes the socket if there is no error or the $close_on_error argument is true. * Closes the socket if there is no error or the $close_on_error argument is true.
* Implements from rfc 821: QUIT <CRLF> * Implements from rfc 821: QUIT <CRLF>
* @param bool $close_on_error Should the connection close if an error occurs? * @param bool $close_on_error Should the connection close if an error occurs?
* @access public * @access public
* @return bool * @return bool
*/ */
public function quit($close_on_error = true) public function quit($close_on_error = true)
{ {
$noerror = $this->sendCommand('QUIT', 'QUIT', 221); $noerror = $this->sendCommand('QUIT', 'QUIT', 221);
$e = $this->error; //Save any error $e = $this->error; //Save any error
if ($noerror or $close_on_error) { if ($noerror or $close_on_error) {
$this->close(); $this->close();
$this->error = $e; //Restore any error from the quit command $this->error = $e; //Restore any error from the quit command
} }
return $noerror; return $noerror;
} }
/** /**
* Send an SMTP RCPT command. * Send an SMTP RCPT command.
* Sets the TO argument to $to. * Sets the TO argument to $to.
* Returns true if the recipient was accepted false if it was rejected. * Returns true if the recipient was accepted false if it was rejected.
* Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
* @param string $to The address the message is being sent to * @param string $to The address the message is being sent to
* @access public * @access public
* @return bool * @return bool
*/ */
public function recipient($to) public function recipient($to)
{ {
return $this->sendCommand( return $this->sendCommand(
'RCPT TO', 'RCPT TO',
'RCPT TO:<' . $to . '>', 'RCPT TO:<' . $to . '>',
array(250, 251) array(250, 251)
); );
} }
/** /**
* Send an SMTP RSET command. * Send an SMTP RSET command.
* Abort any transaction that is currently in progress. * Abort any transaction that is currently in progress.
* Implements rfc 821: RSET <CRLF> * Implements rfc 821: RSET <CRLF>
* @access public * @access public
* @return bool True on success. * @return bool True on success.
*/ */
public function reset() public function reset()
{ {
return $this->sendCommand('RSET', 'RSET', 250); return $this->sendCommand('RSET', 'RSET', 250);
} }
/** /**
* Send a command to an SMTP server and check its return code. * Send a command to an SMTP server and check its return code.
* @param string $command The command name - not sent to the server * @param string $command The command name - not sent to the server
* @param string $commandstring The actual command to send * @param string $commandstring The actual command to send
* @param int|array $expect One or more expected integer success codes * @param int|array $expect One or more expected integer success codes
* @access protected * @access protected
* @return bool True on success. * @return bool True on success.
*/ */
protected function sendCommand($command, $commandstring, $expect) protected function sendCommand($command, $commandstring, $expect)
{ {
if (!$this->connected()) { if (!$this->connected()) {
$this->error = array( $this->error = array(
'error' => "Called $command without being connected" 'error' => "Called $command without being connected"
); );
return false; return false;
} }
$this->client_send($commandstring . self::CRLF); $this->client_send($commandstring . self::CRLF);
$reply = $this->get_lines(); $reply = $this->get_lines();
$code = substr($reply, 0, 3); $code = substr($reply, 0, 3);
if ($this->do_debug >= 2) { if ($this->do_debug >= 2) {
$this->edebug('SERVER -> CLIENT: ' . $reply); $this->edebug('SERVER -> CLIENT: ' . $reply);
} }
if (!in_array($code, (array)$expect)) { if (!in_array($code, (array)$expect)) {
$this->last_reply = null; $this->last_reply = null;
$this->error = array( $this->error = array(
'error' => "$command command failed", 'error' => "$command command failed",
'smtp_code' => $code, 'smtp_code' => $code,
'detail' => substr($reply, 4) 'detail' => substr($reply, 4)
); );
if ($this->do_debug >= 1) { if ($this->do_debug >= 1) {
$this->edebug( $this->edebug(
'SMTP ERROR: ' . $this->error['error'] . ': ' . $reply 'SMTP ERROR: ' . $this->error['error'] . ': ' . $reply
); );
} }
return false; return false;
} }
$this->last_reply = $reply; $this->last_reply = $reply;
$this->error = null; $this->error = null;
return true; return true;
} }
/** /**
* Send an SMTP SAML command. * Send an SMTP SAML command.
* Starts a mail transaction from the email address specified in $from. * Starts a mail transaction from the email address specified in $from.
* Returns true if successful or false otherwise. If True * Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more recipient * the mail transaction is started and then one or more recipient
* commands may be called followed by a data command. This command * commands may be called followed by a data command. This command
* will send the message to the users terminal if they are logged * will send the message to the users terminal if they are logged
* in and send them an email. * in and send them an email.
* Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
* @param string $from The address the message is from * @param string $from The address the message is from
* @access public * @access public
* @return bool * @return bool
*/ */
public function sendAndMail($from) public function sendAndMail($from)
{ {
return $this->sendCommand('SAML', "SAML FROM:$from", 250); return $this->sendCommand('SAML', "SAML FROM:$from", 250);
} }
/** /**
* Send an SMTP VRFY command. * Send an SMTP VRFY command.
* @param string $name The name to verify * @param string $name The name to verify
* @access public * @access public
* @return bool * @return bool
*/ */
public function verify($name) public function verify($name)
{ {
return $this->sendCommand('VRFY', "VRFY $name", array(250, 251)); return $this->sendCommand('VRFY', "VRFY $name", array(250, 251));
} }
/** /**
* Send an SMTP NOOP command. * Send an SMTP NOOP command.
* Used to keep keep-alives alive, doesn't actually do anything * Used to keep keep-alives alive, doesn't actually do anything
* @access public * @access public
* @return bool * @return bool
*/ */
public function noop() public function noop()
{ {
return $this->sendCommand('NOOP', 'NOOP', 250); return $this->sendCommand('NOOP', 'NOOP', 250);
} }
/** /**
* Send an SMTP TURN command. * Send an SMTP TURN command.
* This is an optional command for SMTP that this class does not support. * This is an optional command for SMTP that this class does not support.
* This method is here to make the RFC821 Definition complete for this class * This method is here to make the RFC821 Definition complete for this class
* and _may_ be implemented in future * and _may_ be implemented in future
* Implements from rfc 821: TURN <CRLF> * Implements from rfc 821: TURN <CRLF>
* @access public * @access public
* @return bool * @return bool
*/ */
public function turn() public function turn()
{ {
$this->error = array( $this->error = array(
'error' => 'The SMTP TURN command is not implemented' 'error' => 'The SMTP TURN command is not implemented'
); );
if ($this->do_debug >= 1) { if ($this->do_debug >= 1) {
$this->edebug('SMTP NOTICE: ' . $this->error['error']); $this->edebug('SMTP NOTICE: ' . $this->error['error']);
} }
return false; return false;
} }
/** /**
* Send raw data to the server. * Send raw data to the server.
* @param string $data The data to send * @param string $data The data to send
* @access public * @access public
* @return int|bool The number of bytes sent to the server or false on error * @return int|bool The number of bytes sent to the server or false on error
*/ */
public function client_send($data) public function client_send($data)
{ {
if ($this->do_debug >= 1) { if ($this->do_debug >= 1) {
$this->edebug("CLIENT -> SERVER: $data"); $this->edebug("CLIENT -> SERVER: $data");
} }
return fwrite($this->smtp_conn, $data); return fwrite($this->smtp_conn, $data);
} }
/** /**
* Get the latest error. * Get the latest error.
* @access public * @access public
* @return array * @return array
*/ */
public function getError() public function getError()
{ {
return $this->error; return $this->error;
} }
/** /**
* Get the last reply from the server. * Get the last reply from the server.
* @access public * @access public
* @return string * @return string
*/ */
public function getLastReply() public function getLastReply()
{ {
return $this->last_reply; return $this->last_reply;
} }
/** /**
* Read the SMTP server's response. * Read the SMTP server's response.
* Either before eof or socket timeout occurs on the operation. * Either before eof or socket timeout occurs on the operation.
* With SMTP we can tell if we have more lines to read if the * With SMTP we can tell if we have more lines to read if the
* 4th character is '-' symbol. If it is a space then we don't * 4th character is '-' symbol. If it is a space then we don't
* need to read anything else. * need to read anything else.
* @access protected * @access protected
* @return string * @return string
*/ */
protected function get_lines() protected function get_lines()
{ {
// If the connection is bad, give up straight away // If the connection is bad, give up straight away
if (!is_resource($this->smtp_conn)) { if (!is_resource($this->smtp_conn)) {
return ''; return '';
} }
$data = ''; $data = '';
$endtime = 0; $endtime = 0;
stream_set_timeout($this->smtp_conn, $this->Timeout); stream_set_timeout($this->smtp_conn, $this->Timeout);
if ($this->Timelimit > 0) { if ($this->Timelimit > 0) {
$endtime = time() + $this->Timelimit; $endtime = time() + $this->Timelimit;
} }
while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
$str = @fgets($this->smtp_conn, 515); $str = @fgets($this->smtp_conn, 515);
if ($this->do_debug >= 4) { if ($this->do_debug >= 4) {
$this->edebug("SMTP -> get_lines(): \$data was \"$data\""); $this->edebug("SMTP -> get_lines(): \$data was \"$data\"");
$this->edebug("SMTP -> get_lines(): \$str is \"$str\""); $this->edebug("SMTP -> get_lines(): \$str is \"$str\"");
} }
$data .= $str; $data .= $str;
if ($this->do_debug >= 4) { if ($this->do_debug >= 4) {
$this->edebug("SMTP -> get_lines(): \$data is \"$data\""); $this->edebug("SMTP -> get_lines(): \$data is \"$data\"");
} }
// If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen
if ((isset($str[3]) and $str[3] == ' ')) { if ((isset($str[3]) and $str[3] == ' ')) {
break; break;
} }
// Timed-out? Log and break // Timed-out? Log and break
$info = stream_get_meta_data($this->smtp_conn); $info = stream_get_meta_data($this->smtp_conn);
if ($info['timed_out']) { if ($info['timed_out']) {
if ($this->do_debug >= 4) { if ($this->do_debug >= 4) {
$this->edebug( $this->edebug(
'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)' 'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)'
); );
} }
break; break;
} }
// Now check if reads took too long // Now check if reads took too long
if ($endtime and time() > $endtime) { if ($endtime and time() > $endtime) {
if ($this->do_debug >= 4) { if ($this->do_debug >= 4) {
$this->edebug( $this->edebug(
'SMTP -> get_lines(): timelimit reached ('. 'SMTP -> get_lines(): timelimit reached ('.
$this->Timelimit . ' sec)' $this->Timelimit . ' sec)'
); );
} }
break; break;
} }
} }
return $data; return $data;
} }
/** /**
* Enable or disable VERP address generation. * Enable or disable VERP address generation.
* @param bool $enabled * @param bool $enabled
*/ */
public function setVerp($enabled = false) public function setVerp($enabled = false)
{ {
$this->do_verp = $enabled; $this->do_verp = $enabled;
} }
/** /**
* Get VERP address generation mode. * Get VERP address generation mode.
* @return bool * @return bool
*/ */
public function getVerp() public function getVerp()
{ {
return $this->do_verp; return $this->do_verp;
} }
/** /**
* Set debug output method. * Set debug output method.
* @param string $method The function/method to use for debugging output. * @param string $method The function/method to use for debugging output.
*/ */
public function setDebugOutput($method = 'echo') public function setDebugOutput($method = 'echo')
{ {
$this->Debugoutput = $method; $this->Debugoutput = $method;
} }
/** /**
* Get debug output method. * Get debug output method.
* @return string * @return string
*/ */
public function getDebugOutput() public function getDebugOutput()
{ {
return $this->Debugoutput; return $this->Debugoutput;
} }
/** /**
* Set debug output level. * Set debug output level.
* @param int $level * @param int $level
*/ */
public function setDebugLevel($level = 0) public function setDebugLevel($level = 0)
{ {
$this->do_debug = $level; $this->do_debug = $level;
} }
/** /**
* Get debug output level. * Get debug output level.
* @return int * @return int
*/ */
public function getDebugLevel() public function getDebugLevel()
{ {
return $this->do_debug; return $this->do_debug;
} }
/** /**
* Set SMTP timeout. * Set SMTP timeout.
* @param int $timeout * @param int $timeout
*/ */
public function setTimeout($timeout = 0) public function setTimeout($timeout = 0)
{ {
$this->Timeout = $timeout; $this->Timeout = $timeout;
} }
/** /**
* Get SMTP timeout. * Get SMTP timeout.
* @return int * @return int
*/ */
public function getTimeout() public function getTimeout()
{ {
return $this->Timeout; return $this->Timeout;
} }
} }
<?php <?php
/* /*
htmLawed 1.1.17, 11 March 2014 htmLawed 1.1.17, 11 March 2014
Copyright Santosh Patnaik Copyright Santosh Patnaik
Dual licensed with LGPL 3 and GPL 2+ Dual licensed with LGPL 3 and GPL 2+
A PHP Labware internal utility; www.bioinformatics.org/phplabware/internal_utilities/htmLawed A PHP Labware internal utility; www.bioinformatics.org/phplabware/internal_utilities/htmLawed
See htmLawed_README.txt/htm See htmLawed_README.txt/htm
*/ */
function htmLawed($t, $C=1, $S=array()){ function htmLawed($t, $C=1, $S=array()){
$C = is_array($C) ? $C : array(); $C = is_array($C) ? $C : array();
if(!empty($C['valid_xhtml'])){ if(!empty($C['valid_xhtml'])){
$C['elements'] = empty($C['elements']) ? '*-center-dir-font-isindex-menu-s-strike-u' : $C['elements']; $C['elements'] = empty($C['elements']) ? '*-center-dir-font-isindex-menu-s-strike-u' : $C['elements'];
$C['make_tag_strict'] = isset($C['make_tag_strict']) ? $C['make_tag_strict'] : 2; $C['make_tag_strict'] = isset($C['make_tag_strict']) ? $C['make_tag_strict'] : 2;
$C['xml:lang'] = isset($C['xml:lang']) ? $C['xml:lang'] : 2; $C['xml:lang'] = isset($C['xml:lang']) ? $C['xml:lang'] : 2;
} }
// config eles // config eles
$e = array('a'=>1, 'abbr'=>1, 'acronym'=>1, 'address'=>1, 'applet'=>1, 'area'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'blockquote'=>1, 'br'=>1, 'button'=>1, 'caption'=>1, 'center'=>1, 'cite'=>1, 'code'=>1, 'col'=>1, 'colgroup'=>1, 'dd'=>1, 'del'=>1, 'dfn'=>1, 'dir'=>1, 'div'=>1, 'dl'=>1, 'dt'=>1, 'em'=>1, 'embed'=>1, 'fieldset'=>1, 'font'=>1, 'form'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'isindex'=>1, 'kbd'=>1, 'label'=>1, 'legend'=>1, 'li'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'object'=>1, 'ol'=>1, 'optgroup'=>1, 'option'=>1, 'p'=>1, 'param'=>1, 'pre'=>1, 'q'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'script'=>1, 'select'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'table'=>1, 'tbody'=>1, 'td'=>1, 'textarea'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1, 'tt'=>1, 'u'=>1, 'ul'=>1, 'var'=>1); // 86/deprecated+embed+ruby $e = array('a'=>1, 'abbr'=>1, 'acronym'=>1, 'address'=>1, 'applet'=>1, 'area'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'blockquote'=>1, 'br'=>1, 'button'=>1, 'caption'=>1, 'center'=>1, 'cite'=>1, 'code'=>1, 'col'=>1, 'colgroup'=>1, 'dd'=>1, 'del'=>1, 'dfn'=>1, 'dir'=>1, 'div'=>1, 'dl'=>1, 'dt'=>1, 'em'=>1, 'embed'=>1, 'fieldset'=>1, 'font'=>1, 'form'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'isindex'=>1, 'kbd'=>1, 'label'=>1, 'legend'=>1, 'li'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'object'=>1, 'ol'=>1, 'optgroup'=>1, 'option'=>1, 'p'=>1, 'param'=>1, 'pre'=>1, 'q'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'script'=>1, 'select'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'table'=>1, 'tbody'=>1, 'td'=>1, 'textarea'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1, 'tt'=>1, 'u'=>1, 'ul'=>1, 'var'=>1); // 86/deprecated+embed+ruby
if(!empty($C['safe'])){ if(!empty($C['safe'])){
unset($e['applet'], $e['embed'], $e['iframe'], $e['object'], $e['script']); unset($e['applet'], $e['embed'], $e['iframe'], $e['object'], $e['script']);
} }
$x = !empty($C['elements']) ? str_replace(array("\n", "\r", "\t", ' '), '', $C['elements']) : '*'; $x = !empty($C['elements']) ? str_replace(array("\n", "\r", "\t", ' '), '', $C['elements']) : '*';
if($x == '-*'){$e = array();} if($x == '-*'){$e = array();}
elseif(strpos($x, '*') === false){$e = array_flip(explode(',', $x));} elseif(strpos($x, '*') === false){$e = array_flip(explode(',', $x));}
else{ else{
if(isset($x[1])){ if(isset($x[1])){
preg_match_all('`(?:^|-|\+)[^\-+]+?(?=-|\+|$)`', $x, $m, PREG_SET_ORDER); preg_match_all('`(?:^|-|\+)[^\-+]+?(?=-|\+|$)`', $x, $m, PREG_SET_ORDER);
for($i=count($m); --$i>=0;){$m[$i] = $m[$i][0];} for($i=count($m); --$i>=0;){$m[$i] = $m[$i][0];}
foreach($m as $v){ foreach($m as $v){
if($v[0] == '+'){$e[substr($v, 1)] = 1;} if($v[0] == '+'){$e[substr($v, 1)] = 1;}
if($v[0] == '-' && isset($e[($v = substr($v, 1))]) && !in_array('+'. $v, $m)){unset($e[$v]);} if($v[0] == '-' && isset($e[($v = substr($v, 1))]) && !in_array('+'. $v, $m)){unset($e[$v]);}
} }
} }
} }
$C['elements'] =& $e; $C['elements'] =& $e;
// config attrs // config attrs
$x = !empty($C['deny_attribute']) ? str_replace(array("\n", "\r", "\t", ' '), '', $C['deny_attribute']) : ''; $x = !empty($C['deny_attribute']) ? str_replace(array("\n", "\r", "\t", ' '), '', $C['deny_attribute']) : '';
$x = array_flip((isset($x[0]) && $x[0] == '*') ? explode('-', $x) : explode(',', $x. (!empty($C['safe']) ? ',on*' : ''))); $x = array_flip((isset($x[0]) && $x[0] == '*') ? explode('-', $x) : explode(',', $x. (!empty($C['safe']) ? ',on*' : '')));
if(isset($x['on*'])){ if(isset($x['on*'])){
unset($x['on*']); unset($x['on*']);
$x += array('onblur'=>1, 'onchange'=>1, 'onclick'=>1, 'ondblclick'=>1, 'onfocus'=>1, 'onkeydown'=>1, 'onkeypress'=>1, 'onkeyup'=>1, 'onmousedown'=>1, 'onmousemove'=>1, 'onmouseout'=>1, 'onmouseover'=>1, 'onmouseup'=>1, 'onreset'=>1, 'onselect'=>1, 'onsubmit'=>1); $x += array('onblur'=>1, 'onchange'=>1, 'onclick'=>1, 'ondblclick'=>1, 'onfocus'=>1, 'onkeydown'=>1, 'onkeypress'=>1, 'onkeyup'=>1, 'onmousedown'=>1, 'onmousemove'=>1, 'onmouseout'=>1, 'onmouseover'=>1, 'onmouseup'=>1, 'onreset'=>1, 'onselect'=>1, 'onsubmit'=>1);
} }
$C['deny_attribute'] = $x; $C['deny_attribute'] = $x;
// config URL // config URL
$x = (isset($C['schemes'][2]) && strpos($C['schemes'], ':')) ? strtolower($C['schemes']) : 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; *:file, http, https'; $x = (isset($C['schemes'][2]) && strpos($C['schemes'], ':')) ? strtolower($C['schemes']) : 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; *:file, http, https';
$C['schemes'] = array(); $C['schemes'] = array();
foreach(explode(';', str_replace(array(' ', "\t", "\r", "\n"), '', $x)) as $v){ foreach(explode(';', str_replace(array(' ', "\t", "\r", "\n"), '', $x)) as $v){
$x = $x2 = null; list($x, $x2) = explode(':', $v, 2); $x = $x2 = null; list($x, $x2) = explode(':', $v, 2);
if($x2){$C['schemes'][$x] = array_flip(explode(',', $x2));} if($x2){$C['schemes'][$x] = array_flip(explode(',', $x2));}
} }
if(!isset($C['schemes']['*'])){$C['schemes']['*'] = array('file'=>1, 'http'=>1, 'https'=>1,);} if(!isset($C['schemes']['*'])){$C['schemes']['*'] = array('file'=>1, 'http'=>1, 'https'=>1,);}
if(!empty($C['safe']) && empty($C['schemes']['style'])){$C['schemes']['style'] = array('!'=>1);} if(!empty($C['safe']) && empty($C['schemes']['style'])){$C['schemes']['style'] = array('!'=>1);}
$C['abs_url'] = isset($C['abs_url']) ? $C['abs_url'] : 0; $C['abs_url'] = isset($C['abs_url']) ? $C['abs_url'] : 0;
if(!isset($C['base_url']) or !preg_match('`^[a-zA-Z\d.+\-]+://[^/]+/(.+?/)?$`', $C['base_url'])){ if(!isset($C['base_url']) or !preg_match('`^[a-zA-Z\d.+\-]+://[^/]+/(.+?/)?$`', $C['base_url'])){
$C['base_url'] = $C['abs_url'] = 0; $C['base_url'] = $C['abs_url'] = 0;
} }
// config rest // config rest
$C['and_mark'] = empty($C['and_mark']) ? 0 : 1; $C['and_mark'] = empty($C['and_mark']) ? 0 : 1;
$C['anti_link_spam'] = (isset($C['anti_link_spam']) && is_array($C['anti_link_spam']) && count($C['anti_link_spam']) == 2 && (empty($C['anti_link_spam'][0]) or hl_regex($C['anti_link_spam'][0])) && (empty($C['anti_link_spam'][1]) or hl_regex($C['anti_link_spam'][1]))) ? $C['anti_link_spam'] : 0; $C['anti_link_spam'] = (isset($C['anti_link_spam']) && is_array($C['anti_link_spam']) && count($C['anti_link_spam']) == 2 && (empty($C['anti_link_spam'][0]) or hl_regex($C['anti_link_spam'][0])) && (empty($C['anti_link_spam'][1]) or hl_regex($C['anti_link_spam'][1]))) ? $C['anti_link_spam'] : 0;
$C['anti_mail_spam'] = isset($C['anti_mail_spam']) ? $C['anti_mail_spam'] : 0; $C['anti_mail_spam'] = isset($C['anti_mail_spam']) ? $C['anti_mail_spam'] : 0;
$C['balance'] = isset($C['balance']) ? (bool)$C['balance'] : 1; $C['balance'] = isset($C['balance']) ? (bool)$C['balance'] : 1;
$C['cdata'] = isset($C['cdata']) ? $C['cdata'] : (empty($C['safe']) ? 3 : 0); $C['cdata'] = isset($C['cdata']) ? $C['cdata'] : (empty($C['safe']) ? 3 : 0);
$C['clean_ms_char'] = empty($C['clean_ms_char']) ? 0 : $C['clean_ms_char']; $C['clean_ms_char'] = empty($C['clean_ms_char']) ? 0 : $C['clean_ms_char'];
$C['comment'] = isset($C['comment']) ? $C['comment'] : (empty($C['safe']) ? 3 : 0); $C['comment'] = isset($C['comment']) ? $C['comment'] : (empty($C['safe']) ? 3 : 0);
$C['css_expression'] = empty($C['css_expression']) ? 0 : 1; $C['css_expression'] = empty($C['css_expression']) ? 0 : 1;
$C['direct_list_nest'] = empty($C['direct_list_nest']) ? 0 : 1; $C['direct_list_nest'] = empty($C['direct_list_nest']) ? 0 : 1;
$C['hexdec_entity'] = isset($C['hexdec_entity']) ? $C['hexdec_entity'] : 1; $C['hexdec_entity'] = isset($C['hexdec_entity']) ? $C['hexdec_entity'] : 1;
$C['hook'] = (!empty($C['hook']) && function_exists($C['hook'])) ? $C['hook'] : 0; $C['hook'] = (!empty($C['hook']) && function_exists($C['hook'])) ? $C['hook'] : 0;
$C['hook_tag'] = (!empty($C['hook_tag']) && function_exists($C['hook_tag'])) ? $C['hook_tag'] : 0; $C['hook_tag'] = (!empty($C['hook_tag']) && function_exists($C['hook_tag'])) ? $C['hook_tag'] : 0;
$C['keep_bad'] = isset($C['keep_bad']) ? $C['keep_bad'] : 6; $C['keep_bad'] = isset($C['keep_bad']) ? $C['keep_bad'] : 6;
$C['lc_std_val'] = isset($C['lc_std_val']) ? (bool)$C['lc_std_val'] : 1; $C['lc_std_val'] = isset($C['lc_std_val']) ? (bool)$C['lc_std_val'] : 1;
$C['make_tag_strict'] = isset($C['make_tag_strict']) ? $C['make_tag_strict'] : 1; $C['make_tag_strict'] = isset($C['make_tag_strict']) ? $C['make_tag_strict'] : 1;
$C['named_entity'] = isset($C['named_entity']) ? (bool)$C['named_entity'] : 1; $C['named_entity'] = isset($C['named_entity']) ? (bool)$C['named_entity'] : 1;
$C['no_deprecated_attr'] = isset($C['no_deprecated_attr']) ? $C['no_deprecated_attr'] : 1; $C['no_deprecated_attr'] = isset($C['no_deprecated_attr']) ? $C['no_deprecated_attr'] : 1;
$C['parent'] = isset($C['parent'][0]) ? strtolower($C['parent']) : 'body'; $C['parent'] = isset($C['parent'][0]) ? strtolower($C['parent']) : 'body';
$C['show_setting'] = !empty($C['show_setting']) ? $C['show_setting'] : 0; $C['show_setting'] = !empty($C['show_setting']) ? $C['show_setting'] : 0;
$C['style_pass'] = empty($C['style_pass']) ? 0 : 1; $C['style_pass'] = empty($C['style_pass']) ? 0 : 1;
$C['tidy'] = empty($C['tidy']) ? 0 : $C['tidy']; $C['tidy'] = empty($C['tidy']) ? 0 : $C['tidy'];
$C['unique_ids'] = isset($C['unique_ids']) ? $C['unique_ids'] : 1; $C['unique_ids'] = isset($C['unique_ids']) ? $C['unique_ids'] : 1;
$C['xml:lang'] = isset($C['xml:lang']) ? $C['xml:lang'] : 0; $C['xml:lang'] = isset($C['xml:lang']) ? $C['xml:lang'] : 0;
if(isset($GLOBALS['C'])){$reC = $GLOBALS['C'];} if(isset($GLOBALS['C'])){$reC = $GLOBALS['C'];}
$GLOBALS['C'] = $C; $GLOBALS['C'] = $C;
$S = is_array($S) ? $S : hl_spec($S); $S = is_array($S) ? $S : hl_spec($S);
if(isset($GLOBALS['S'])){$reS = $GLOBALS['S'];} if(isset($GLOBALS['S'])){$reS = $GLOBALS['S'];}
$GLOBALS['S'] = $S; $GLOBALS['S'] = $S;
$t = preg_replace('`[\x00-\x08\x0b-\x0c\x0e-\x1f]`', '', $t); $t = preg_replace('`[\x00-\x08\x0b-\x0c\x0e-\x1f]`', '', $t);
if($C['clean_ms_char']){ if($C['clean_ms_char']){
$x = array("\x7f"=>'', "\x80"=>'&#8364;', "\x81"=>'', "\x83"=>'&#402;', "\x85"=>'&#8230;', "\x86"=>'&#8224;', "\x87"=>'&#8225;', "\x88"=>'&#710;', "\x89"=>'&#8240;', "\x8a"=>'&#352;', "\x8b"=>'&#8249;', "\x8c"=>'&#338;', "\x8d"=>'', "\x8e"=>'&#381;', "\x8f"=>'', "\x90"=>'', "\x95"=>'&#8226;', "\x96"=>'&#8211;', "\x97"=>'&#8212;', "\x98"=>'&#732;', "\x99"=>'&#8482;', "\x9a"=>'&#353;', "\x9b"=>'&#8250;', "\x9c"=>'&#339;', "\x9d"=>'', "\x9e"=>'&#382;', "\x9f"=>'&#376;'); $x = array("\x7f"=>'', "\x80"=>'&#8364;', "\x81"=>'', "\x83"=>'&#402;', "\x85"=>'&#8230;', "\x86"=>'&#8224;', "\x87"=>'&#8225;', "\x88"=>'&#710;', "\x89"=>'&#8240;', "\x8a"=>'&#352;', "\x8b"=>'&#8249;', "\x8c"=>'&#338;', "\x8d"=>'', "\x8e"=>'&#381;', "\x8f"=>'', "\x90"=>'', "\x95"=>'&#8226;', "\x96"=>'&#8211;', "\x97"=>'&#8212;', "\x98"=>'&#732;', "\x99"=>'&#8482;', "\x9a"=>'&#353;', "\x9b"=>'&#8250;', "\x9c"=>'&#339;', "\x9d"=>'', "\x9e"=>'&#382;', "\x9f"=>'&#376;');
$x = $x + ($C['clean_ms_char'] == 1 ? array("\x82"=>'&#8218;', "\x84"=>'&#8222;', "\x91"=>'&#8216;', "\x92"=>'&#8217;', "\x93"=>'&#8220;', "\x94"=>'&#8221;') : array("\x82"=>'\'', "\x84"=>'"', "\x91"=>'\'', "\x92"=>'\'', "\x93"=>'"', "\x94"=>'"')); $x = $x + ($C['clean_ms_char'] == 1 ? array("\x82"=>'&#8218;', "\x84"=>'&#8222;', "\x91"=>'&#8216;', "\x92"=>'&#8217;', "\x93"=>'&#8220;', "\x94"=>'&#8221;') : array("\x82"=>'\'', "\x84"=>'"', "\x91"=>'\'', "\x92"=>'\'', "\x93"=>'"', "\x94"=>'"'));
$t = strtr($t, $x); $t = strtr($t, $x);
} }
if($C['cdata'] or $C['comment']){$t = preg_replace_callback('`<!(?:(?:--.*?--)|(?:\[CDATA\[.*?\]\]))>`sm', 'hl_cmtcd', $t);} if($C['cdata'] or $C['comment']){$t = preg_replace_callback('`<!(?:(?:--.*?--)|(?:\[CDATA\[.*?\]\]))>`sm', 'hl_cmtcd', $t);}
$t = preg_replace_callback('`&amp;([A-Za-z][A-Za-z0-9]{1,30}|#(?:[0-9]{1,8}|[Xx][0-9A-Fa-f]{1,7}));`', 'hl_ent', str_replace('&', '&amp;', $t)); $t = preg_replace_callback('`&amp;([A-Za-z][A-Za-z0-9]{1,30}|#(?:[0-9]{1,8}|[Xx][0-9A-Fa-f]{1,7}));`', 'hl_ent', str_replace('&', '&amp;', $t));
if($C['unique_ids'] && !isset($GLOBALS['hl_Ids'])){$GLOBALS['hl_Ids'] = array();} if($C['unique_ids'] && !isset($GLOBALS['hl_Ids'])){$GLOBALS['hl_Ids'] = array();}
if($C['hook']){$t = $C['hook']($t, $C, $S);} if($C['hook']){$t = $C['hook']($t, $C, $S);}
if($C['show_setting'] && preg_match('`^[a-z][a-z0-9_]*$`i', $C['show_setting'])){ if($C['show_setting'] && preg_match('`^[a-z][a-z0-9_]*$`i', $C['show_setting'])){
$GLOBALS[$C['show_setting']] = array('config'=>$C, 'spec'=>$S, 'time'=>microtime()); $GLOBALS[$C['show_setting']] = array('config'=>$C, 'spec'=>$S, 'time'=>microtime());
} }
// main // main
$t = preg_replace_callback('`<(?:(?:\s|$)|(?:[^>]*(?:>|$)))|>`m', 'hl_tag', $t); $t = preg_replace_callback('`<(?:(?:\s|$)|(?:[^>]*(?:>|$)))|>`m', 'hl_tag', $t);
$t = $C['balance'] ? hl_bal($t, $C['keep_bad'], $C['parent']) : $t; $t = $C['balance'] ? hl_bal($t, $C['keep_bad'], $C['parent']) : $t;
$t = (($C['cdata'] or $C['comment']) && strpos($t, "\x01") !== false) ? str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05"), array('', '', '&', '<', '>'), $t) : $t; $t = (($C['cdata'] or $C['comment']) && strpos($t, "\x01") !== false) ? str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05"), array('', '', '&', '<', '>'), $t) : $t;
$t = $C['tidy'] ? hl_tidy($t, $C['tidy'], $C['parent']) : $t; $t = $C['tidy'] ? hl_tidy($t, $C['tidy'], $C['parent']) : $t;
unset($C, $e); unset($C, $e);
if(isset($reC)){$GLOBALS['C'] = $reC;} if(isset($reC)){$GLOBALS['C'] = $reC;}
if(isset($reS)){$GLOBALS['S'] = $reS;} if(isset($reS)){$GLOBALS['S'] = $reS;}
return $t; return $t;
// eof // eof
} }
function hl_attrval($t, $p){ function hl_attrval($t, $p){
// check attr val against $S // check attr val against $S
$o = 1; $l = strlen($t); $o = 1; $l = strlen($t);
foreach($p as $k=>$v){ foreach($p as $k=>$v){
switch($k){ switch($k){
case 'maxlen':if($l > $v){$o = 0;} case 'maxlen':if($l > $v){$o = 0;}
break; case 'minlen': if($l < $v){$o = 0;} break; case 'minlen': if($l < $v){$o = 0;}
break; case 'maxval': if((float)($t) > $v){$o = 0;} break; case 'maxval': if((float)($t) > $v){$o = 0;}
break; case 'minval': if((float)($t) < $v){$o = 0;} break; case 'minval': if((float)($t) < $v){$o = 0;}
break; case 'match': if(!preg_match($v, $t)){$o = 0;} break; case 'match': if(!preg_match($v, $t)){$o = 0;}
break; case 'nomatch': if(preg_match($v, $t)){$o = 0;} break; case 'nomatch': if(preg_match($v, $t)){$o = 0;}
break; case 'oneof': break; case 'oneof':
$m = 0; $m = 0;
foreach(explode('|', $v) as $n){if($t == $n){$m = 1; break;}} foreach(explode('|', $v) as $n){if($t == $n){$m = 1; break;}}
$o = $m; $o = $m;
break; case 'noneof': break; case 'noneof':
$m = 1; $m = 1;
foreach(explode('|', $v) as $n){if($t == $n){$m = 0; break;}} foreach(explode('|', $v) as $n){if($t == $n){$m = 0; break;}}
$o = $m; $o = $m;
break; default: break; default:
break; break;
} }
if(!$o){break;} if(!$o){break;}
} }
return ($o ? $t : (isset($p['default']) ? $p['default'] : 0)); return ($o ? $t : (isset($p['default']) ? $p['default'] : 0));
// eof // eof
} }
function hl_bal($t, $do=1, $in='div'){ function hl_bal($t, $do=1, $in='div'){
// balance tags // balance tags
// by content // by content
$cB = array('blockquote'=>1, 'form'=>1, 'map'=>1, 'noscript'=>1); // Block $cB = array('blockquote'=>1, 'form'=>1, 'map'=>1, 'noscript'=>1); // Block
$cE = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1); // Empty $cE = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1); // Empty
$cF = array('button'=>1, 'del'=>1, 'div'=>1, 'dd'=>1, 'fieldset'=>1, 'iframe'=>1, 'ins'=>1, 'li'=>1, 'noscript'=>1, 'object'=>1, 'td'=>1, 'th'=>1); // Flow; later context-wise dynamic move of ins & del to $cI $cF = array('button'=>1, 'del'=>1, 'div'=>1, 'dd'=>1, 'fieldset'=>1, 'iframe'=>1, 'ins'=>1, 'li'=>1, 'noscript'=>1, 'object'=>1, 'td'=>1, 'th'=>1); // Flow; later context-wise dynamic move of ins & del to $cI
$cI = array('a'=>1, 'abbr'=>1, 'acronym'=>1, 'address'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'caption'=>1, 'cite'=>1, 'code'=>1, 'dfn'=>1, 'dt'=>1, 'em'=>1, 'font'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'i'=>1, 'kbd'=>1, 'label'=>1, 'legend'=>1, 'p'=>1, 'pre'=>1, 'q'=>1, 'rb'=>1, 'rt'=>1, 's'=>1, 'samp'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'tt'=>1, 'u'=>1, 'var'=>1); // Inline $cI = array('a'=>1, 'abbr'=>1, 'acronym'=>1, 'address'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'caption'=>1, 'cite'=>1, 'code'=>1, 'dfn'=>1, 'dt'=>1, 'em'=>1, 'font'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'i'=>1, 'kbd'=>1, 'label'=>1, 'legend'=>1, 'p'=>1, 'pre'=>1, 'q'=>1, 'rb'=>1, 'rt'=>1, 's'=>1, 'samp'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'tt'=>1, 'u'=>1, 'var'=>1); // Inline
$cN = array('a'=>array('a'=>1), 'button'=>array('a'=>1, 'button'=>1, 'fieldset'=>1, 'form'=>1, 'iframe'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'fieldset'=>array('fieldset'=>1), 'form'=>array('form'=>1), 'label'=>array('label'=>1), 'noscript'=>array('script'=>1), 'pre'=>array('big'=>1, 'font'=>1, 'img'=>1, 'object'=>1, 'script'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1), 'rb'=>array('ruby'=>1), 'rt'=>array('ruby'=>1)); // Illegal $cN = array('a'=>array('a'=>1), 'button'=>array('a'=>1, 'button'=>1, 'fieldset'=>1, 'form'=>1, 'iframe'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'fieldset'=>array('fieldset'=>1), 'form'=>array('form'=>1), 'label'=>array('label'=>1), 'noscript'=>array('script'=>1), 'pre'=>array('big'=>1, 'font'=>1, 'img'=>1, 'object'=>1, 'script'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1), 'rb'=>array('ruby'=>1), 'rt'=>array('ruby'=>1)); // Illegal
$cN2 = array_keys($cN); $cN2 = array_keys($cN);
$cR = array('blockquote'=>1, 'dir'=>1, 'dl'=>1, 'form'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'optgroup'=>1, 'rbc'=>1, 'rtc'=>1, 'ruby'=>1, 'select'=>1, 'table'=>1, 'tbody'=>1, 'tfoot'=>1, 'thead'=>1, 'tr'=>1, 'ul'=>1); $cR = array('blockquote'=>1, 'dir'=>1, 'dl'=>1, 'form'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'optgroup'=>1, 'rbc'=>1, 'rtc'=>1, 'ruby'=>1, 'select'=>1, 'table'=>1, 'tbody'=>1, 'tfoot'=>1, 'thead'=>1, 'tr'=>1, 'ul'=>1);
$cS = array('colgroup'=>array('col'=>1), 'dir'=>array('li'=>1), 'dl'=>array('dd'=>1, 'dt'=>1), 'menu'=>array('li'=>1), 'ol'=>array('li'=>1), 'optgroup'=>array('option'=>1), 'option'=>array('#pcdata'=>1), 'rbc'=>array('rb'=>1), 'rp'=>array('#pcdata'=>1), 'rtc'=>array('rt'=>1), 'ruby'=>array('rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1), 'select'=>array('optgroup'=>1, 'option'=>1), 'script'=>array('#pcdata'=>1), 'table'=>array('caption'=>1, 'col'=>1, 'colgroup'=>1, 'tfoot'=>1, 'tbody'=>1, 'tr'=>1, 'thead'=>1), 'tbody'=>array('tr'=>1), 'tfoot'=>array('tr'=>1), 'textarea'=>array('#pcdata'=>1), 'thead'=>array('tr'=>1), 'tr'=>array('td'=>1, 'th'=>1), 'ul'=>array('li'=>1)); // Specific - immediate parent-child $cS = array('colgroup'=>array('col'=>1), 'dir'=>array('li'=>1), 'dl'=>array('dd'=>1, 'dt'=>1), 'menu'=>array('li'=>1), 'ol'=>array('li'=>1), 'optgroup'=>array('option'=>1), 'option'=>array('#pcdata'=>1), 'rbc'=>array('rb'=>1), 'rp'=>array('#pcdata'=>1), 'rtc'=>array('rt'=>1), 'ruby'=>array('rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1), 'select'=>array('optgroup'=>1, 'option'=>1), 'script'=>array('#pcdata'=>1), 'table'=>array('caption'=>1, 'col'=>1, 'colgroup'=>1, 'tfoot'=>1, 'tbody'=>1, 'tr'=>1, 'thead'=>1), 'tbody'=>array('tr'=>1), 'tfoot'=>array('tr'=>1), 'textarea'=>array('#pcdata'=>1), 'thead'=>array('tr'=>1), 'tr'=>array('td'=>1, 'th'=>1), 'ul'=>array('li'=>1)); // Specific - immediate parent-child
if($GLOBALS['C']['direct_list_nest']){$cS['ol'] = $cS['ul'] += array('ol'=>1, 'ul'=>1);} if($GLOBALS['C']['direct_list_nest']){$cS['ol'] = $cS['ul'] += array('ol'=>1, 'ul'=>1);}
$cO = array('address'=>array('p'=>1), 'applet'=>array('param'=>1), 'blockquote'=>array('script'=>1), 'fieldset'=>array('legend'=>1, '#pcdata'=>1), 'form'=>array('script'=>1), 'map'=>array('area'=>1), 'object'=>array('param'=>1, 'embed'=>1)); // Other $cO = array('address'=>array('p'=>1), 'applet'=>array('param'=>1), 'blockquote'=>array('script'=>1), 'fieldset'=>array('legend'=>1, '#pcdata'=>1), 'form'=>array('script'=>1), 'map'=>array('area'=>1), 'object'=>array('param'=>1, 'embed'=>1)); // Other
$cT = array('colgroup'=>1, 'dd'=>1, 'dt'=>1, 'li'=>1, 'option'=>1, 'p'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1); // Omitable closing $cT = array('colgroup'=>1, 'dd'=>1, 'dt'=>1, 'li'=>1, 'option'=>1, 'p'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1); // Omitable closing
// block/inline type; ins & del both type; #pcdata: text // block/inline type; ins & del both type; #pcdata: text
$eB = array('address'=>1, 'blockquote'=>1, 'center'=>1, 'del'=>1, 'dir'=>1, 'dl'=>1, 'div'=>1, 'fieldset'=>1, 'form'=>1, 'ins'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'isindex'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'p'=>1, 'pre'=>1, 'table'=>1, 'ul'=>1); $eB = array('address'=>1, 'blockquote'=>1, 'center'=>1, 'del'=>1, 'dir'=>1, 'dl'=>1, 'div'=>1, 'fieldset'=>1, 'form'=>1, 'ins'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'isindex'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'p'=>1, 'pre'=>1, 'table'=>1, 'ul'=>1);
$eI = array('#pcdata'=>1, 'a'=>1, 'abbr'=>1, 'acronym'=>1, 'applet'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'br'=>1, 'button'=>1, 'cite'=>1, 'code'=>1, 'del'=>1, 'dfn'=>1, 'em'=>1, 'embed'=>1, 'font'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'kbd'=>1, 'label'=>1, 'map'=>1, 'object'=>1, 'q'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'select'=>1, 'script'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1, 'tt'=>1, 'u'=>1, 'var'=>1); $eI = array('#pcdata'=>1, 'a'=>1, 'abbr'=>1, 'acronym'=>1, 'applet'=>1, 'b'=>1, 'bdo'=>1, 'big'=>1, 'br'=>1, 'button'=>1, 'cite'=>1, 'code'=>1, 'del'=>1, 'dfn'=>1, 'em'=>1, 'embed'=>1, 'font'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'kbd'=>1, 'label'=>1, 'map'=>1, 'object'=>1, 'q'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'select'=>1, 'script'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1, 'tt'=>1, 'u'=>1, 'var'=>1);
$eN = array('a'=>1, 'big'=>1, 'button'=>1, 'fieldset'=>1, 'font'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'label'=>1, 'object'=>1, 'ruby'=>1, 'script'=>1, 'select'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1); // Exclude from specific ele; $cN values $eN = array('a'=>1, 'big'=>1, 'button'=>1, 'fieldset'=>1, 'font'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'label'=>1, 'object'=>1, 'ruby'=>1, 'script'=>1, 'select'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1); // Exclude from specific ele; $cN values
$eO = array('area'=>1, 'caption'=>1, 'col'=>1, 'colgroup'=>1, 'dd'=>1, 'dt'=>1, 'legend'=>1, 'li'=>1, 'optgroup'=>1, 'option'=>1, 'param'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'script'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'thead'=>1, 'th'=>1, 'tr'=>1); // Missing in $eB & $eI $eO = array('area'=>1, 'caption'=>1, 'col'=>1, 'colgroup'=>1, 'dd'=>1, 'dt'=>1, 'legend'=>1, 'li'=>1, 'optgroup'=>1, 'option'=>1, 'param'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'script'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'thead'=>1, 'th'=>1, 'tr'=>1); // Missing in $eB & $eI
$eF = $eB + $eI; $eF = $eB + $eI;
// $in sets allowed child // $in sets allowed child
$in = ((isset($eF[$in]) && $in != '#pcdata') or isset($eO[$in])) ? $in : 'div'; $in = ((isset($eF[$in]) && $in != '#pcdata') or isset($eO[$in])) ? $in : 'div';
if(isset($cE[$in])){ if(isset($cE[$in])){
return (!$do ? '' : str_replace(array('<', '>'), array('&lt;', '&gt;'), $t)); return (!$do ? '' : str_replace(array('<', '>'), array('&lt;', '&gt;'), $t));
} }
if(isset($cS[$in])){$inOk = $cS[$in];} if(isset($cS[$in])){$inOk = $cS[$in];}
elseif(isset($cI[$in])){$inOk = $eI; $cI['del'] = 1; $cI['ins'] = 1;} elseif(isset($cI[$in])){$inOk = $eI; $cI['del'] = 1; $cI['ins'] = 1;}
elseif(isset($cF[$in])){$inOk = $eF; unset($cI['del'], $cI['ins']);} elseif(isset($cF[$in])){$inOk = $eF; unset($cI['del'], $cI['ins']);}
elseif(isset($cB[$in])){$inOk = $eB; unset($cI['del'], $cI['ins']);} elseif(isset($cB[$in])){$inOk = $eB; unset($cI['del'], $cI['ins']);}
if(isset($cO[$in])){$inOk = $inOk + $cO[$in];} if(isset($cO[$in])){$inOk = $inOk + $cO[$in];}
if(isset($cN[$in])){$inOk = array_diff_assoc($inOk, $cN[$in]);} if(isset($cN[$in])){$inOk = array_diff_assoc($inOk, $cN[$in]);}
$t = explode('<', $t); $t = explode('<', $t);
$ok = $q = array(); // $q seq list of open non-empty ele $ok = $q = array(); // $q seq list of open non-empty ele
ob_start(); ob_start();
for($i=-1, $ci=count($t); ++$i<$ci;){ for($i=-1, $ci=count($t); ++$i<$ci;){
// allowed $ok in parent $p // allowed $ok in parent $p
if($ql = count($q)){ if($ql = count($q)){
$p = array_pop($q); $p = array_pop($q);
$q[] = $p; $q[] = $p;
if(isset($cS[$p])){$ok = $cS[$p];} if(isset($cS[$p])){$ok = $cS[$p];}
elseif(isset($cI[$p])){$ok = $eI; $cI['del'] = 1; $cI['ins'] = 1;} elseif(isset($cI[$p])){$ok = $eI; $cI['del'] = 1; $cI['ins'] = 1;}
elseif(isset($cF[$p])){$ok = $eF; unset($cI['del'], $cI['ins']);} elseif(isset($cF[$p])){$ok = $eF; unset($cI['del'], $cI['ins']);}
elseif(isset($cB[$p])){$ok = $eB; unset($cI['del'], $cI['ins']);} elseif(isset($cB[$p])){$ok = $eB; unset($cI['del'], $cI['ins']);}
if(isset($cO[$p])){$ok = $ok + $cO[$p];} if(isset($cO[$p])){$ok = $ok + $cO[$p];}
if(isset($cN[$p])){$ok = array_diff_assoc($ok, $cN[$p]);} if(isset($cN[$p])){$ok = array_diff_assoc($ok, $cN[$p]);}
}else{$ok = $inOk; unset($cI['del'], $cI['ins']);} }else{$ok = $inOk; unset($cI['del'], $cI['ins']);}
// bad tags, & ele content // bad tags, & ele content
if(isset($e) && ($do == 1 or (isset($ok['#pcdata']) && ($do == 3 or $do == 5)))){ if(isset($e) && ($do == 1 or (isset($ok['#pcdata']) && ($do == 3 or $do == 5)))){
echo '&lt;', $s, $e, $a, '&gt;'; echo '&lt;', $s, $e, $a, '&gt;';
} }
if(isset($x[0])){ if(isset($x[0])){
if(strlen(trim($x)) && (($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql))){ if(strlen(trim($x)) && (($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql))){
echo '<div>', $x, '</div>'; echo '<div>', $x, '</div>';
} }
elseif($do < 3 or isset($ok['#pcdata'])){echo $x;} elseif($do < 3 or isset($ok['#pcdata'])){echo $x;}
elseif(strpos($x, "\x02\x04")){ elseif(strpos($x, "\x02\x04")){
foreach(preg_split('`(\x01\x02[^\x01\x02]+\x02\x01)`', $x, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $v){ foreach(preg_split('`(\x01\x02[^\x01\x02]+\x02\x01)`', $x, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $v){
echo (substr($v, 0, 2) == "\x01\x02" ? $v : ($do > 4 ? preg_replace('`\S`', '', $v) : '')); echo (substr($v, 0, 2) == "\x01\x02" ? $v : ($do > 4 ? preg_replace('`\S`', '', $v) : ''));
} }
}elseif($do > 4){echo preg_replace('`\S`', '', $x);} }elseif($do > 4){echo preg_replace('`\S`', '', $x);}
} }
// get markup // get markup
if(!preg_match('`^(/?)([a-z1-6]+)([^>]*)>(.*)`sm', $t[$i], $r)){$x = $t[$i]; continue;} if(!preg_match('`^(/?)([a-z1-6]+)([^>]*)>(.*)`sm', $t[$i], $r)){$x = $t[$i]; continue;}
$s = null; $e = null; $a = null; $x = null; list($all, $s, $e, $a, $x) = $r; $s = null; $e = null; $a = null; $x = null; list($all, $s, $e, $a, $x) = $r;
// close tag // close tag
if($s){ if($s){
if(isset($cE[$e]) or !in_array($e, $q)){continue;} // Empty/unopen if(isset($cE[$e]) or !in_array($e, $q)){continue;} // Empty/unopen
if($p == $e){array_pop($q); echo '</', $e, '>'; unset($e); continue;} // Last open if($p == $e){array_pop($q); echo '</', $e, '>'; unset($e); continue;} // Last open
$add = ''; // Nesting - close open tags that need to be $add = ''; // Nesting - close open tags that need to be
for($j=-1, $cj=count($q); ++$j<$cj;){ for($j=-1, $cj=count($q); ++$j<$cj;){
if(($d = array_pop($q)) == $e){break;} if(($d = array_pop($q)) == $e){break;}
else{$add .= "</{$d}>";} else{$add .= "</{$d}>";}
} }
echo $add, '</', $e, '>'; unset($e); continue; echo $add, '</', $e, '>'; unset($e); continue;
} }
// open tag // open tag
// $cB ele needs $eB ele as child // $cB ele needs $eB ele as child
if(isset($cB[$e]) && strlen(trim($x))){ if(isset($cB[$e]) && strlen(trim($x))){
$t[$i] = "{$e}{$a}>"; $t[$i] = "{$e}{$a}>";
array_splice($t, $i+1, 0, 'div>'. $x); unset($e, $x); ++$ci; --$i; continue; array_splice($t, $i+1, 0, 'div>'. $x); unset($e, $x); ++$ci; --$i; continue;
} }
if((($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql)) && !isset($eB[$e]) && !isset($ok[$e])){ if((($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql)) && !isset($eB[$e]) && !isset($ok[$e])){
array_splice($t, $i, 0, 'div>'); unset($e, $x); ++$ci; --$i; continue; array_splice($t, $i, 0, 'div>'); unset($e, $x); ++$ci; --$i; continue;
} }
// if no open ele, $in = parent; mostly immediate parent-child relation should hold // if no open ele, $in = parent; mostly immediate parent-child relation should hold
if(!$ql or !isset($eN[$e]) or !array_intersect($q, $cN2)){ if(!$ql or !isset($eN[$e]) or !array_intersect($q, $cN2)){
if(!isset($ok[$e])){ if(!isset($ok[$e])){
if($ql && isset($cT[$p])){echo '</', array_pop($q), '>'; unset($e, $x); --$i;} if($ql && isset($cT[$p])){echo '</', array_pop($q), '>'; unset($e, $x); --$i;}
continue; continue;
} }
if(!isset($cE[$e])){$q[] = $e;} if(!isset($cE[$e])){$q[] = $e;}
echo '<', $e, $a, '>'; unset($e); continue; echo '<', $e, $a, '>'; unset($e); continue;
} }
// specific parent-child // specific parent-child
if(isset($cS[$p][$e])){ if(isset($cS[$p][$e])){
if(!isset($cE[$e])){$q[] = $e;} if(!isset($cE[$e])){$q[] = $e;}
echo '<', $e, $a, '>'; unset($e); continue; echo '<', $e, $a, '>'; unset($e); continue;
} }
// nesting // nesting
$add = ''; $add = '';
$q2 = array(); $q2 = array();
for($k=-1, $kc=count($q); ++$k<$kc;){ for($k=-1, $kc=count($q); ++$k<$kc;){
$d = $q[$k]; $d = $q[$k];
$ok2 = array(); $ok2 = array();
if(isset($cS[$d])){$q2[] = $d; continue;} if(isset($cS[$d])){$q2[] = $d; continue;}
$ok2 = isset($cI[$d]) ? $eI : $eF; $ok2 = isset($cI[$d]) ? $eI : $eF;
if(isset($cO[$d])){$ok2 = $ok2 + $cO[$d];} if(isset($cO[$d])){$ok2 = $ok2 + $cO[$d];}
if(isset($cN[$d])){$ok2 = array_diff_assoc($ok2, $cN[$d]);} if(isset($cN[$d])){$ok2 = array_diff_assoc($ok2, $cN[$d]);}
if(!isset($ok2[$e])){ if(!isset($ok2[$e])){
if(!$k && !isset($inOk[$e])){continue 2;} if(!$k && !isset($inOk[$e])){continue 2;}
$add = "</{$d}>"; $add = "</{$d}>";
for(;++$k<$kc;){$add = "</{$q[$k]}>{$add}";} for(;++$k<$kc;){$add = "</{$q[$k]}>{$add}";}
break; break;
} }
else{$q2[] = $d;} else{$q2[] = $d;}
} }
$q = $q2; $q = $q2;
if(!isset($cE[$e])){$q[] = $e;} if(!isset($cE[$e])){$q[] = $e;}
echo $add, '<', $e, $a, '>'; unset($e); continue; echo $add, '<', $e, $a, '>'; unset($e); continue;
} }
// end // end
if($ql = count($q)){ if($ql = count($q)){
$p = array_pop($q); $p = array_pop($q);
$q[] = $p; $q[] = $p;
if(isset($cS[$p])){$ok = $cS[$p];} if(isset($cS[$p])){$ok = $cS[$p];}
elseif(isset($cI[$p])){$ok = $eI; $cI['del'] = 1; $cI['ins'] = 1;} elseif(isset($cI[$p])){$ok = $eI; $cI['del'] = 1; $cI['ins'] = 1;}
elseif(isset($cF[$p])){$ok = $eF; unset($cI['del'], $cI['ins']);} elseif(isset($cF[$p])){$ok = $eF; unset($cI['del'], $cI['ins']);}
elseif(isset($cB[$p])){$ok = $eB; unset($cI['del'], $cI['ins']);} elseif(isset($cB[$p])){$ok = $eB; unset($cI['del'], $cI['ins']);}
if(isset($cO[$p])){$ok = $ok + $cO[$p];} if(isset($cO[$p])){$ok = $ok + $cO[$p];}
if(isset($cN[$p])){$ok = array_diff_assoc($ok, $cN[$p]);} if(isset($cN[$p])){$ok = array_diff_assoc($ok, $cN[$p]);}
}else{$ok = $inOk; unset($cI['del'], $cI['ins']);} }else{$ok = $inOk; unset($cI['del'], $cI['ins']);}
if(isset($e) && ($do == 1 or (isset($ok['#pcdata']) && ($do == 3 or $do == 5)))){ if(isset($e) && ($do == 1 or (isset($ok['#pcdata']) && ($do == 3 or $do == 5)))){
echo '&lt;', $s, $e, $a, '&gt;'; echo '&lt;', $s, $e, $a, '&gt;';
} }
if(isset($x[0])){ if(isset($x[0])){
if(strlen(trim($x)) && (($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql))){ if(strlen(trim($x)) && (($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql))){
echo '<div>', $x, '</div>'; echo '<div>', $x, '</div>';
} }
elseif($do < 3 or isset($ok['#pcdata'])){echo $x;} elseif($do < 3 or isset($ok['#pcdata'])){echo $x;}
elseif(strpos($x, "\x02\x04")){ elseif(strpos($x, "\x02\x04")){
foreach(preg_split('`(\x01\x02[^\x01\x02]+\x02\x01)`', $x, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $v){ foreach(preg_split('`(\x01\x02[^\x01\x02]+\x02\x01)`', $x, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $v){
echo (substr($v, 0, 2) == "\x01\x02" ? $v : ($do > 4 ? preg_replace('`\S`', '', $v) : '')); echo (substr($v, 0, 2) == "\x01\x02" ? $v : ($do > 4 ? preg_replace('`\S`', '', $v) : ''));
} }
}elseif($do > 4){echo preg_replace('`\S`', '', $x);} }elseif($do > 4){echo preg_replace('`\S`', '', $x);}
} }
while(!empty($q) && ($e = array_pop($q))){echo '</', $e, '>';} while(!empty($q) && ($e = array_pop($q))){echo '</', $e, '>';}
$o = ob_get_contents(); $o = ob_get_contents();
ob_end_clean(); ob_end_clean();
return $o; return $o;
// eof // eof
} }
function hl_cmtcd($t){ function hl_cmtcd($t){
// comment/CDATA sec handler // comment/CDATA sec handler
$t = $t[0]; $t = $t[0];
global $C; global $C;
if(!($v = $C[$n = $t[3] == '-' ? 'comment' : 'cdata'])){return $t;} if(!($v = $C[$n = $t[3] == '-' ? 'comment' : 'cdata'])){return $t;}
if($v == 1){return '';} if($v == 1){return '';}
if($n == 'comment'){ if($n == 'comment'){
if(substr(($t = preg_replace('`--+`', '-', substr($t, 4, -3))), -1) != ' '){$t .= ' ';} if(substr(($t = preg_replace('`--+`', '-', substr($t, 4, -3))), -1) != ' '){$t .= ' ';}
} }
else{$t = substr($t, 1, -1);} else{$t = substr($t, 1, -1);}
$t = $v == 2 ? str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $t) : $t; $t = $v == 2 ? str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $t) : $t;
return str_replace(array('&', '<', '>'), array("\x03", "\x04", "\x05"), ($n == 'comment' ? "\x01\x02\x04!--$t--\x05\x02\x01" : "\x01\x01\x04$t\x05\x01\x01")); return str_replace(array('&', '<', '>'), array("\x03", "\x04", "\x05"), ($n == 'comment' ? "\x01\x02\x04!--$t--\x05\x02\x01" : "\x01\x01\x04$t\x05\x01\x01"));
// eof // eof
} }
function hl_ent($t){ function hl_ent($t){
// entitity handler // entitity handler
global $C; global $C;
$t = $t[1]; $t = $t[1];
static $U = array('quot'=>1,'amp'=>1,'lt'=>1,'gt'=>1); static $U = array('quot'=>1,'amp'=>1,'lt'=>1,'gt'=>1);
static $N = array('fnof'=>'402', 'Alpha'=>'913', 'Beta'=>'914', 'Gamma'=>'915', 'Delta'=>'916', 'Epsilon'=>'917', 'Zeta'=>'918', 'Eta'=>'919', 'Theta'=>'920', 'Iota'=>'921', 'Kappa'=>'922', 'Lambda'=>'923', 'Mu'=>'924', 'Nu'=>'925', 'Xi'=>'926', 'Omicron'=>'927', 'Pi'=>'928', 'Rho'=>'929', 'Sigma'=>'931', 'Tau'=>'932', 'Upsilon'=>'933', 'Phi'=>'934', 'Chi'=>'935', 'Psi'=>'936', 'Omega'=>'937', 'alpha'=>'945', 'beta'=>'946', 'gamma'=>'947', 'delta'=>'948', 'epsilon'=>'949', 'zeta'=>'950', 'eta'=>'951', 'theta'=>'952', 'iota'=>'953', 'kappa'=>'954', 'lambda'=>'955', 'mu'=>'956', 'nu'=>'957', 'xi'=>'958', 'omicron'=>'959', 'pi'=>'960', 'rho'=>'961', 'sigmaf'=>'962', 'sigma'=>'963', 'tau'=>'964', 'upsilon'=>'965', 'phi'=>'966', 'chi'=>'967', 'psi'=>'968', 'omega'=>'969', 'thetasym'=>'977', 'upsih'=>'978', 'piv'=>'982', 'bull'=>'8226', 'hellip'=>'8230', 'prime'=>'8242', 'Prime'=>'8243', 'oline'=>'8254', 'frasl'=>'8260', 'weierp'=>'8472', 'image'=>'8465', 'real'=>'8476', 'trade'=>'8482', 'alefsym'=>'8501', 'larr'=>'8592', 'uarr'=>'8593', 'rarr'=>'8594', 'darr'=>'8595', 'harr'=>'8596', 'crarr'=>'8629', 'lArr'=>'8656', 'uArr'=>'8657', 'rArr'=>'8658', 'dArr'=>'8659', 'hArr'=>'8660', 'forall'=>'8704', 'part'=>'8706', 'exist'=>'8707', 'empty'=>'8709', 'nabla'=>'8711', 'isin'=>'8712', 'notin'=>'8713', 'ni'=>'8715', 'prod'=>'8719', 'sum'=>'8721', 'minus'=>'8722', 'lowast'=>'8727', 'radic'=>'8730', 'prop'=>'8733', 'infin'=>'8734', 'ang'=>'8736', 'and'=>'8743', 'or'=>'8744', 'cap'=>'8745', 'cup'=>'8746', 'int'=>'8747', 'there4'=>'8756', 'sim'=>'8764', 'cong'=>'8773', 'asymp'=>'8776', 'ne'=>'8800', 'equiv'=>'8801', 'le'=>'8804', 'ge'=>'8805', 'sub'=>'8834', 'sup'=>'8835', 'nsub'=>'8836', 'sube'=>'8838', 'supe'=>'8839', 'oplus'=>'8853', 'otimes'=>'8855', 'perp'=>'8869', 'sdot'=>'8901', 'lceil'=>'8968', 'rceil'=>'8969', 'lfloor'=>'8970', 'rfloor'=>'8971', 'lang'=>'9001', 'rang'=>'9002', 'loz'=>'9674', 'spades'=>'9824', 'clubs'=>'9827', 'hearts'=>'9829', 'diams'=>'9830', 'apos'=>'39', 'OElig'=>'338', 'oelig'=>'339', 'Scaron'=>'352', 'scaron'=>'353', 'Yuml'=>'376', 'circ'=>'710', 'tilde'=>'732', 'ensp'=>'8194', 'emsp'=>'8195', 'thinsp'=>'8201', 'zwnj'=>'8204', 'zwj'=>'8205', 'lrm'=>'8206', 'rlm'=>'8207', 'ndash'=>'8211', 'mdash'=>'8212', 'lsquo'=>'8216', 'rsquo'=>'8217', 'sbquo'=>'8218', 'ldquo'=>'8220', 'rdquo'=>'8221', 'bdquo'=>'8222', 'dagger'=>'8224', 'Dagger'=>'8225', 'permil'=>'8240', 'lsaquo'=>'8249', 'rsaquo'=>'8250', 'euro'=>'8364', 'nbsp'=>'160', 'iexcl'=>'161', 'cent'=>'162', 'pound'=>'163', 'curren'=>'164', 'yen'=>'165', 'brvbar'=>'166', 'sect'=>'167', 'uml'=>'168', 'copy'=>'169', 'ordf'=>'170', 'laquo'=>'171', 'not'=>'172', 'shy'=>'173', 'reg'=>'174', 'macr'=>'175', 'deg'=>'176', 'plusmn'=>'177', 'sup2'=>'178', 'sup3'=>'179', 'acute'=>'180', 'micro'=>'181', 'para'=>'182', 'middot'=>'183', 'cedil'=>'184', 'sup1'=>'185', 'ordm'=>'186', 'raquo'=>'187', 'frac14'=>'188', 'frac12'=>'189', 'frac34'=>'190', 'iquest'=>'191', 'Agrave'=>'192', 'Aacute'=>'193', 'Acirc'=>'194', 'Atilde'=>'195', 'Auml'=>'196', 'Aring'=>'197', 'AElig'=>'198', 'Ccedil'=>'199', 'Egrave'=>'200', 'Eacute'=>'201', 'Ecirc'=>'202', 'Euml'=>'203', 'Igrave'=>'204', 'Iacute'=>'205', 'Icirc'=>'206', 'Iuml'=>'207', 'ETH'=>'208', 'Ntilde'=>'209', 'Ograve'=>'210', 'Oacute'=>'211', 'Ocirc'=>'212', 'Otilde'=>'213', 'Ouml'=>'214', 'times'=>'215', 'Oslash'=>'216', 'Ugrave'=>'217', 'Uacute'=>'218', 'Ucirc'=>'219', 'Uuml'=>'220', 'Yacute'=>'221', 'THORN'=>'222', 'szlig'=>'223', 'agrave'=>'224', 'aacute'=>'225', 'acirc'=>'226', 'atilde'=>'227', 'auml'=>'228', 'aring'=>'229', 'aelig'=>'230', 'ccedil'=>'231', 'egrave'=>'232', 'eacute'=>'233', 'ecirc'=>'234', 'euml'=>'235', 'igrave'=>'236', 'iacute'=>'237', 'icirc'=>'238', 'iuml'=>'239', 'eth'=>'240', 'ntilde'=>'241', 'ograve'=>'242', 'oacute'=>'243', 'ocirc'=>'244', 'otilde'=>'245', 'ouml'=>'246', 'divide'=>'247', 'oslash'=>'248', 'ugrave'=>'249', 'uacute'=>'250', 'ucirc'=>'251', 'uuml'=>'252', 'yacute'=>'253', 'thorn'=>'254', 'yuml'=>'255'); static $N = array('fnof'=>'402', 'Alpha'=>'913', 'Beta'=>'914', 'Gamma'=>'915', 'Delta'=>'916', 'Epsilon'=>'917', 'Zeta'=>'918', 'Eta'=>'919', 'Theta'=>'920', 'Iota'=>'921', 'Kappa'=>'922', 'Lambda'=>'923', 'Mu'=>'924', 'Nu'=>'925', 'Xi'=>'926', 'Omicron'=>'927', 'Pi'=>'928', 'Rho'=>'929', 'Sigma'=>'931', 'Tau'=>'932', 'Upsilon'=>'933', 'Phi'=>'934', 'Chi'=>'935', 'Psi'=>'936', 'Omega'=>'937', 'alpha'=>'945', 'beta'=>'946', 'gamma'=>'947', 'delta'=>'948', 'epsilon'=>'949', 'zeta'=>'950', 'eta'=>'951', 'theta'=>'952', 'iota'=>'953', 'kappa'=>'954', 'lambda'=>'955', 'mu'=>'956', 'nu'=>'957', 'xi'=>'958', 'omicron'=>'959', 'pi'=>'960', 'rho'=>'961', 'sigmaf'=>'962', 'sigma'=>'963', 'tau'=>'964', 'upsilon'=>'965', 'phi'=>'966', 'chi'=>'967', 'psi'=>'968', 'omega'=>'969', 'thetasym'=>'977', 'upsih'=>'978', 'piv'=>'982', 'bull'=>'8226', 'hellip'=>'8230', 'prime'=>'8242', 'Prime'=>'8243', 'oline'=>'8254', 'frasl'=>'8260', 'weierp'=>'8472', 'image'=>'8465', 'real'=>'8476', 'trade'=>'8482', 'alefsym'=>'8501', 'larr'=>'8592', 'uarr'=>'8593', 'rarr'=>'8594', 'darr'=>'8595', 'harr'=>'8596', 'crarr'=>'8629', 'lArr'=>'8656', 'uArr'=>'8657', 'rArr'=>'8658', 'dArr'=>'8659', 'hArr'=>'8660', 'forall'=>'8704', 'part'=>'8706', 'exist'=>'8707', 'empty'=>'8709', 'nabla'=>'8711', 'isin'=>'8712', 'notin'=>'8713', 'ni'=>'8715', 'prod'=>'8719', 'sum'=>'8721', 'minus'=>'8722', 'lowast'=>'8727', 'radic'=>'8730', 'prop'=>'8733', 'infin'=>'8734', 'ang'=>'8736', 'and'=>'8743', 'or'=>'8744', 'cap'=>'8745', 'cup'=>'8746', 'int'=>'8747', 'there4'=>'8756', 'sim'=>'8764', 'cong'=>'8773', 'asymp'=>'8776', 'ne'=>'8800', 'equiv'=>'8801', 'le'=>'8804', 'ge'=>'8805', 'sub'=>'8834', 'sup'=>'8835', 'nsub'=>'8836', 'sube'=>'8838', 'supe'=>'8839', 'oplus'=>'8853', 'otimes'=>'8855', 'perp'=>'8869', 'sdot'=>'8901', 'lceil'=>'8968', 'rceil'=>'8969', 'lfloor'=>'8970', 'rfloor'=>'8971', 'lang'=>'9001', 'rang'=>'9002', 'loz'=>'9674', 'spades'=>'9824', 'clubs'=>'9827', 'hearts'=>'9829', 'diams'=>'9830', 'apos'=>'39', 'OElig'=>'338', 'oelig'=>'339', 'Scaron'=>'352', 'scaron'=>'353', 'Yuml'=>'376', 'circ'=>'710', 'tilde'=>'732', 'ensp'=>'8194', 'emsp'=>'8195', 'thinsp'=>'8201', 'zwnj'=>'8204', 'zwj'=>'8205', 'lrm'=>'8206', 'rlm'=>'8207', 'ndash'=>'8211', 'mdash'=>'8212', 'lsquo'=>'8216', 'rsquo'=>'8217', 'sbquo'=>'8218', 'ldquo'=>'8220', 'rdquo'=>'8221', 'bdquo'=>'8222', 'dagger'=>'8224', 'Dagger'=>'8225', 'permil'=>'8240', 'lsaquo'=>'8249', 'rsaquo'=>'8250', 'euro'=>'8364', 'nbsp'=>'160', 'iexcl'=>'161', 'cent'=>'162', 'pound'=>'163', 'curren'=>'164', 'yen'=>'165', 'brvbar'=>'166', 'sect'=>'167', 'uml'=>'168', 'copy'=>'169', 'ordf'=>'170', 'laquo'=>'171', 'not'=>'172', 'shy'=>'173', 'reg'=>'174', 'macr'=>'175', 'deg'=>'176', 'plusmn'=>'177', 'sup2'=>'178', 'sup3'=>'179', 'acute'=>'180', 'micro'=>'181', 'para'=>'182', 'middot'=>'183', 'cedil'=>'184', 'sup1'=>'185', 'ordm'=>'186', 'raquo'=>'187', 'frac14'=>'188', 'frac12'=>'189', 'frac34'=>'190', 'iquest'=>'191', 'Agrave'=>'192', 'Aacute'=>'193', 'Acirc'=>'194', 'Atilde'=>'195', 'Auml'=>'196', 'Aring'=>'197', 'AElig'=>'198', 'Ccedil'=>'199', 'Egrave'=>'200', 'Eacute'=>'201', 'Ecirc'=>'202', 'Euml'=>'203', 'Igrave'=>'204', 'Iacute'=>'205', 'Icirc'=>'206', 'Iuml'=>'207', 'ETH'=>'208', 'Ntilde'=>'209', 'Ograve'=>'210', 'Oacute'=>'211', 'Ocirc'=>'212', 'Otilde'=>'213', 'Ouml'=>'214', 'times'=>'215', 'Oslash'=>'216', 'Ugrave'=>'217', 'Uacute'=>'218', 'Ucirc'=>'219', 'Uuml'=>'220', 'Yacute'=>'221', 'THORN'=>'222', 'szlig'=>'223', 'agrave'=>'224', 'aacute'=>'225', 'acirc'=>'226', 'atilde'=>'227', 'auml'=>'228', 'aring'=>'229', 'aelig'=>'230', 'ccedil'=>'231', 'egrave'=>'232', 'eacute'=>'233', 'ecirc'=>'234', 'euml'=>'235', 'igrave'=>'236', 'iacute'=>'237', 'icirc'=>'238', 'iuml'=>'239', 'eth'=>'240', 'ntilde'=>'241', 'ograve'=>'242', 'oacute'=>'243', 'ocirc'=>'244', 'otilde'=>'245', 'ouml'=>'246', 'divide'=>'247', 'oslash'=>'248', 'ugrave'=>'249', 'uacute'=>'250', 'ucirc'=>'251', 'uuml'=>'252', 'yacute'=>'253', 'thorn'=>'254', 'yuml'=>'255');
if($t[0] != '#'){ if($t[0] != '#'){
return ($C['and_mark'] ? "\x06" : '&'). (isset($U[$t]) ? $t : (isset($N[$t]) ? (!$C['named_entity'] ? '#'. ($C['hexdec_entity'] > 1 ? 'x'. dechex($N[$t]) : $N[$t]) : $t) : 'amp;'. $t)). ';'; return ($C['and_mark'] ? "\x06" : '&'). (isset($U[$t]) ? $t : (isset($N[$t]) ? (!$C['named_entity'] ? '#'. ($C['hexdec_entity'] > 1 ? 'x'. dechex($N[$t]) : $N[$t]) : $t) : 'amp;'. $t)). ';';
} }
if(($n = ctype_digit($t = substr($t, 1)) ? intval($t) : hexdec(substr($t, 1))) < 9 or ($n > 13 && $n < 32) or $n == 11 or $n == 12 or ($n > 126 && $n < 160 && $n != 133) or ($n > 55295 && ($n < 57344 or ($n > 64975 && $n < 64992) or $n == 65534 or $n == 65535 or $n > 1114111))){ if(($n = ctype_digit($t = substr($t, 1)) ? intval($t) : hexdec(substr($t, 1))) < 9 or ($n > 13 && $n < 32) or $n == 11 or $n == 12 or ($n > 126 && $n < 160 && $n != 133) or ($n > 55295 && ($n < 57344 or ($n > 64975 && $n < 64992) or $n == 65534 or $n == 65535 or $n > 1114111))){
return ($C['and_mark'] ? "\x06" : '&'). "amp;#{$t};"; return ($C['and_mark'] ? "\x06" : '&'). "amp;#{$t};";
} }
return ($C['and_mark'] ? "\x06" : '&'). '#'. (((ctype_digit($t) && $C['hexdec_entity'] < 2) or !$C['hexdec_entity']) ? $n : 'x'. dechex($n)). ';'; return ($C['and_mark'] ? "\x06" : '&'). '#'. (((ctype_digit($t) && $C['hexdec_entity'] < 2) or !$C['hexdec_entity']) ? $n : 'x'. dechex($n)). ';';
// eof // eof
} }
function hl_prot($p, $c=null){ function hl_prot($p, $c=null){
// check URL scheme // check URL scheme
global $C; global $C;
$b = $a = ''; $b = $a = '';
if($c == null){$c = 'style'; $b = $p[1]; $a = $p[3]; $p = trim($p[2]);} if($c == null){$c = 'style'; $b = $p[1]; $a = $p[3]; $p = trim($p[2]);}
$c = isset($C['schemes'][$c]) ? $C['schemes'][$c] : $C['schemes']['*']; $c = isset($C['schemes'][$c]) ? $C['schemes'][$c] : $C['schemes']['*'];
static $d = 'denied:'; static $d = 'denied:';
if(isset($c['!']) && substr($p, 0, 7) != $d){$p = "$d$p";} if(isset($c['!']) && substr($p, 0, 7) != $d){$p = "$d$p";}
if(isset($c['*']) or !strcspn($p, '#?;') or (substr($p, 0, 7) == $d)){return "{$b}{$p}{$a}";} // All ok, frag, query, param if(isset($c['*']) or !strcspn($p, '#?;') or (substr($p, 0, 7) == $d)){return "{$b}{$p}{$a}";} // All ok, frag, query, param
if(preg_match('`^([^:?[@!$()*,=/\'\]]+?)(:|&#(58|x3a);|%3a|\\\\0{0,4}3a).`i', $p, $m) && !isset($c[strtolower($m[1])])){ // Denied prot if(preg_match('`^([^:?[@!$()*,=/\'\]]+?)(:|&#(58|x3a);|%3a|\\\\0{0,4}3a).`i', $p, $m) && !isset($c[strtolower($m[1])])){ // Denied prot
return "{$b}{$d}{$p}{$a}"; return "{$b}{$d}{$p}{$a}";
} }
if($C['abs_url']){ if($C['abs_url']){
if($C['abs_url'] == -1 && strpos($p, $C['base_url']) === 0){ // Make url rel if($C['abs_url'] == -1 && strpos($p, $C['base_url']) === 0){ // Make url rel
$p = substr($p, strlen($C['base_url'])); $p = substr($p, strlen($C['base_url']));
}elseif(empty($m[1])){ // Make URL abs }elseif(empty($m[1])){ // Make URL abs
if(substr($p, 0, 2) == '//'){$p = substr($C['base_url'], 0, strpos($C['base_url'], ':')+1). $p;} if(substr($p, 0, 2) == '//'){$p = substr($C['base_url'], 0, strpos($C['base_url'], ':')+1). $p;}
elseif($p[0] == '/'){$p = preg_replace('`(^.+?://[^/]+)(.*)`', '$1', $C['base_url']). $p;} elseif($p[0] == '/'){$p = preg_replace('`(^.+?://[^/]+)(.*)`', '$1', $C['base_url']). $p;}
elseif(strcspn($p, './')){$p = $C['base_url']. $p;} elseif(strcspn($p, './')){$p = $C['base_url']. $p;}
else{ else{
preg_match('`^([a-zA-Z\d\-+.]+://[^/]+)(.*)`', $C['base_url'], $m); preg_match('`^([a-zA-Z\d\-+.]+://[^/]+)(.*)`', $C['base_url'], $m);
$p = preg_replace('`(?<=/)\./`', '', $m[2]. $p); $p = preg_replace('`(?<=/)\./`', '', $m[2]. $p);
while(preg_match('`(?<=/)([^/]{3,}|[^/.]+?|\.[^/.]|[^/.]\.)/\.\./`', $p)){ while(preg_match('`(?<=/)([^/]{3,}|[^/.]+?|\.[^/.]|[^/.]\.)/\.\./`', $p)){
$p = preg_replace('`(?<=/)([^/]{3,}|[^/.]+?|\.[^/.]|[^/.]\.)/\.\./`', '', $p); $p = preg_replace('`(?<=/)([^/]{3,}|[^/.]+?|\.[^/.]|[^/.]\.)/\.\./`', '', $p);
} }
$p = $m[1]. $p; $p = $m[1]. $p;
} }
} }
} }
return "{$b}{$p}{$a}"; return "{$b}{$p}{$a}";
// eof // eof
} }
function hl_regex($p){ function hl_regex($p){
// ?regex // ?regex
if(empty($p)){return 0;} if(empty($p)){return 0;}
if($t = ini_get('track_errors')){$o = isset($php_errormsg) ? $php_errormsg : null;} if($t = ini_get('track_errors')){$o = isset($php_errormsg) ? $php_errormsg : null;}
else{ini_set('track_errors', 1);} else{ini_set('track_errors', 1);}
unset($php_errormsg); unset($php_errormsg);
if(($d = ini_get('display_errors'))){ini_set('display_errors', 0);} if(($d = ini_get('display_errors'))){ini_set('display_errors', 0);}
preg_match($p, ''); preg_match($p, '');
if($d){ini_set('display_errors', 1);} if($d){ini_set('display_errors', 1);}
$r = isset($php_errormsg) ? 0 : 1; $r = isset($php_errormsg) ? 0 : 1;
if($t){$php_errormsg = isset($o) ? $o : null;} if($t){$php_errormsg = isset($o) ? $o : null;}
else{ini_set('track_errors', 0);} else{ini_set('track_errors', 0);}
return $r; return $r;
// eof // eof
} }
function hl_spec($t){ function hl_spec($t){
// final $spec // final $spec
$s = array(); $s = array();
$t = str_replace(array("\t", "\r", "\n", ' '), '', preg_replace_callback('/"(?>(`.|[^"])*)"/sm', create_function('$m', 'return substr(str_replace(array(";", "|", "~", " ", ",", "/", "(", ")", \'`"\'), array("\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\""), $m[0]), 1, -1);'), trim($t))); $t = str_replace(array("\t", "\r", "\n", ' '), '', preg_replace_callback('/"(?>(`.|[^"])*)"/sm', create_function('$m', 'return substr(str_replace(array(";", "|", "~", " ", ",", "/", "(", ")", \'`"\'), array("\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\""), $m[0]), 1, -1);'), trim($t)));
for($i = count(($t = explode(';', $t))); --$i>=0;){ for($i = count(($t = explode(';', $t))); --$i>=0;){
$w = $t[$i]; $w = $t[$i];
if(empty($w) or ($e = strpos($w, '=')) === false or !strlen(($a = substr($w, $e+1)))){continue;} if(empty($w) or ($e = strpos($w, '=')) === false or !strlen(($a = substr($w, $e+1)))){continue;}
$y = $n = array(); $y = $n = array();
foreach(explode(',', $a) as $v){ foreach(explode(',', $a) as $v){
if(!preg_match('`^([a-z:\-\*]+)(?:\((.*?)\))?`i', $v, $m)){continue;} if(!preg_match('`^([a-z:\-\*]+)(?:\((.*?)\))?`i', $v, $m)){continue;}
if(($x = strtolower($m[1])) == '-*'){$n['*'] = 1; continue;} if(($x = strtolower($m[1])) == '-*'){$n['*'] = 1; continue;}
if($x[0] == '-'){$n[substr($x, 1)] = 1; continue;} if($x[0] == '-'){$n[substr($x, 1)] = 1; continue;}
if(!isset($m[2])){$y[$x] = 1; continue;} if(!isset($m[2])){$y[$x] = 1; continue;}
foreach(explode('/', $m[2]) as $m){ foreach(explode('/', $m[2]) as $m){
if(empty($m) or ($p = strpos($m, '=')) == 0 or $p < 5){$y[$x] = 1; continue;} if(empty($m) or ($p = strpos($m, '=')) == 0 or $p < 5){$y[$x] = 1; continue;}
$y[$x][strtolower(substr($m, 0, $p))] = str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08"), array(";", "|", "~", " ", ",", "/", "(", ")"), substr($m, $p+1)); $y[$x][strtolower(substr($m, 0, $p))] = str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08"), array(";", "|", "~", " ", ",", "/", "(", ")"), substr($m, $p+1));
} }
if(isset($y[$x]['match']) && !hl_regex($y[$x]['match'])){unset($y[$x]['match']);} if(isset($y[$x]['match']) && !hl_regex($y[$x]['match'])){unset($y[$x]['match']);}
if(isset($y[$x]['nomatch']) && !hl_regex($y[$x]['nomatch'])){unset($y[$x]['nomatch']);} if(isset($y[$x]['nomatch']) && !hl_regex($y[$x]['nomatch'])){unset($y[$x]['nomatch']);}
} }
if(!count($y) && !count($n)){continue;} if(!count($y) && !count($n)){continue;}
foreach(explode(',', substr($w, 0, $e)) as $v){ foreach(explode(',', substr($w, 0, $e)) as $v){
if(!strlen(($v = strtolower($v)))){continue;} if(!strlen(($v = strtolower($v)))){continue;}
if(count($y)){$s[$v] = $y;} if(count($y)){$s[$v] = $y;}
if(count($n)){$s[$v]['n'] = $n;} if(count($n)){$s[$v]['n'] = $n;}
} }
} }
return $s; return $s;
// eof // eof
} }
function hl_tag($t){ function hl_tag($t){
// tag/attribute handler // tag/attribute handler
global $C; global $C;
$t = $t[0]; $t = $t[0];
// invalid < > // invalid < >
if($t == '< '){return '&lt; ';} if($t == '< '){return '&lt; ';}
if($t == '>'){return '&gt;';} if($t == '>'){return '&gt;';}
if(!preg_match('`^<(/?)([a-zA-Z][a-zA-Z1-6]*)([^>]*?)\s?>$`m', $t, $m)){ if(!preg_match('`^<(/?)([a-zA-Z][a-zA-Z1-6]*)([^>]*?)\s?>$`m', $t, $m)){
return str_replace(array('<', '>'), array('&lt;', '&gt;'), $t); return str_replace(array('<', '>'), array('&lt;', '&gt;'), $t);
}elseif(!isset($C['elements'][($e = strtolower($m[2]))])){ }elseif(!isset($C['elements'][($e = strtolower($m[2]))])){
return (($C['keep_bad']%2) ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : ''); return (($C['keep_bad']%2) ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : '');
} }
// attr string // attr string
$a = str_replace(array("\n", "\r", "\t"), ' ', trim($m[3])); $a = str_replace(array("\n", "\r", "\t"), ' ', trim($m[3]));
// tag transform // tag transform
static $eD = array('applet'=>1, 'center'=>1, 'dir'=>1, 'embed'=>1, 'font'=>1, 'isindex'=>1, 'menu'=>1, 's'=>1, 'strike'=>1, 'u'=>1); // Deprecated static $eD = array('applet'=>1, 'center'=>1, 'dir'=>1, 'embed'=>1, 'font'=>1, 'isindex'=>1, 'menu'=>1, 's'=>1, 'strike'=>1, 'u'=>1); // Deprecated
if($C['make_tag_strict'] && isset($eD[$e])){ if($C['make_tag_strict'] && isset($eD[$e])){
$trt = hl_tag2($e, $a, $C['make_tag_strict']); $trt = hl_tag2($e, $a, $C['make_tag_strict']);
if(!$e){return (($C['keep_bad']%2) ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : '');} if(!$e){return (($C['keep_bad']%2) ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : '');}
} }
// close tag // close tag
static $eE = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1); // Empty ele static $eE = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1); // Empty ele
if(!empty($m[1])){ if(!empty($m[1])){
return (!isset($eE[$e]) ? (empty($C['hook_tag']) ? "</$e>" : $C['hook_tag']($e)) : (($C['keep_bad'])%2 ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : '')); return (!isset($eE[$e]) ? (empty($C['hook_tag']) ? "</$e>" : $C['hook_tag']($e)) : (($C['keep_bad'])%2 ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : ''));
} }
// open tag & attr // open tag & attr
static $aN = array('abbr'=>array('td'=>1, 'th'=>1), 'accept-charset'=>array('form'=>1), 'accept'=>array('form'=>1, 'input'=>1), 'accesskey'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'legend'=>1, 'textarea'=>1), 'action'=>array('form'=>1), 'align'=>array('caption'=>1, 'embed'=>1, 'applet'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'legend'=>1, 'table'=>1, 'hr'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'p'=>1, 'col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'alt'=>array('applet'=>1, 'area'=>1, 'img'=>1, 'input'=>1), 'archive'=>array('applet'=>1, 'object'=>1), 'axis'=>array('td'=>1, 'th'=>1), 'bgcolor'=>array('embed'=>1, 'table'=>1, 'tr'=>1, 'td'=>1, 'th'=>1), 'border'=>array('table'=>1, 'img'=>1, 'object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'cellpadding'=>array('table'=>1), 'cellspacing'=>array('table'=>1), 'char'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charoff'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charset'=>array('a'=>1, 'script'=>1), 'checked'=>array('input'=>1), 'cite'=>array('blockquote'=>1, 'q'=>1, 'del'=>1, 'ins'=>1), 'classid'=>array('object'=>1), 'clear'=>array('br'=>1), 'code'=>array('applet'=>1), 'codebase'=>array('object'=>1, 'applet'=>1), 'codetype'=>array('object'=>1), 'color'=>array('font'=>1), 'cols'=>array('textarea'=>1), 'colspan'=>array('td'=>1, 'th'=>1), 'compact'=>array('dir'=>1, 'dl'=>1, 'menu'=>1, 'ol'=>1, 'ul'=>1), 'coords'=>array('area'=>1, 'a'=>1), 'data'=>array('object'=>1), 'datetime'=>array('del'=>1, 'ins'=>1), 'declare'=>array('object'=>1), 'defer'=>array('script'=>1), 'dir'=>array('bdo'=>1), 'disabled'=>array('button'=>1, 'input'=>1, 'optgroup'=>1, 'option'=>1, 'select'=>1, 'textarea'=>1), 'enctype'=>array('form'=>1), 'face'=>array('font'=>1), 'flashvars'=>array('embed'=>1), 'for'=>array('label'=>1), 'frame'=>array('table'=>1), 'frameborder'=>array('iframe'=>1), 'headers'=>array('td'=>1, 'th'=>1), 'height'=>array('embed'=>1, 'iframe'=>1, 'td'=>1, 'th'=>1, 'img'=>1, 'object'=>1, 'applet'=>1), 'href'=>array('a'=>1, 'area'=>1), 'hreflang'=>array('a'=>1), 'hspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'ismap'=>array('img'=>1, 'input'=>1), 'label'=>array('option'=>1, 'optgroup'=>1), 'language'=>array('script'=>1), 'longdesc'=>array('img'=>1, 'iframe'=>1), 'marginheight'=>array('iframe'=>1), 'marginwidth'=>array('iframe'=>1), 'maxlength'=>array('input'=>1), 'method'=>array('form'=>1), 'model'=>array('embed'=>1), 'multiple'=>array('select'=>1), 'name'=>array('button'=>1, 'embed'=>1, 'textarea'=>1, 'applet'=>1, 'select'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'a'=>1, 'input'=>1, 'object'=>1, 'map'=>1, 'param'=>1), 'nohref'=>array('area'=>1), 'noshade'=>array('hr'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'object'=>array('applet'=>1), 'onblur'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onchange'=>array('input'=>1, 'select'=>1, 'textarea'=>1), 'onfocus'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onreset'=>array('form'=>1), 'onselect'=>array('input'=>1, 'textarea'=>1), 'onsubmit'=>array('form'=>1), 'pluginspage'=>array('embed'=>1), 'pluginurl'=>array('embed'=>1), 'prompt'=>array('isindex'=>1), 'readonly'=>array('textarea'=>1, 'input'=>1), 'rel'=>array('a'=>1), 'rev'=>array('a'=>1), 'rows'=>array('textarea'=>1), 'rowspan'=>array('td'=>1, 'th'=>1), 'rules'=>array('table'=>1), 'scope'=>array('td'=>1, 'th'=>1), 'scrolling'=>array('iframe'=>1), 'selected'=>array('option'=>1), 'shape'=>array('area'=>1, 'a'=>1), 'size'=>array('hr'=>1, 'font'=>1, 'input'=>1, 'select'=>1), 'span'=>array('col'=>1, 'colgroup'=>1), 'src'=>array('embed'=>1, 'script'=>1, 'input'=>1, 'iframe'=>1, 'img'=>1), 'standby'=>array('object'=>1), 'start'=>array('ol'=>1), 'summary'=>array('table'=>1), 'tabindex'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'object'=>1, 'select'=>1, 'textarea'=>1), 'target'=>array('a'=>1, 'area'=>1, 'form'=>1), 'type'=>array('a'=>1, 'embed'=>1, 'object'=>1, 'param'=>1, 'script'=>1, 'input'=>1, 'li'=>1, 'ol'=>1, 'ul'=>1, 'button'=>1), 'usemap'=>array('img'=>1, 'input'=>1, 'object'=>1), 'valign'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'value'=>array('input'=>1, 'option'=>1, 'param'=>1, 'button'=>1, 'li'=>1), 'valuetype'=>array('param'=>1), 'vspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'width'=>array('embed'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'object'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'applet'=>1, 'col'=>1, 'colgroup'=>1, 'pre'=>1), 'wmode'=>array('embed'=>1), 'xml:space'=>array('pre'=>1, 'script'=>1, 'style'=>1)); // Ele-specific static $aN = array('abbr'=>array('td'=>1, 'th'=>1), 'accept-charset'=>array('form'=>1), 'accept'=>array('form'=>1, 'input'=>1), 'accesskey'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'legend'=>1, 'textarea'=>1), 'action'=>array('form'=>1), 'align'=>array('caption'=>1, 'embed'=>1, 'applet'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'legend'=>1, 'table'=>1, 'hr'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'p'=>1, 'col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'alt'=>array('applet'=>1, 'area'=>1, 'img'=>1, 'input'=>1), 'archive'=>array('applet'=>1, 'object'=>1), 'axis'=>array('td'=>1, 'th'=>1), 'bgcolor'=>array('embed'=>1, 'table'=>1, 'tr'=>1, 'td'=>1, 'th'=>1), 'border'=>array('table'=>1, 'img'=>1, 'object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'cellpadding'=>array('table'=>1), 'cellspacing'=>array('table'=>1), 'char'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charoff'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charset'=>array('a'=>1, 'script'=>1), 'checked'=>array('input'=>1), 'cite'=>array('blockquote'=>1, 'q'=>1, 'del'=>1, 'ins'=>1), 'classid'=>array('object'=>1), 'clear'=>array('br'=>1), 'code'=>array('applet'=>1), 'codebase'=>array('object'=>1, 'applet'=>1), 'codetype'=>array('object'=>1), 'color'=>array('font'=>1), 'cols'=>array('textarea'=>1), 'colspan'=>array('td'=>1, 'th'=>1), 'compact'=>array('dir'=>1, 'dl'=>1, 'menu'=>1, 'ol'=>1, 'ul'=>1), 'coords'=>array('area'=>1, 'a'=>1), 'data'=>array('object'=>1), 'datetime'=>array('del'=>1, 'ins'=>1), 'declare'=>array('object'=>1), 'defer'=>array('script'=>1), 'dir'=>array('bdo'=>1), 'disabled'=>array('button'=>1, 'input'=>1, 'optgroup'=>1, 'option'=>1, 'select'=>1, 'textarea'=>1), 'enctype'=>array('form'=>1), 'face'=>array('font'=>1), 'flashvars'=>array('embed'=>1), 'for'=>array('label'=>1), 'frame'=>array('table'=>1), 'frameborder'=>array('iframe'=>1), 'headers'=>array('td'=>1, 'th'=>1), 'height'=>array('embed'=>1, 'iframe'=>1, 'td'=>1, 'th'=>1, 'img'=>1, 'object'=>1, 'applet'=>1), 'href'=>array('a'=>1, 'area'=>1), 'hreflang'=>array('a'=>1), 'hspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'ismap'=>array('img'=>1, 'input'=>1), 'label'=>array('option'=>1, 'optgroup'=>1), 'language'=>array('script'=>1), 'longdesc'=>array('img'=>1, 'iframe'=>1), 'marginheight'=>array('iframe'=>1), 'marginwidth'=>array('iframe'=>1), 'maxlength'=>array('input'=>1), 'method'=>array('form'=>1), 'model'=>array('embed'=>1), 'multiple'=>array('select'=>1), 'name'=>array('button'=>1, 'embed'=>1, 'textarea'=>1, 'applet'=>1, 'select'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'a'=>1, 'input'=>1, 'object'=>1, 'map'=>1, 'param'=>1), 'nohref'=>array('area'=>1), 'noshade'=>array('hr'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'object'=>array('applet'=>1), 'onblur'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onchange'=>array('input'=>1, 'select'=>1, 'textarea'=>1), 'onfocus'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'onreset'=>array('form'=>1), 'onselect'=>array('input'=>1, 'textarea'=>1), 'onsubmit'=>array('form'=>1), 'pluginspage'=>array('embed'=>1), 'pluginurl'=>array('embed'=>1), 'prompt'=>array('isindex'=>1), 'readonly'=>array('textarea'=>1, 'input'=>1), 'rel'=>array('a'=>1), 'rev'=>array('a'=>1), 'rows'=>array('textarea'=>1), 'rowspan'=>array('td'=>1, 'th'=>1), 'rules'=>array('table'=>1), 'scope'=>array('td'=>1, 'th'=>1), 'scrolling'=>array('iframe'=>1), 'selected'=>array('option'=>1), 'shape'=>array('area'=>1, 'a'=>1), 'size'=>array('hr'=>1, 'font'=>1, 'input'=>1, 'select'=>1), 'span'=>array('col'=>1, 'colgroup'=>1), 'src'=>array('embed'=>1, 'script'=>1, 'input'=>1, 'iframe'=>1, 'img'=>1), 'standby'=>array('object'=>1), 'start'=>array('ol'=>1), 'summary'=>array('table'=>1), 'tabindex'=>array('a'=>1, 'area'=>1, 'button'=>1, 'input'=>1, 'object'=>1, 'select'=>1, 'textarea'=>1), 'target'=>array('a'=>1, 'area'=>1, 'form'=>1), 'type'=>array('a'=>1, 'embed'=>1, 'object'=>1, 'param'=>1, 'script'=>1, 'input'=>1, 'li'=>1, 'ol'=>1, 'ul'=>1, 'button'=>1), 'usemap'=>array('img'=>1, 'input'=>1, 'object'=>1), 'valign'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'value'=>array('input'=>1, 'option'=>1, 'param'=>1, 'button'=>1, 'li'=>1), 'valuetype'=>array('param'=>1), 'vspace'=>array('applet'=>1, 'img'=>1, 'object'=>1), 'width'=>array('embed'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'object'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'applet'=>1, 'col'=>1, 'colgroup'=>1, 'pre'=>1), 'wmode'=>array('embed'=>1), 'xml:space'=>array('pre'=>1, 'script'=>1, 'style'=>1)); // Ele-specific
static $aNE = array('checked'=>1, 'compact'=>1, 'declare'=>1, 'defer'=>1, 'disabled'=>1, 'ismap'=>1, 'multiple'=>1, 'nohref'=>1, 'noresize'=>1, 'noshade'=>1, 'nowrap'=>1, 'readonly'=>1, 'selected'=>1); // Empty static $aNE = array('checked'=>1, 'compact'=>1, 'declare'=>1, 'defer'=>1, 'disabled'=>1, 'ismap'=>1, 'multiple'=>1, 'nohref'=>1, 'noresize'=>1, 'noshade'=>1, 'nowrap'=>1, 'readonly'=>1, 'selected'=>1); // Empty
static $aNP = array('action'=>1, 'cite'=>1, 'classid'=>1, 'codebase'=>1, 'data'=>1, 'href'=>1, 'longdesc'=>1, 'model'=>1, 'pluginspage'=>1, 'pluginurl'=>1, 'usemap'=>1); // Need scheme check; excludes style, on* & src static $aNP = array('action'=>1, 'cite'=>1, 'classid'=>1, 'codebase'=>1, 'data'=>1, 'href'=>1, 'longdesc'=>1, 'model'=>1, 'pluginspage'=>1, 'pluginurl'=>1, 'usemap'=>1); // Need scheme check; excludes style, on* & src
static $aNU = array('class'=>array('param'=>1, 'script'=>1), 'dir'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'id'=>array('script'=>1), 'lang'=>array('applet'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'xml:lang'=>array('applet'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'onclick'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'ondblclick'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeydown'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeypress'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeyup'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmousedown'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmousemove'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseout'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseover'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseup'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'style'=>array('param'=>1, 'script'=>1), 'title'=>array('param'=>1, 'script'=>1)); // Univ & exceptions static $aNU = array('class'=>array('param'=>1, 'script'=>1), 'dir'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'id'=>array('script'=>1), 'lang'=>array('applet'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'xml:lang'=>array('applet'=>1, 'br'=>1, 'iframe'=>1, 'param'=>1, 'script'=>1), 'onclick'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'ondblclick'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeydown'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeypress'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onkeyup'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmousedown'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmousemove'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseout'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseover'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'onmouseup'=>array('applet'=>1, 'bdo'=>1, 'br'=>1, 'font'=>1, 'iframe'=>1, 'isindex'=>1, 'param'=>1, 'script'=>1), 'style'=>array('param'=>1, 'script'=>1), 'title'=>array('param'=>1, 'script'=>1)); // Univ & exceptions
if($C['lc_std_val']){ if($C['lc_std_val']){
// predef attr vals for $eAL & $aNE ele // predef attr vals for $eAL & $aNE ele
static $aNL = array('all'=>1, 'baseline'=>1, 'bottom'=>1, 'button'=>1, 'center'=>1, 'char'=>1, 'checkbox'=>1, 'circle'=>1, 'col'=>1, 'colgroup'=>1, 'cols'=>1, 'data'=>1, 'default'=>1, 'file'=>1, 'get'=>1, 'groups'=>1, 'hidden'=>1, 'image'=>1, 'justify'=>1, 'left'=>1, 'ltr'=>1, 'middle'=>1, 'none'=>1, 'object'=>1, 'password'=>1, 'poly'=>1, 'post'=>1, 'preserve'=>1, 'radio'=>1, 'rect'=>1, 'ref'=>1, 'reset'=>1, 'right'=>1, 'row'=>1, 'rowgroup'=>1, 'rows'=>1, 'rtl'=>1, 'submit'=>1, 'text'=>1, 'top'=>1); static $aNL = array('all'=>1, 'baseline'=>1, 'bottom'=>1, 'button'=>1, 'center'=>1, 'char'=>1, 'checkbox'=>1, 'circle'=>1, 'col'=>1, 'colgroup'=>1, 'cols'=>1, 'data'=>1, 'default'=>1, 'file'=>1, 'get'=>1, 'groups'=>1, 'hidden'=>1, 'image'=>1, 'justify'=>1, 'left'=>1, 'ltr'=>1, 'middle'=>1, 'none'=>1, 'object'=>1, 'password'=>1, 'poly'=>1, 'post'=>1, 'preserve'=>1, 'radio'=>1, 'rect'=>1, 'ref'=>1, 'reset'=>1, 'right'=>1, 'row'=>1, 'rowgroup'=>1, 'rows'=>1, 'rtl'=>1, 'submit'=>1, 'text'=>1, 'top'=>1);
static $eAL = array('a'=>1, 'area'=>1, 'bdo'=>1, 'button'=>1, 'col'=>1, 'form'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'optgroup'=>1, 'option'=>1, 'param'=>1, 'script'=>1, 'select'=>1, 'table'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1, 'xml:space'=>1); static $eAL = array('a'=>1, 'area'=>1, 'bdo'=>1, 'button'=>1, 'col'=>1, 'form'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'optgroup'=>1, 'option'=>1, 'param'=>1, 'script'=>1, 'select'=>1, 'table'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1, 'xml:space'=>1);
$lcase = isset($eAL[$e]) ? 1 : 0; $lcase = isset($eAL[$e]) ? 1 : 0;
} }
$depTr = 0; $depTr = 0;
if($C['no_deprecated_attr']){ if($C['no_deprecated_attr']){
// dep attr:applicable ele // dep attr:applicable ele
static $aND = array('align'=>array('caption'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'legend'=>1, 'object'=>1, 'p'=>1, 'table'=>1), 'bgcolor'=>array('table'=>1, 'td'=>1, 'th'=>1, 'tr'=>1), 'border'=>array('img'=>1, 'object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'clear'=>array('br'=>1), 'compact'=>array('dl'=>1, 'ol'=>1, 'ul'=>1), 'height'=>array('td'=>1, 'th'=>1), 'hspace'=>array('img'=>1, 'object'=>1), 'language'=>array('script'=>1), 'name'=>array('a'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'map'=>1), 'noshade'=>array('hr'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'size'=>array('hr'=>1), 'start'=>array('ol'=>1), 'type'=>array('li'=>1, 'ol'=>1, 'ul'=>1), 'value'=>array('li'=>1), 'vspace'=>array('img'=>1, 'object'=>1), 'width'=>array('hr'=>1, 'pre'=>1, 'td'=>1, 'th'=>1)); static $aND = array('align'=>array('caption'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'legend'=>1, 'object'=>1, 'p'=>1, 'table'=>1), 'bgcolor'=>array('table'=>1, 'td'=>1, 'th'=>1, 'tr'=>1), 'border'=>array('img'=>1, 'object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'clear'=>array('br'=>1), 'compact'=>array('dl'=>1, 'ol'=>1, 'ul'=>1), 'height'=>array('td'=>1, 'th'=>1), 'hspace'=>array('img'=>1, 'object'=>1), 'language'=>array('script'=>1), 'name'=>array('a'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'map'=>1), 'noshade'=>array('hr'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'size'=>array('hr'=>1), 'start'=>array('ol'=>1), 'type'=>array('li'=>1, 'ol'=>1, 'ul'=>1), 'value'=>array('li'=>1), 'vspace'=>array('img'=>1, 'object'=>1), 'width'=>array('hr'=>1, 'pre'=>1, 'td'=>1, 'th'=>1));
static $eAD = array('a'=>1, 'br'=>1, 'caption'=>1, 'div'=>1, 'dl'=>1, 'form'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'legend'=>1, 'li'=>1, 'map'=>1, 'object'=>1, 'ol'=>1, 'p'=>1, 'pre'=>1, 'script'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'tr'=>1, 'ul'=>1); static $eAD = array('a'=>1, 'br'=>1, 'caption'=>1, 'div'=>1, 'dl'=>1, 'form'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'legend'=>1, 'li'=>1, 'map'=>1, 'object'=>1, 'ol'=>1, 'p'=>1, 'pre'=>1, 'script'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'tr'=>1, 'ul'=>1);
$depTr = isset($eAD[$e]) ? 1 : 0; $depTr = isset($eAD[$e]) ? 1 : 0;
} }
// attr name-vals // attr name-vals
if(strpos($a, "\x01") !== false){$a = preg_replace('`\x01[^\x01]*\x01`', '', $a);} // No comment/CDATA sec if(strpos($a, "\x01") !== false){$a = preg_replace('`\x01[^\x01]*\x01`', '', $a);} // No comment/CDATA sec
$mode = 0; $a = trim($a, ' /'); $aA = array(); $mode = 0; $a = trim($a, ' /'); $aA = array();
while(strlen($a)){ while(strlen($a)){
$w = 0; $w = 0;
switch($mode){ switch($mode){
case 0: // Name case 0: // Name
if(preg_match('`^[a-zA-Z][\-a-zA-Z:]+`', $a, $m)){ if(preg_match('`^[a-zA-Z][\-a-zA-Z:]+`', $a, $m)){
$nm = strtolower($m[0]); $nm = strtolower($m[0]);
$w = $mode = 1; $a = ltrim(substr_replace($a, '', 0, strlen($m[0]))); $w = $mode = 1; $a = ltrim(substr_replace($a, '', 0, strlen($m[0])));
} }
break; case 1: break; case 1:
if($a[0] == '='){ // = if($a[0] == '='){ // =
$w = 1; $mode = 2; $a = ltrim($a, '= '); $w = 1; $mode = 2; $a = ltrim($a, '= ');
}else{ // No val }else{ // No val
$w = 1; $mode = 0; $a = ltrim($a); $w = 1; $mode = 0; $a = ltrim($a);
$aA[$nm] = ''; $aA[$nm] = '';
} }
break; case 2: // Val break; case 2: // Val
if(preg_match('`^((?:"[^"]*")|(?:\'[^\']*\')|(?:\s*[^\s"\']+))(.*)`', $a, $m)){ if(preg_match('`^((?:"[^"]*")|(?:\'[^\']*\')|(?:\s*[^\s"\']+))(.*)`', $a, $m)){
$a = ltrim($m[2]); $m = $m[1]; $w = 1; $mode = 0; $a = ltrim($m[2]); $m = $m[1]; $w = 1; $mode = 0;
$aA[$nm] = trim(($m[0] == '"' or $m[0] == '\'') ? substr($m, 1, -1) : $m); $aA[$nm] = trim(($m[0] == '"' or $m[0] == '\'') ? substr($m, 1, -1) : $m);
} }
break; break;
} }
if($w == 0){ // Parse errs, deal with space, " & ' if($w == 0){ // Parse errs, deal with space, " & '
$a = preg_replace('`^(?:"[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*`', '', $a); $a = preg_replace('`^(?:"[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*`', '', $a);
$mode = 0; $mode = 0;
} }
} }
if($mode == 1){$aA[$nm] = '';} if($mode == 1){$aA[$nm] = '';}
// clean attrs // clean attrs
global $S; global $S;
$rl = isset($S[$e]) ? $S[$e] : array(); $rl = isset($S[$e]) ? $S[$e] : array();
$a = array(); $nfr = 0; $a = array(); $nfr = 0;
foreach($aA as $k=>$v){ foreach($aA as $k=>$v){
if(((isset($C['deny_attribute']['*']) ? isset($C['deny_attribute'][$k]) : !isset($C['deny_attribute'][$k])) && (isset($aN[$k][$e]) or (isset($aNU[$k]) && !isset($aNU[$k][$e]))) && !isset($rl['n'][$k]) && !isset($rl['n']['*'])) or isset($rl[$k])){ if(((isset($C['deny_attribute']['*']) ? isset($C['deny_attribute'][$k]) : !isset($C['deny_attribute'][$k])) && (isset($aN[$k][$e]) or (isset($aNU[$k]) && !isset($aNU[$k][$e]))) && !isset($rl['n'][$k]) && !isset($rl['n']['*'])) or isset($rl[$k])){
if(isset($aNE[$k])){$v = $k;} if(isset($aNE[$k])){$v = $k;}
elseif(!empty($lcase) && (($e != 'button' or $e != 'input') or $k == 'type')){ // Rather loose but ?not cause issues elseif(!empty($lcase) && (($e != 'button' or $e != 'input') or $k == 'type')){ // Rather loose but ?not cause issues
$v = (isset($aNL[($v2 = strtolower($v))])) ? $v2 : $v; $v = (isset($aNL[($v2 = strtolower($v))])) ? $v2 : $v;
} }
if($k == 'style' && !$C['style_pass']){ if($k == 'style' && !$C['style_pass']){
if(false !== strpos($v, '&#')){ if(false !== strpos($v, '&#')){
static $sC = array('&#x20;'=>' ', '&#32;'=>' ', '&#x45;'=>'e', '&#69;'=>'e', '&#x65;'=>'e', '&#101;'=>'e', '&#x58;'=>'x', '&#88;'=>'x', '&#x78;'=>'x', '&#120;'=>'x', '&#x50;'=>'p', '&#80;'=>'p', '&#x70;'=>'p', '&#112;'=>'p', '&#x53;'=>'s', '&#83;'=>'s', '&#x73;'=>'s', '&#115;'=>'s', '&#x49;'=>'i', '&#73;'=>'i', '&#x69;'=>'i', '&#105;'=>'i', '&#x4f;'=>'o', '&#79;'=>'o', '&#x6f;'=>'o', '&#111;'=>'o', '&#x4e;'=>'n', '&#78;'=>'n', '&#x6e;'=>'n', '&#110;'=>'n', '&#x55;'=>'u', '&#85;'=>'u', '&#x75;'=>'u', '&#117;'=>'u', '&#x52;'=>'r', '&#82;'=>'r', '&#x72;'=>'r', '&#114;'=>'r', '&#x4c;'=>'l', '&#76;'=>'l', '&#x6c;'=>'l', '&#108;'=>'l', '&#x28;'=>'(', '&#40;'=>'(', '&#x29;'=>')', '&#41;'=>')', '&#x20;'=>':', '&#32;'=>':', '&#x22;'=>'"', '&#34;'=>'"', '&#x27;'=>"'", '&#39;'=>"'", '&#x2f;'=>'/', '&#47;'=>'/', '&#x2a;'=>'*', '&#42;'=>'*', '&#x5c;'=>'\\', '&#92;'=>'\\'); static $sC = array('&#x20;'=>' ', '&#32;'=>' ', '&#x45;'=>'e', '&#69;'=>'e', '&#x65;'=>'e', '&#101;'=>'e', '&#x58;'=>'x', '&#88;'=>'x', '&#x78;'=>'x', '&#120;'=>'x', '&#x50;'=>'p', '&#80;'=>'p', '&#x70;'=>'p', '&#112;'=>'p', '&#x53;'=>'s', '&#83;'=>'s', '&#x73;'=>'s', '&#115;'=>'s', '&#x49;'=>'i', '&#73;'=>'i', '&#x69;'=>'i', '&#105;'=>'i', '&#x4f;'=>'o', '&#79;'=>'o', '&#x6f;'=>'o', '&#111;'=>'o', '&#x4e;'=>'n', '&#78;'=>'n', '&#x6e;'=>'n', '&#110;'=>'n', '&#x55;'=>'u', '&#85;'=>'u', '&#x75;'=>'u', '&#117;'=>'u', '&#x52;'=>'r', '&#82;'=>'r', '&#x72;'=>'r', '&#114;'=>'r', '&#x4c;'=>'l', '&#76;'=>'l', '&#x6c;'=>'l', '&#108;'=>'l', '&#x28;'=>'(', '&#40;'=>'(', '&#x29;'=>')', '&#41;'=>')', '&#x20;'=>':', '&#32;'=>':', '&#x22;'=>'"', '&#34;'=>'"', '&#x27;'=>"'", '&#39;'=>"'", '&#x2f;'=>'/', '&#47;'=>'/', '&#x2a;'=>'*', '&#42;'=>'*', '&#x5c;'=>'\\', '&#92;'=>'\\');
$v = strtr($v, $sC); $v = strtr($v, $sC);
} }
$v = preg_replace_callback('`(url(?:\()(?: )*(?:\'|"|&(?:quot|apos);)?)(.+?)((?:\'|"|&(?:quot|apos);)?(?: )*(?:\)))`iS', 'hl_prot', $v); $v = preg_replace_callback('`(url(?:\()(?: )*(?:\'|"|&(?:quot|apos);)?)(.+?)((?:\'|"|&(?:quot|apos);)?(?: )*(?:\)))`iS', 'hl_prot', $v);
$v = !$C['css_expression'] ? preg_replace('`expression`i', ' ', preg_replace('`\\\\\S|(/|(%2f))(\*|(%2a))`i', ' ', $v)) : $v; $v = !$C['css_expression'] ? preg_replace('`expression`i', ' ', preg_replace('`\\\\\S|(/|(%2f))(\*|(%2a))`i', ' ', $v)) : $v;
}elseif(isset($aNP[$k]) or strpos($k, 'src') !== false or $k[0] == 'o'){ }elseif(isset($aNP[$k]) or strpos($k, 'src') !== false or $k[0] == 'o'){
$v = str_replace("\xad", ' ', (strpos($v, '&') !== false ? str_replace(array('&#xad;', '&#173;', '&shy;'), ' ', $v) : $v)); $v = str_replace("\xad", ' ', (strpos($v, '&') !== false ? str_replace(array('&#xad;', '&#173;', '&shy;'), ' ', $v) : $v));
$v = hl_prot($v, $k); $v = hl_prot($v, $k);
if($k == 'href'){ // X-spam if($k == 'href'){ // X-spam
if($C['anti_mail_spam'] && strpos($v, 'mailto:') === 0){ if($C['anti_mail_spam'] && strpos($v, 'mailto:') === 0){
$v = str_replace('@', htmlspecialchars($C['anti_mail_spam']), $v); $v = str_replace('@', htmlspecialchars($C['anti_mail_spam']), $v);
}elseif($C['anti_link_spam']){ }elseif($C['anti_link_spam']){
$r1 = $C['anti_link_spam'][1]; $r1 = $C['anti_link_spam'][1];
if(!empty($r1) && preg_match($r1, $v)){continue;} if(!empty($r1) && preg_match($r1, $v)){continue;}
$r0 = $C['anti_link_spam'][0]; $r0 = $C['anti_link_spam'][0];
if(!empty($r0) && preg_match($r0, $v)){ if(!empty($r0) && preg_match($r0, $v)){
if(isset($a['rel'])){ if(isset($a['rel'])){
if(!preg_match('`\bnofollow\b`i', $a['rel'])){$a['rel'] .= ' nofollow';} if(!preg_match('`\bnofollow\b`i', $a['rel'])){$a['rel'] .= ' nofollow';}
}elseif(isset($aA['rel'])){ }elseif(isset($aA['rel'])){
if(!preg_match('`\bnofollow\b`i', $aA['rel'])){$nfr = 1;} if(!preg_match('`\bnofollow\b`i', $aA['rel'])){$nfr = 1;}
}else{$a['rel'] = 'nofollow';} }else{$a['rel'] = 'nofollow';}
} }
} }
} }
} }
if(isset($rl[$k]) && is_array($rl[$k]) && ($v = hl_attrval($v, $rl[$k])) === 0){continue;} if(isset($rl[$k]) && is_array($rl[$k]) && ($v = hl_attrval($v, $rl[$k])) === 0){continue;}
$a[$k] = str_replace('"', '&quot;', $v); $a[$k] = str_replace('"', '&quot;', $v);
} }
} }
if($nfr){$a['rel'] = isset($a['rel']) ? $a['rel']. ' nofollow' : 'nofollow';} if($nfr){$a['rel'] = isset($a['rel']) ? $a['rel']. ' nofollow' : 'nofollow';}
// rqd attr // rqd attr
static $eAR = array('area'=>array('alt'=>'area'), 'bdo'=>array('dir'=>'ltr'), 'form'=>array('action'=>''), 'img'=>array('src'=>'', 'alt'=>'image'), 'map'=>array('name'=>''), 'optgroup'=>array('label'=>''), 'param'=>array('name'=>''), 'script'=>array('type'=>'text/javascript'), 'textarea'=>array('rows'=>'10', 'cols'=>'50')); static $eAR = array('area'=>array('alt'=>'area'), 'bdo'=>array('dir'=>'ltr'), 'form'=>array('action'=>''), 'img'=>array('src'=>'', 'alt'=>'image'), 'map'=>array('name'=>''), 'optgroup'=>array('label'=>''), 'param'=>array('name'=>''), 'script'=>array('type'=>'text/javascript'), 'textarea'=>array('rows'=>'10', 'cols'=>'50'));
if(isset($eAR[$e])){ if(isset($eAR[$e])){
foreach($eAR[$e] as $k=>$v){ foreach($eAR[$e] as $k=>$v){
if(!isset($a[$k])){$a[$k] = isset($v[0]) ? $v : $k;} if(!isset($a[$k])){$a[$k] = isset($v[0]) ? $v : $k;}
} }
} }
// depr attrs // depr attrs
if($depTr){ if($depTr){
$c = array(); $c = array();
foreach($a as $k=>$v){ foreach($a as $k=>$v){
if($k == 'style' or !isset($aND[$k][$e])){continue;} if($k == 'style' or !isset($aND[$k][$e])){continue;}
if($k == 'align'){ if($k == 'align'){
unset($a['align']); unset($a['align']);
if($e == 'img' && ($v == 'left' or $v == 'right')){$c[] = 'float: '. $v;} if($e == 'img' && ($v == 'left' or $v == 'right')){$c[] = 'float: '. $v;}
elseif(($e == 'div' or $e == 'table') && $v == 'center'){$c[] = 'margin: auto';} elseif(($e == 'div' or $e == 'table') && $v == 'center'){$c[] = 'margin: auto';}
else{$c[] = 'text-align: '. $v;} else{$c[] = 'text-align: '. $v;}
}elseif($k == 'bgcolor'){ }elseif($k == 'bgcolor'){
unset($a['bgcolor']); unset($a['bgcolor']);
$c[] = 'background-color: '. $v; $c[] = 'background-color: '. $v;
}elseif($k == 'border'){ }elseif($k == 'border'){
unset($a['border']); $c[] = "border: {$v}px"; unset($a['border']); $c[] = "border: {$v}px";
}elseif($k == 'bordercolor'){ }elseif($k == 'bordercolor'){
unset($a['bordercolor']); $c[] = 'border-color: '. $v; unset($a['bordercolor']); $c[] = 'border-color: '. $v;
}elseif($k == 'clear'){ }elseif($k == 'clear'){
unset($a['clear']); $c[] = 'clear: '. ($v != 'all' ? $v : 'both'); unset($a['clear']); $c[] = 'clear: '. ($v != 'all' ? $v : 'both');
}elseif($k == 'compact'){ }elseif($k == 'compact'){
unset($a['compact']); $c[] = 'font-size: 85%'; unset($a['compact']); $c[] = 'font-size: 85%';
}elseif($k == 'height' or $k == 'width'){ }elseif($k == 'height' or $k == 'width'){
unset($a[$k]); $c[] = $k. ': '. ($v[0] != '*' ? $v. (ctype_digit($v) ? 'px' : '') : 'auto'); unset($a[$k]); $c[] = $k. ': '. ($v[0] != '*' ? $v. (ctype_digit($v) ? 'px' : '') : 'auto');
}elseif($k == 'hspace'){ }elseif($k == 'hspace'){
unset($a['hspace']); $c[] = "margin-left: {$v}px; margin-right: {$v}px"; unset($a['hspace']); $c[] = "margin-left: {$v}px; margin-right: {$v}px";
}elseif($k == 'language' && !isset($a['type'])){ }elseif($k == 'language' && !isset($a['type'])){
unset($a['language']); unset($a['language']);
$a['type'] = 'text/'. strtolower($v); $a['type'] = 'text/'. strtolower($v);
}elseif($k == 'name'){ }elseif($k == 'name'){
if($C['no_deprecated_attr'] == 2 or ($e != 'a' && $e != 'map')){unset($a['name']);} if($C['no_deprecated_attr'] == 2 or ($e != 'a' && $e != 'map')){unset($a['name']);}
if(!isset($a['id']) && preg_match('`[a-zA-Z][a-zA-Z\d.:_\-]*`', $v)){$a['id'] = $v;} if(!isset($a['id']) && preg_match('`[a-zA-Z][a-zA-Z\d.:_\-]*`', $v)){$a['id'] = $v;}
}elseif($k == 'noshade'){ }elseif($k == 'noshade'){
unset($a['noshade']); $c[] = 'border-style: none; border: 0; background-color: gray; color: gray'; unset($a['noshade']); $c[] = 'border-style: none; border: 0; background-color: gray; color: gray';
}elseif($k == 'nowrap'){ }elseif($k == 'nowrap'){
unset($a['nowrap']); $c[] = 'white-space: nowrap'; unset($a['nowrap']); $c[] = 'white-space: nowrap';
}elseif($k == 'size'){ }elseif($k == 'size'){
unset($a['size']); $c[] = 'size: '. $v. 'px'; unset($a['size']); $c[] = 'size: '. $v. 'px';
}elseif($k == 'start' or $k == 'value'){ }elseif($k == 'start' or $k == 'value'){
unset($a[$k]); unset($a[$k]);
}elseif($k == 'type'){ }elseif($k == 'type'){
unset($a['type']); unset($a['type']);
static $ol_type = array('i'=>'lower-roman', 'I'=>'upper-roman', 'a'=>'lower-latin', 'A'=>'upper-latin', '1'=>'decimal'); static $ol_type = array('i'=>'lower-roman', 'I'=>'upper-roman', 'a'=>'lower-latin', 'A'=>'upper-latin', '1'=>'decimal');
$c[] = 'list-style-type: '. (isset($ol_type[$v]) ? $ol_type[$v] : 'decimal'); $c[] = 'list-style-type: '. (isset($ol_type[$v]) ? $ol_type[$v] : 'decimal');
}elseif($k == 'vspace'){ }elseif($k == 'vspace'){
unset($a['vspace']); $c[] = "margin-top: {$v}px; margin-bottom: {$v}px"; unset($a['vspace']); $c[] = "margin-top: {$v}px; margin-bottom: {$v}px";
} }
} }
if(count($c)){ if(count($c)){
$c = implode('; ', $c); $c = implode('; ', $c);
$a['style'] = isset($a['style']) ? rtrim($a['style'], ' ;'). '; '. $c. ';': $c. ';'; $a['style'] = isset($a['style']) ? rtrim($a['style'], ' ;'). '; '. $c. ';': $c. ';';
} }
} }
// unique ID // unique ID
if($C['unique_ids'] && isset($a['id'])){ if($C['unique_ids'] && isset($a['id'])){
if(!preg_match('`^[A-Za-z][A-Za-z0-9_\-.:]*$`', ($id = $a['id'])) or (isset($GLOBALS['hl_Ids'][$id]) && $C['unique_ids'] == 1)){unset($a['id']); if(!preg_match('`^[A-Za-z][A-Za-z0-9_\-.:]*$`', ($id = $a['id'])) or (isset($GLOBALS['hl_Ids'][$id]) && $C['unique_ids'] == 1)){unset($a['id']);
}else{ }else{
while(isset($GLOBALS['hl_Ids'][$id])){$id = $C['unique_ids']. $id;} while(isset($GLOBALS['hl_Ids'][$id])){$id = $C['unique_ids']. $id;}
$GLOBALS['hl_Ids'][($a['id'] = $id)] = 1; $GLOBALS['hl_Ids'][($a['id'] = $id)] = 1;
} }
} }
// xml:lang // xml:lang
if($C['xml:lang'] && isset($a['lang'])){ if($C['xml:lang'] && isset($a['lang'])){
$a['xml:lang'] = isset($a['xml:lang']) ? $a['xml:lang'] : $a['lang']; $a['xml:lang'] = isset($a['xml:lang']) ? $a['xml:lang'] : $a['lang'];
if($C['xml:lang'] == 2){unset($a['lang']);} if($C['xml:lang'] == 2){unset($a['lang']);}
} }
// for transformed tag // for transformed tag
if(!empty($trt)){ if(!empty($trt)){
$a['style'] = isset($a['style']) ? rtrim($a['style'], ' ;'). '; '. $trt : $trt; $a['style'] = isset($a['style']) ? rtrim($a['style'], ' ;'). '; '. $trt : $trt;
} }
// return with empty ele / // return with empty ele /
if(empty($C['hook_tag'])){ if(empty($C['hook_tag'])){
$aA = ''; $aA = '';
foreach($a as $k=>$v){$aA .= " {$k}=\"{$v}\"";} foreach($a as $k=>$v){$aA .= " {$k}=\"{$v}\"";}
return "<{$e}{$aA}". (isset($eE[$e]) ? ' /' : ''). '>'; return "<{$e}{$aA}". (isset($eE[$e]) ? ' /' : ''). '>';
} }
else{return $C['hook_tag']($e, $a);} else{return $C['hook_tag']($e, $a);}
// eof // eof
} }
function hl_tag2(&$e, &$a, $t=1){ function hl_tag2(&$e, &$a, $t=1){
// transform tag // transform tag
if($e == 'center'){$e = 'div'; return 'text-align: center;';} if($e == 'center'){$e = 'div'; return 'text-align: center;';}
if($e == 'dir' or $e == 'menu'){$e = 'ul'; return '';} if($e == 'dir' or $e == 'menu'){$e = 'ul'; return '';}
if($e == 's' or $e == 'strike'){$e = 'span'; return 'text-decoration: line-through;';} if($e == 's' or $e == 'strike'){$e = 'span'; return 'text-decoration: line-through;';}
if($e == 'u'){$e = 'span'; return 'text-decoration: underline;';} if($e == 'u'){$e = 'span'; return 'text-decoration: underline;';}
static $fs = array('0'=>'xx-small', '1'=>'xx-small', '2'=>'small', '3'=>'medium', '4'=>'large', '5'=>'x-large', '6'=>'xx-large', '7'=>'300%', '-1'=>'smaller', '-2'=>'60%', '+1'=>'larger', '+2'=>'150%', '+3'=>'200%', '+4'=>'300%'); static $fs = array('0'=>'xx-small', '1'=>'xx-small', '2'=>'small', '3'=>'medium', '4'=>'large', '5'=>'x-large', '6'=>'xx-large', '7'=>'300%', '-1'=>'smaller', '-2'=>'60%', '+1'=>'larger', '+2'=>'150%', '+3'=>'200%', '+4'=>'300%');
if($e == 'font'){ if($e == 'font'){
$a2 = ''; $a2 = '';
if(preg_match('`face\s*=\s*(\'|")([^=]+?)\\1`i', $a, $m) or preg_match('`face\s*=(\s*)(\S+)`i', $a, $m)){ if(preg_match('`face\s*=\s*(\'|")([^=]+?)\\1`i', $a, $m) or preg_match('`face\s*=(\s*)(\S+)`i', $a, $m)){
$a2 .= ' font-family: '. str_replace('"', '\'', trim($m[2])). ';'; $a2 .= ' font-family: '. str_replace('"', '\'', trim($m[2])). ';';
} }
if(preg_match('`color\s*=\s*(\'|")?(.+?)(\\1|\s|$)`i', $a, $m)){ if(preg_match('`color\s*=\s*(\'|")?(.+?)(\\1|\s|$)`i', $a, $m)){
$a2 .= ' color: '. trim($m[2]). ';'; $a2 .= ' color: '. trim($m[2]). ';';
} }
if(preg_match('`size\s*=\s*(\'|")?(.+?)(\\1|\s|$)`i', $a, $m) && isset($fs[($m = trim($m[2]))])){ if(preg_match('`size\s*=\s*(\'|")?(.+?)(\\1|\s|$)`i', $a, $m) && isset($fs[($m = trim($m[2]))])){
$a2 .= ' font-size: '. $fs[$m]. ';'; $a2 .= ' font-size: '. $fs[$m]. ';';
} }
$e = 'span'; return ltrim($a2); $e = 'span'; return ltrim($a2);
} }
if($t == 2){$e = 0; return 0;} if($t == 2){$e = 0; return 0;}
return ''; return '';
// eof // eof
} }
function hl_tidy($t, $w, $p){ function hl_tidy($t, $w, $p){
// Tidy/compact HTM // Tidy/compact HTM
if(strpos(' pre,script,textarea', "$p,")){return $t;} if(strpos(' pre,script,textarea', "$p,")){return $t;}
$t = preg_replace('`\s+`', ' ', preg_replace_callback(array('`(<(!\[CDATA\[))(.+?)(\]\]>)`sm', '`(<(!--))(.+?)(-->)`sm', '`(<(pre|script|textarea)[^>]*?>)(.+?)(</\2>)`sm'), create_function('$m', 'return $m[1]. str_replace(array("<", ">", "\n", "\r", "\t", " "), array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), $m[3]). $m[4];'), $t)); $t = preg_replace('`\s+`', ' ', preg_replace_callback(array('`(<(!\[CDATA\[))(.+?)(\]\]>)`sm', '`(<(!--))(.+?)(-->)`sm', '`(<(pre|script|textarea)[^>]*?>)(.+?)(</\2>)`sm'), create_function('$m', 'return $m[1]. str_replace(array("<", ">", "\n", "\r", "\t", " "), array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), $m[3]). $m[4];'), $t));
if(($w = strtolower($w)) == -1){ if(($w = strtolower($w)) == -1){
return str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), array('<', '>', "\n", "\r", "\t", ' '), $t); return str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), array('<', '>', "\n", "\r", "\t", ' '), $t);
} }
$s = strpos(" $w", 't') ? "\t" : ' '; $s = strpos(" $w", 't') ? "\t" : ' ';
$s = preg_match('`\d`', $w, $m) ? str_repeat($s, $m[0]) : str_repeat($s, ($s == "\t" ? 1 : 2)); $s = preg_match('`\d`', $w, $m) ? str_repeat($s, $m[0]) : str_repeat($s, ($s == "\t" ? 1 : 2));
$N = preg_match('`[ts]([1-9])`', $w, $m) ? $m[1] : 0; $N = preg_match('`[ts]([1-9])`', $w, $m) ? $m[1] : 0;
$a = array('br'=>1); $a = array('br'=>1);
$b = array('button'=>1, 'input'=>1, 'option'=>1, 'param'=>1); $b = array('button'=>1, 'input'=>1, 'option'=>1, 'param'=>1);
$c = array('caption'=>1, 'dd'=>1, 'dt'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'isindex'=>1, 'label'=>1, 'legend'=>1, 'li'=>1, 'object'=>1, 'p'=>1, 'pre'=>1, 'td'=>1, 'textarea'=>1, 'th'=>1); $c = array('caption'=>1, 'dd'=>1, 'dt'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'isindex'=>1, 'label'=>1, 'legend'=>1, 'li'=>1, 'object'=>1, 'p'=>1, 'pre'=>1, 'td'=>1, 'textarea'=>1, 'th'=>1);
$d = array('address'=>1, 'blockquote'=>1, 'center'=>1, 'colgroup'=>1, 'dir'=>1, 'div'=>1, 'dl'=>1, 'fieldset'=>1, 'form'=>1, 'hr'=>1, 'iframe'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'optgroup'=>1, 'rbc'=>1, 'rtc'=>1, 'ruby'=>1, 'script'=>1, 'select'=>1, 'table'=>1, 'tbody'=>1, 'tfoot'=>1, 'thead'=>1, 'tr'=>1, 'ul'=>1); $d = array('address'=>1, 'blockquote'=>1, 'center'=>1, 'colgroup'=>1, 'dir'=>1, 'div'=>1, 'dl'=>1, 'fieldset'=>1, 'form'=>1, 'hr'=>1, 'iframe'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'optgroup'=>1, 'rbc'=>1, 'rtc'=>1, 'ruby'=>1, 'script'=>1, 'select'=>1, 'table'=>1, 'tbody'=>1, 'tfoot'=>1, 'thead'=>1, 'tr'=>1, 'ul'=>1);
$T = explode('<', $t); $T = explode('<', $t);
$X = 1; $X = 1;
while($X){ while($X){
$n = $N; $n = $N;
$t = $T; $t = $T;
ob_start(); ob_start();
if(isset($d[$p])){echo str_repeat($s, ++$n);} if(isset($d[$p])){echo str_repeat($s, ++$n);}
echo ltrim(array_shift($t)); echo ltrim(array_shift($t));
for($i=-1, $j=count($t); ++$i<$j;){ for($i=-1, $j=count($t); ++$i<$j;){
$r = ''; list($e, $r) = explode('>', $t[$i]); $r = ''; list($e, $r) = explode('>', $t[$i]);
$x = $e[0] == '/' ? 0 : (substr($e, -1) == '/' ? 1 : ($e[0] != '!' ? 2 : -1)); $x = $e[0] == '/' ? 0 : (substr($e, -1) == '/' ? 1 : ($e[0] != '!' ? 2 : -1));
$y = !$x ? ltrim($e, '/') : ($x > 0 ? substr($e, 0, strcspn($e, ' ')) : 0); $y = !$x ? ltrim($e, '/') : ($x > 0 ? substr($e, 0, strcspn($e, ' ')) : 0);
$e = "<$e>"; $e = "<$e>";
if(isset($d[$y])){ if(isset($d[$y])){
if(!$x){ if(!$x){
if($n){echo "\n", str_repeat($s, --$n), "$e\n", str_repeat($s, $n);} if($n){echo "\n", str_repeat($s, --$n), "$e\n", str_repeat($s, $n);}
else{++$N; ob_end_clean(); continue 2;} else{++$N; ob_end_clean(); continue 2;}
} }
else{echo "\n", str_repeat($s, $n), "$e\n", str_repeat($s, ($x != 1 ? ++$n : $n));} else{echo "\n", str_repeat($s, $n), "$e\n", str_repeat($s, ($x != 1 ? ++$n : $n));}
echo $r; continue; echo $r; continue;
} }
$f = "\n". str_repeat($s, $n); $f = "\n". str_repeat($s, $n);
if(isset($c[$y])){ if(isset($c[$y])){
if(!$x){echo $e, $f, $r;} if(!$x){echo $e, $f, $r;}
else{echo $f, $e, $r;} else{echo $f, $e, $r;}
}elseif(isset($b[$y])){echo $f, $e, $r; }elseif(isset($b[$y])){echo $f, $e, $r;
}elseif(isset($a[$y])){echo $e, $f, $r; }elseif(isset($a[$y])){echo $e, $f, $r;
}elseif(!$y){echo $f, $e, $f, $r; }elseif(!$y){echo $f, $e, $f, $r;
}else{echo $e, $r;} }else{echo $e, $r;}
} }
$X = 0; $X = 0;
} }
$t = str_replace(array("\n ", " \n"), "\n", preg_replace('`[\n]\s*?[\n]+`', "\n", ob_get_contents())); $t = str_replace(array("\n ", " \n"), "\n", preg_replace('`[\n]\s*?[\n]+`', "\n", ob_get_contents()));
ob_end_clean(); ob_end_clean();
if(($l = strpos(" $w", 'r') ? (strpos(" $w", 'n') ? "\r\n" : "\r") : 0)){ if(($l = strpos(" $w", 'r') ? (strpos(" $w", 'n') ? "\r\n" : "\r") : 0)){
$t = str_replace("\n", $l, $t); $t = str_replace("\n", $l, $t);
} }
return str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), array('<', '>', "\n", "\r", "\t", ' '), $t); return str_replace(array("\x01", "\x02", "\x03", "\x04", "\x05", "\x07"), array('<', '>', "\n", "\r", "\t", ' '), $t);
// eof // eof
} }
function hl_version(){ function hl_version(){
// rel // rel
return '1.1.17'; return '1.1.17';
// eof // eof
} }
function kses($t, $h, $p=array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'gopher', 'mailto')){ function kses($t, $h, $p=array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'gopher', 'mailto')){
// kses compat // kses compat
foreach($h as $k=>$v){ foreach($h as $k=>$v){
$h[$k]['n']['*'] = 1; $h[$k]['n']['*'] = 1;
} }
$C['cdata'] = $C['comment'] = $C['make_tag_strict'] = $C['no_deprecated_attr'] = $C['unique_ids'] = 0; $C['cdata'] = $C['comment'] = $C['make_tag_strict'] = $C['no_deprecated_attr'] = $C['unique_ids'] = 0;
$C['keep_bad'] = 1; $C['keep_bad'] = 1;
$C['elements'] = count($h) ? strtolower(implode(',', array_keys($h))) : '-*'; $C['elements'] = count($h) ? strtolower(implode(',', array_keys($h))) : '-*';
$C['hook'] = 'kses_hook'; $C['hook'] = 'kses_hook';
$C['schemes'] = '*:'. implode(',', $p); $C['schemes'] = '*:'. implode(',', $p);
return htmLawed($t, $C, $h); return htmLawed($t, $C, $h);
// eof // eof
} }
function kses_hook($t, &$C, &$S){ function kses_hook($t, &$C, &$S){
// kses compat // kses compat
return $t; return $t;
// eof // eof
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment