'. ceil(round(($s / 1024), 1)) .' KB'; // in kb
if ($s >= "1000000") {
$size = ''. round(($s / 1048576), 1) .' MB'; // in mb
}
if ($s <= "999") {
$size = '< 1 KB'; // in kb
}
return $size;
}
/**
* Validate Email Address
*
* @since 1.0
*
* @param string $email
* @return bool
*/
function check_email_address($email) {
if (function_exists('filter_var')) {
// PHP 5.2 or higher
return (!filter_var((string)$email,FILTER_VALIDATE_EMAIL)) ? false: true;
} else {
// old way
if (!preg_match("/[^@]{1,64}@[^@]{1,255}$/", $email)) {
return false;
}
$email_array = explode("@", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if (!preg_match("/(([A-Za-z0-9!#$%&'*+\/\=?^_`{|}~-][A-Za-z0-9!#$%&'*+\/\=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$/", $local_array[$i])) {
return false;
}
}
if (!preg_match("/\[?[0-9\.]+\]?$/", $email_array[1])) {
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if (!preg_match("/(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$/", $domain_array[$i])) {
return false;
}
}
}
return true;
}
}
/**
* Do Regex
*
* @since 1.0
*
* @param string $text Text to perform regex on
* @param string $regex Regex format to use
* @return bool
*/
function do_reg($text, $regex) {
if (preg_match($regex, $text)) {
return true;
} else {
return false;
}
}
/**
* Validate XML
*
* @since 1.0
* @uses i18n_r
* @uses getXML
*
* @param string $file File to validate
* @return string
*/
function valid_xml($file) {
$xmlv = getXML($file);
global $i18n;
if (is_object($xmlv)) {
return ''.i18n_r('XML_VALID').' - '.i18n_r('OK').'';
} else {
return ''.i18n_r('XML_INVALID').' - '.i18n_r('ERROR').'!';
}
}
/**
* Generate Salt
*
* Returns a new unique salt
* @updated 3.0
*
* @return string
*/
function generate_salt() {
if(version_compare(PHP_VERSION, '5.3.0') >= 0 && function_exists("openssl_random_pseudo_bytes")){
return bin2hex(openssl_random_pseudo_bytes(16));
}else{
/* Known to be terribly insecure. Default seeded with an cryptographically
* insecure, 32 bit integer, and PHP versions prior to 5.3 lack built in access
* to secure random.
*/
return sha1(mt_rand());
}
}
/**
* Get Admin Path
*
* Gets the path of the admin directory
*
* @since 1.0
* @uses $GSADMIN
* @uses GSROOTPATH
* @uses tsl
*
* @return string
*/
function get_admin_path() {
global $GSADMIN;
return tsl(GSROOTPATH . $GSADMIN);
}
/**
* Get Root Install Path
*
* Gets the path of the root installation directory
*
* @since 1.0
*
* @return string
*/
function get_root_path() {
$pos = strrpos(dirname(__FILE__),DIRECTORY_SEPARATOR.'inc');
$adm = substr(dirname(__FILE__), 0, $pos);
$pos2 = strrpos($adm,DIRECTORY_SEPARATOR);
return tsl(substr(__FILE__, 0, $pos2));
}
/**
* Check Current Menu
*
* Checks to see if a menu item matches the current page
*
* @since 1.0
*
* @param string $text
* @return string
*/
function check_menu($text) {
if(get_filename_id()===$text){
echo 'class="current"';
}
}
/**
* Password Hashing
*
* Default function to create a hashed password for GetSimple
*
* @since 2.0
* @uses GSLOGINSALT
*
* @param string $p
* @return string
*/
function passhash($p) {
if(defined('GSLOGINSALT') && GSLOGINSALT != '') {
$logsalt = sha1(GSLOGINSALT);
} else {
$logsalt = null;
}
return sha1($p . $logsalt);
}
/**
* Get Available Pages
*
* Lists all available pages for plugin/api use
*
* @since 2.0
* @uses GSDATAPAGESPATH
* @uses find_url
* @uses getXML
* @uses subval_sort
*
* @return array|string Type 'string' in this case will be XML
*/
function get_available_pages() {
$menu_extract = '';
global $pagesArray;
$pagesSorted = subval_sort($pagesArray,'title');
if (count($pagesSorted) != 0) {
$count = 0;
foreach ($pagesSorted as $page) {
if ($page['private']!='Y'){
$text = (string)$page['menu'];
$pri = (string)$page['menuOrder'];
$parent = (string)$page['parent'];
$title = (string)$page['title'];
$slug = (string)$page['url'];
$menuStatus = (string)$page['menuStatus'];
$private = (string)$page['private'];
$pubDate = (string)$page['pubDate'];
$url = find_url($slug,$parent);
$specific = array("slug"=>$slug,"url"=>$url,"parent_slug"=>$parent,"title"=>$title,"menu_priority"=>$pri,"menu_text"=>$text,"menu_status"=>$menuStatus,"private"=>$private,"pub_date"=>$pubDate);
$extract[] = $specific;
}
}
return $extract;
}
}
/**
* Update Slugs
*
* @since 2.04
* @uses $url
* @uses GSDATAPAGESPATH
* @uses XMLsave
*
*/
function updateSlugs($existingUrl, $newurl=null){
global $pagesArray;
getPagesXmlValues();
if (!$newurl){
global $url;
} else {
$url = $newurl;
}
foreach ($pagesArray as $page){
if ( $page['parent'] == $existingUrl ){
$thisfile = @file_get_contents(GSDATAPAGESPATH.$page['filename']);
$data = simplexml_load_string($thisfile);
$data->parent=$url;
XMLsave($data, GSDATAPAGESPATH.$page['filename']);
}
}
}
/**
* Get Link Menu Array
*
* get an array of menu links sorted by heirarchy and indented
*
* @uses $pagesSorted
*
* @since 3.3.0
* @param string $parent
* @param array $array
* @param int $level
* @return array menuitems title,url,parent
*/
function get_link_menu_array($parent='', $array=array(), $level=0) {
global $pagesSorted;
$items=array();
// $pageList=array();
foreach ($pagesSorted as $page) {
if ($page['parent']==$parent){
$items[(string)$page['url']]=$page;
}
}
if (count($items)>0){
foreach ($items as $page) {
$dash="";
if ($page['parent'] != '') {
$page['parent'] = $page['parent']."/";
}
for ($i=0;$i<=$level-1;$i++){
if ($i!=$level-1){
$dash .= utf8_encode("\xA0\xA0"); // outer level
} else {
$dash .= '- '; // inner level
}
}
array_push($array, array( $dash . $page['title'], find_url($page['url'], $page['parent'])));
// recurse submenus
$array=get_link_menu_array((string)$page['url'], $array,$level+1);
}
}
return $array;
}
/**
* List Pages Json
*
* This is used by the CKEditor link-local plugin function: ckeditor_add_page_link()
*
* @author Joshas: mailto:joshas@gmail.com
*
* @since 3.0
* @uses $pagesArray
* @uses subval_sort
* @uses GSDATAPAGESPATH
* @uses getXML
*
* @returns array
*/
function list_pages_json() {
GLOBAL $pagesArray,$pagesSorted;
$pagesArray_tmp = array();
$count = 0;
foreach ($pagesArray as $page) {
if ($page['parent'] != '') {
$parentTitle = returnPageField($page['parent'], "title");
$sort = $parentTitle .' '. $page['title'];
} else {
$sort = $page['title'];
}
$page = array_merge($page, array('sort' => $sort));
$pagesArray_tmp[$count] = $page;
$count++;
}
$pagesSorted = subval_sort($pagesArray_tmp,'sort');
$links = exec_filter('editorlinks',get_link_menu_array());
return json_encode($links);
}
/**
* @deprecated since 3.3.0
* moved to ckeditor config.js
*/
function ckeditor_add_page_link(){
echo "
";
}
/**
* Recursive list of pages
*
* Returns a recursive list of items for the main page
*
* @author Mike
*
* @since 3.0
* @uses $pagesSorted
*
* @param string $parent
* @param string $menu
* @param int $level
*
* @returns string
*/
function get_pages_menu($parent, $menu,$level) {
global $pagesSorted;
$items=array();
foreach ($pagesSorted as $page) {
if ($page['parent']==$parent){
$items[(string)$page['url']]=$page;
}
}
if (count($items)>0){
foreach ($items as $page) {
$dash="";
if ($page['parent'] != '') {
$page['parent'] = $page['parent']."/";
}
for ($i=0;$i<=$level-1;$i++){
if ($i!=$level-1){
$dash .= ' ';
} else {
$dash .= ' – ';
}
}
$menu .= '
';
if ($page['title'] == '' ) { $page['title'] = '[No Title] » '. $page['url'] .''; }
if ($page['menuStatus'] != '' ) { $page['menuStatus'] = ' ['.i18n_r('MENUITEM_SUBTITLE').']'; } else { $page['menuStatus'] = ''; }
if ($page['private'] != '' ) { $page['private'] = ' ['.i18n_r('PRIVATE_SUBTITLE').']'; } else { $page['private'] = ''; }
if ($page['url'] == 'index' ) { $homepage = ' ['.i18n_r('HOMEPAGE_SUBTITLE').']'; } else { $homepage = ''; }
$menu .= ''. $dash .''. cl($page['title']) .''. $homepage . $page['menuStatus'] . $page['private'] .' | ';
$menu .= ''. shtDate($page['pubDate']) .' | ';
$menu .= '';
$menu .= '#';
$menu .= ' | ';
if ($page['url'] != 'index' ) {
$menu .= '× | ';
} else {
$menu .= ' | ';
}
$menu .= '
';
$menu = get_pages_menu((string)$page['url'], $menu,$level+1);
}
}
return $menu;
}
/**
* Recursive list of pages for Dropdown menu
*
* Returns a recursive list of items for the main page
*
* @author Mike
*
* @since 3.0
* @uses $pagesSorted
*
* @param string $parent
* @param string $menu
* @param int $level
*
* @returns string
*/
function get_pages_menu_dropdown($parentitem, $menu,$level) {
global $pagesSorted;
global $parent;
$items=array();
foreach ($pagesSorted as $page) {
if ($page['parent']==$parentitem){
$items[(string)$page['url']]=$page;
}
}
if (count($items)>0){
foreach ($items as $page) {
$dash="";
if ($page['parent'] != '') {
$page['parent'] = $page['parent']."/";
}
for ($i=0;$i<=$level-1;$i++){
if ($i!=$level-1){
$dash .= ' ';
} else {
$dash .= ' – ';
}
}
if ($parent == (string)$page['url']) { $sel="selected"; } else { $sel=""; }
$menu .= '';
$menu = get_pages_menu_dropdown((string)$page['url'], $menu,$level+1);
}
}
return $menu;
}
/**
* Get API Details
*
* Returns the contents of an API url request
*
* This is needed because of the "XmlHttpRequest error: Origin null is not allowed by Access-Control-Allow-Origin"
* error that javascript gets when trying to access outside domains sometimes.
*
* @since 3.1
* @uses GSADMININCPATH
* @uses GSCACHEPATH
*
* @param string $type, default is 'core'
* @param array $args, default is empty
* @param bool $cached force cached check only, do not use curl
*
* @returns string
*/
function get_api_details($type='core', $args=null, $cached = false) {
GLOBAL $debugApi,$nocache,$nocurl;
include(GSADMININCPATH.'configuration.php');
if($cached){
debug_api_details("API REQEUSTS DISABLED, using cache files only");
}
# core api details
if ($type=='core') {
# core version request, return status 0-outdated,1-current,2-bleedingedge
$fetch_this_api = $api_url .'?v='.GSVERSION;
}
else if ($type=='plugin' && $args) {
# plugin api details. requires a passed plugin i
$apiurl = $site_link_back_url.'api/extend/?file=';
$fetch_this_api = $apiurl.$args;
}
else if ($type=='custom' && $args) {
# custom api details. requires a passed url
$fetch_this_api = $args;
} else return;
// get_execution_time();
debug_api_details("type: " . $type. " " .$args);
debug_api_details("address: " . $fetch_this_api);
# debug_api_details(debug_backtrace());
if(!isset($api_timeout) or (int)$api_timeout<100) $api_timeout = 500; // default and clamp min to 100ms
debug_api_details("timeout: " .$api_timeout);
# check to see if cache is available for this
$cachefile = md5($fetch_this_api).'.txt';
$cacheExpire = 39600; // 11 minutes
if(!$nocache || $cached) debug_api_details('cache file check - ' . $fetch_this_api.' ' .$cachefile);
else debug_api_details('cache check: disabled');
$cacheAge = file_exists(GSCACHEPATH.$cachefile) ? filemtime(GSCACHEPATH.$cachefile) : '';
// api disabled and no cache file exists
if($cached && empty($cacheAge)){
debug_api_details('cache file does not exist - ' . GSCACHEPATH.$cachefile);
debug_api_details();
return '{"status":-1}';
}
if (!$nocache && !empty($cacheAge) && (time() - $cacheExpire) < $cacheAge ) {
debug_api_details('cache file time - ' . $cacheAge . ' (' . (time() - $cacheAge) . ')' );
# grab the api request from the cache
$data = file_get_contents(GSCACHEPATH.$cachefile);
debug_api_details('returning cache file - ' . GSCACHEPATH.$cachefile);
} else {
# make the api call
if (function_exists('curl_init') && function_exists('curl_exec') && !$nocurl) {
// USE CURL
$ch = curl_init();
// define missing curlopts php<5.2.3
if(!defined('CURLOPT_CONNECTTIMEOUT_MS')) define('CURLOPT_CONNECTTIMEOUT_MS',156);
if(!defined('CURLOPT_TIMEOUT_MS')) define('CURLOPT_TIMEOUT_MS',155);
// min cURL 7.16.2
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $api_timeout); // define the maximum amount of time that cURL can take to connect to the server
curl_setopt($ch, CURLOPT_TIMEOUT_MS, $api_timeout); // define the maximum amount of time cURL can execute for.
curl_setopt($ch, CURLOPT_NOSIGNAL, 1); // prevents SIGALRM during dns allowing timeouts to work http://us2.php.net/manual/en/function.curl-setopt.php#104597
curl_setopt($ch, CURLOPT_HEADER, false); // ensures header is not in output
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $fetch_this_api);
if($debugApi){
// $verbose = fopen(GSDATAOTHERPATH .'logs/curllog.txt', 'w+');
$verbose = tmpfile();
// curl_setopt($ch, CURLOPT_WRITEHEADER, $verbose );
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $verbose );
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
}
$data = curl_exec($ch);
if($debugApi){
debug_api_details("using curl");
debug_api_details("curl version: ");
debug_api_details(print_r(curl_version(),true));
debug_api_details("curl info:");
debug_api_details(print_r(curl_getinfo($ch),true));
if (!$data) {
debug_api_details("curl error number:" .curl_errno($ch));
debug_api_details("curl error:" . curl_error($ch));
}
debug_api_details("curl Verbose: ");
debug_api_details(!rewind($verbose) . nl2br(htmlspecialchars(stream_get_contents($verbose))) );
fclose($verbose);
// output header and response then remove header from data
$dataparts = explode("\r\n",$data);
debug_api_details("curl Data: ");
debug_api_details($data);
$data = end($dataparts);
}
curl_close($ch);
} else if(ini_get('allow_url_fopen')) {
// USE FOPEN
debug_api_details("using fopen");
$timeout = $api_timeout / 1000; // ms to float seconds
// $context = stream_context_create();
// stream_context_set_option ( $context, array('http' => array('timeout' => $timeout)) );
$context = stream_context_create(array('http' => array('timeout' => $timeout)));
$data = @file_get_contents($fetch_this_api,false,$context);
debug_api_details("fopen data: " .$data);
} else {
debug_api_details("No api methods available");
debug_api_details();
return;
}
// debug_api_details("Duration: ".get_execution_time());
$response = json_decode($data);
debug_api_details('JSON:');
debug_api_details(print_r($response,true),'');
// if response is invalid set status to -1 error
// and we pass on our own data, it is also cached to prevent constant rechecking
if(!$response){
$data = '{"status":-1}';
}
debug_api_details($data);
file_put_contents(GSCACHEPATH.$cachefile, $data);
chmod(GSCACHEPATH.$cachefile, 0644);
debug_api_details();
return $data;
}
debug_api_details();
return $data;
}
function debug_api_details($msg = null ,$prefix = "API: "){
GLOBAL $debugApi;
if(!$debugApi) return;
if(!isset($msg)) $msg = str_repeat('-',80);
debugLog($prefix.$msg);
}
/**
* Get GetSimple Version
*
* Returns the version of this GetSimple installation
*
* @since 3.1
* @uses GSADMININCPATH
* @uses GSVERSION
*
* @returns string
*/
function get_gs_version() {
include(GSADMININCPATH.'configuration.php');
return GSVERSION;
}
/**
* Creates Sitemap
*
* Creates sitemap.xml in the site's root.
*/
function generate_sitemap() {
if(getDef('GSNOSITEMAP',true)) return;
// Variable settings
global $SITEURL;
$path = GSDATAPAGESPATH;
global $pagesArray;
getPagesXmlValues(false);
$pagesSorted = subval_sort($pagesArray,'menuStatus');
if (count($pagesSorted) != 0)
{
$xml = new SimpleXMLElement('');
$xml->addAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd', 'http://www.w3.org/2001/XMLSchema-instance');
$xml->addAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach ($pagesSorted as $page)
{
if ($page['url'] != '404')
{
if ($page['private'] != 'Y')
{
// set
$pageLoc = find_url($page['url'], $page['parent']);
// set
$tmpDate = date("Y-m-d H:i:s", strtotime($page['pubDate']));
$pageLastMod = makeIso8601TimeStamp($tmpDate);
// set
$pageChangeFreq = 'weekly';
// set
if ($page['menuStatus'] == 'Y') {
$pagePriority = '1.0';
} else {
$pagePriority = '0.5';
}
//add to sitemap
$url_item = $xml->addChild('url');
$url_item->addChild('loc', $pageLoc);
$url_item->addChild('lastmod', $pageLastMod);
$url_item->addChild('changefreq', $pageChangeFreq);
$url_item->addChild('priority', $pagePriority);
}
}
}
//create xml file
$file = GSROOTPATH .'sitemap.xml';
$xml = exec_filter('sitemap',$xml);
XMLsave($xml, $file);
exec_action('sitemap-aftersave');
}
if (!defined('GSDONOTPING')) {
if (file_exists(GSROOTPATH .'sitemap.xml')){
if( 200 === ($status=pingGoogleSitemaps($SITEURL.'sitemap.xml'))) {
#sitemap successfully created & pinged
return true;
} else {
error_log(i18n_r('SITEMAP_ERRORPING'));
return i18n_r('SITEMAP_ERRORPING');
}
} else {
error_log(i18n_r('SITEMAP_ERROR'));
return i18n_r('SITEMAP_ERROR');
}
} else {
#sitemap successfully created - did not ping
return true;
}
}
/**
* Creates tar.gz Archive
*/
function archive_targz() {
if(!function_exists('exec')) {
return false;
exit;
}
$timestamp = gmdate('Y-m-d-Hi_s');
$saved_zip_file_path = GSBACKUPSPATH.'zip/';
$saved_zip_file = $timestamp .'_archive.tar.gz';
$script_contents = "tar -cvzf ".$saved_zip_file_path.$saved_zip_file." ".GSROOTPATH.".htaccess ".GSROOTPATH."gsconfig.php ".GSROOTPATH."data ".GSROOTPATH."plugins ".GSROOTPATH."theme ".GSROOTPATH."admin/lang > /dev/null 2>&1";
exec($script_contents, $output, $rc);
if (file_exists($saved_zip_file_path.$saved_zip_file)) {
return true;
} else {
return false;
}
}
/**
* Check if a page is a public admin page
* @return boolean true if page is non protected admin page
*/
function isAuthPage(){
$page = get_filename_id();
return $page == 'index' || $page == 'resetpassword';
}
/**
* returns a query string with only the allowed keys
* @since 3.3.0
*
* @param array $allowed array of querystring keys to keep
* @return string built query string
*/
function filter_queryString($allowed = array()){
parse_str($_SERVER['QUERY_STRING'], $query_string);
$qstring_filtered = array_intersect_key($query_string, array_flip($allowed));
$new_qstring = http_build_query($qstring_filtered,'','&');
return $new_qstring;
}
/**
* Get String Excerpt
*
* @since 3.3.2
*
* @uses mb_strlen
* @uses mb_strrpos
* @uses mb_substr
* @uses strip_tags
* @uses strIsMultibyte
* @uses cleanHtml
* @uses preg_repalce PCRE compiled with "--enable-unicode-properties"
*
* @param string $n Optional, default is 200.
* @param bool $striphtml Optional, default true, true will strip html from $content
* @param string $ellipsis
* @param bool $break break words, default: do not break words find whitespace and puntuation
* @param bool $cleanhtml attempt to clean up html IF strip tags is false, default: true
* @return string
*/
function getExcerpt($str, $len = 200, $striphtml = true, $ellipsis = '...', $break = false, $cleanhtml = true){
$str = $striphtml ? trim(strip_tags($str)) : $str;
$len = $len++; // zero index bump
// setup multibyte function names
$prefix = strIsMultibyte($str) ? 'mb_' : '';
list($substr,$strlen,$strrpos) = array($prefix.'substr',$prefix.'strlen',$prefix.'strrpos');
// string is shorter than truncate length, return
if ($strlen($str) < $len) return $str;
// if not break, find last word boundary before truncate to avoid splitting last word
// solves for unicode whitespace \p{Z} and punctuation \p{P} and a 1 character lookahead hack,
// replaces punc with space so it handles the same for obtaining word boundary index
// REQUIRES that PCRE is compiled with "--enable-unicode-properties,
// @todo detect or supress requirement, perhaps defined('PREG_BAD_UTF8_OFFSET_ERROR'), translit puntuation only might be an alternative
debugLog(defined('PREG_BAD_UTF8_OFFSET_ERROR'));
if(!$break) $excerpt = preg_replace('/\n|\p{Z}|\p{P}+$/u',' ',$substr($str, 0, $len+1));
$lastWordBoundaryIndex = !$break ? $strrpos($excerpt, ' ') : $len;
$str = $substr($str, 0, $lastWordBoundaryIndex);
if(!$striphtml && $cleanhtml) return trim(cleanHtml($str)) . $ellipsis;
return trim($str) . $ellipsis;
}
/**
* check if a string is multbyte
* @since 3.3.2
*
* @uses mb_check_encoding
*
* @param string $str string to check
* @return bool true if multibyte
*/
function strIsMultibyte($str){
return function_exists('mb_check_encoding') && ! mb_check_encoding($str, 'ASCII') && mb_check_encoding($str, 'UTF-8');
}
/**
* clean Html fragments by loading and saving from DOMDocument
* Will only clean html body fragments,unexpected results with full html doc or containing head or body
* which are always stripped
*
* @note supressing errors on libxml functions to prevent parse errors on not well-formed content
* @since 3.3.2
* @param string $str string to clean up
* @param array $strip_tags optional elements to remove eg. array('style')
* @return string return well formed html , with open tags being closed and incomplete open tags removed
*/
function cleanHtml($str,$strip_tags = array()){
// setup encoding, required for proper dom loading
// @note
// $dom_document = new DOMDocument('1.0', 'utf-8'); // this does not deal with transcoding issues, loadhtml will treat string as ISO-8859-1 unless the doc specifies it
// $dom_document->loadHTML(mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8')); // aternate option that might work...
$dom_document = new DOMDocument();
$charsetstr = '';
@$dom_document->loadHTML($charsetstr.$str);
foreach($strip_tags as $tag){
$elem = $dom_document->getElementsByTagName($tag);
while ( ($node = $elem->item(0)) ) {
$node->parentNode->removeChild($node);
}
}
// strip dom tags that we added, and ones that savehtml adds
// strip doctype, head, html, body tags
$html_fragment = preg_replace('/^|(.*)?<\/head>/', '', str_replace( array('', '', '', ''), array('', '', '', ''), @$dom_document->saveHTML()));
return $html_fragment;
}
?>