'tikiwiki_save_data', 'load_function' => 'tikiwiki_parse_data', 'verify_function' => 'tikiwiki_verify_data', 'rename_function' => 'tikiwiki_rename', 'expunge_function' => 'tikiwiki_expunge', 'description' => 'TikiWiki Syntax Format Parser', 'edit_label' => 'Tiki Wiki Syntax', 'edit_field' => PLUGIN_GUID_TIKIWIKI, 'help_page' => 'TikiWikiSyntax', 'plugin_type' => FORMAT_PLUGIN ); $gLibertySystem->registerPlugin( PLUGIN_GUID_TIKIWIKI, $pluginParams ); /** * tikiwiki_save_data */ function tikiwiki_save_data( &$pParamHash ) { static $parser; if( empty( $parser ) ) { $parser = new TikiWikiParser(); } if( $pParamHash['edit'] ) { $parser->storeLinks( $pParamHash ); } LibertyContent::expungeCacheFile( $pParamHash['content_id'] ); } function tikiwiki_verify_data( &$pParamHash ) { $errorMsg = NULL; $pParamHash['content_store']['data'] = $pParamHash['edit']; return( $errorMsg ); } function tikiwiki_expunge( $pContentId ) { $parser = new TikiWikiParser(); $parser->expungeLinks( $pContentId ); LibertyContent::expungeCacheFile( $pContentId ); } function tikiwiki_rename( $pContentId, $pOldName, $pNewName, &$pCommonObject ) { $query = " SELECT `from_content_id`, `data` FROM `".BIT_DB_PREFIX."liberty_content_links` lcl INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lcl.`from_content_id`=lc.`content_id` ) WHERE `to_content_id` = ?"; if( $result = $pCommonObject->mDb->query( $query, array( $pContentId ) ) ) { while( $row = $result->fetchRow() ) { // check if there are occasions of the old name with alternate display link name // --- ((WikiLink|Description)) // \({2} # check for (( // \b$pOldName\b # make sure the old name is on it's own // \| # the seperating deliminator // ([^\)]*) # get as many characters as possible up to the next ) - put this in $1 // \){2} # closing brackets )) $pattern[] = "!\({2}\b$pOldName\b\|([^\)]*)\){2}!"; // - replace with new name leaving description in tact $replace[] = "(($pNewName|$1))"; // --- ((WikiLink)) or WikiLink // (\({2})? # check for (( - optional - put this in $1 // \b$pOldName\b # make sure the old name is on it's own // (\){2})? # closing brackets )) - optional - put this in $2 $pattern[] = "!(\({2})?\b$pOldName\b(\){2})?!"; // - the replacement depends on the new name if( preg_match( "! !", $pNewName ) ) { // since we have a space in the final name, we need to have (( // and )) to make the link work $replace[] = "(($pNewName))"; } else { // no spaces in the new name either, so we only insert the (( // and )) if the author used them to start off with $replace[] = "$1$pNewName$2"; } $data = preg_replace( $pattern, $replace, $row['data'] ); if( md5( $data ) != md5( $row['data'] ) ) { $query = "UPDATE `".BIT_DB_PREFIX."liberty_content` SET `data`=? WHERE `content_id`=?"; $pCommonObject->mDb->query( $query, array( $data, $row['from_content_id'] ) ); // remove any chached files pointing here LibertyContent::expungeCacheFile( $row['from_content_id'] ); } } } # Fix up titles in the link table $query = "UPDATE `".BIT_DB_PREFIX."liberty_content_links` SET `to_title`=? WHERE `to_content_id`=?"; $pCommonObject->mDb->query( $query, array( $pNewName, $pContentId ) ); } function tikiwiki_parse_data( &$pParseHash, &$pCommonObject ) { global $gBitSystem; // cache data if we are using liberty cache if( $gBitSystem->isFeatureActive( 'liberty_cache' ) && !empty( $pParseHash['content_id'] ) && empty( $pParseHash['no_cache'] ) ) { if( $cacheFile = LibertyContent::getCacheFile( $pParseHash['content_id'], $pParseHash['cache_extension'] ) ) { // write / refresh cache if we are exceeding time limit of cache if( !is_file( $cacheFile ) || ( $gBitSystem->getConfig( 'liberty_cache' ) < ( time() - filemtime( $cacheFile ) ) ) ) { static $parser; if( empty( $parser ) ) { $parser = new TikiWikiParser(); } $ret = $parser->parse_data( $pParseHash, $pCommonObject ); // write parsed contents to cache file $h = fopen( $cacheFile, 'w' ); fwrite( $h, $ret ); fclose( $h ); } else { // get contents from cache file $h = fopen( $cacheFile, 'r' ); $ret = fread( $h, filesize( $cacheFile ) ); fclose( $h ); $pCommonObject->mInfo['is_cached'] = TRUE; } } } else { static $parser; if( empty( $parser ) ) { $parser = new TikiWikiParser(); } $ret = $parser->parse_data( $pParseHash, $pCommonObject ); } return $ret; } /** * TikiWikiParser * * @package kernel */ class TikiWikiParser extends BitBase { var $mWikiWordRegex; var $mUseWikiWords; var $mPageLookup; var $pre_handlers = array(); var $pos_handlers = array(); function TikiWikiParser () { BitBase::BitBase(); global $gBitSystem; $this->mUseWikiWords = $gBitSystem->isFeatureActive( 'wiki_words' ); // Setup the WikiWord regex $wiki_page_regex = $gBitSystem->getConfig( 'wiki_page_regex', 'strict' ); // Please DO NOT modify any of the brackets in the regex(s). // It may seem redundent but, really, they are ALL REQUIRED. if ($wiki_page_regex == 'strict') { $this->mWikiWordRegex = '([A-Za-z0-9_])([\.: A-Za-z0-9_\-])*([A-Za-z0-9_])'; } elseif ($wiki_page_regex == 'full') { $this->mWikiWordRegex = '([A-Za-z0-9_]|[\x80-\xFF])([\.: A-Za-z0-9_\-]|[\x80-\xFF])*([A-Za-z0-9_]|[\x80-\xFF])'; } else { // This is just evil. The middle section means "anything, as long // as it's not a | and isn't followed by ))". -rlpowell $this->mWikiWordRegex = '([^|\(\)])([^|](?!\)\)))*?([^|\(\)])'; } } function add_pre_handler($name) { if (!in_array($name, $this->pre_handlers)) { $this->pre_handlers[] = $name; } } function add_pos_handler($name) { if (!in_array($name, $this->pos_handlers)) { $this->pos_handlers[] = $name; } } function extractWikiWords( &$data ) { if( $this->mUseWikiWords ) { preg_match_all("/\(\(($this->mWikiWordRegex)\)\)/", $data, $words2); preg_match_all("/\(\(($this->mWikiWordRegex)\|(.+?)\)\)/", $data, $words3); preg_match_all( '/\b('.WIKI_WORDS_REGEX.')\b/', $data, $words ); $words = array_unique(array_merge($words[1], $words2[1], $words3[1])); } else { preg_match_all("/\(\(($this->mWikiWordRegex)\)\)/", $data, $words); preg_match_all("/\(\(($this->mWikiWordRegex)\|(.+?)\)\)/", $data, $words2); $words = array_unique(array_merge($words[1], $words2[1])); } return $words; } function storeLinks( &$pParamHash ) { global $gBitSystem; if( empty( $pParamHash['content_id'] ) ) { return; } $from_content_id = $pParamHash['content_id']; $from_title = $pParamHash['title']; // we need to remove the cache of any pages pointing to this one $clearCache = $this->mDb->getCol( "SELECT `from_content_id` FROM `".BIT_DB_PREFIX."liberty_content_links` WHERE (`to_content_id`=? or `to_content_id` is NULL ) and `to_title` = ?", array( 0, $from_title ) ); foreach( $clearCache as $content_id ) { LibertyContent::expungeCacheFile( $content_id ); } #if this is a new page, fix up any links that may already point to it $query = "UPDATE `".BIT_DB_PREFIX."liberty_content_links` SET `to_content_id`=? WHERE (`to_content_id`=? or `to_content_id` is NULL ) and `to_title` = ?"; $this->mDb->query( $query, array( $from_content_id, 0, $from_title ) ); #get all the current links from this page $old_links_in_db = array(); $query = "SELECT * FROM `".BIT_DB_PREFIX."liberty_content_links` WHERE `from_content_id`=?"; if( $result = $this->mDb->query( $query, array( $from_content_id ) ) ) { while( $row = $result->fetchRow() ) { $old_links_in_db[$row['to_title']] = $row['to_content_id']; } } #get list of all wiki links on this page $wiki_links_in_content = $this->extractWikiWords( $pParamHash['edit'] ); if( !is_array( $wiki_links_in_content ) ) { $wiki_links_in_content = array(); } #create list of unique new wiki links on this page $unique_new_wiki_links = array(); foreach( $wiki_links_in_content as $to_title ) { if( empty( $to_title ) ) { continue; } if( isset( $old_links_in_db[$to_title] ) ) { # link already in DB - skip rest of processing continue; } $unique_new_wiki_links[$to_title] = $to_title; } #get list of all new links that point to existing content $new_link_pointing_to_existing_content = array(); $title_list_count = count($unique_new_wiki_links); if( $title_list_count > 0 ) { $title_list = '?' . str_repeat(',?',$title_list_count - 1); $query = "SELECT * FROM `".BIT_DB_PREFIX."liberty_content` WHERE `title` IN($title_list)"; if( $result = $this->mDb->query($query, array_keys($unique_new_wiki_links) ) ) { while( $row = $result->fetchRow() ) { $new_link_pointing_to_existing_content[$row['title']] = $row['content_id']; } } if( count($new_link_pointing_to_existing_content) > 0 ) { #insert all new links pointing to existing content $query_var = array_keys($new_link_pointing_to_existing_content); $query_var_list = '?' . str_repeat(',?', count($new_link_pointing_to_existing_content) - 1); $query = "INSERT INTO `".BIT_DB_PREFIX."liberty_content_links` (`from_content_id`,`to_content_id`,`to_title`) SELECT ?,`content_id`,`title` FROM `".BIT_DB_PREFIX."liberty_content` WHERE `title` IN ( $query_var_list )"; array_unshift($query_var,$from_content_id); $result = $this->mDb->query($query, $query_var); } } #insert all new links pointing to non-existing content foreach ($unique_new_wiki_links as $to_title) { if( isset($new_link_pointing_to_existing_content[$to_title]) ) { continue; } $query = "insert into `".BIT_DB_PREFIX."liberty_content_links` (`from_content_id`,`to_title`) values(?, ?)"; $result = $this->mDb->query($query, array( $from_content_id, $to_title ) ); } # now delete any links no longer on page foreach( $wiki_links_in_content as $to_title) { $wiki_links_in_content_table[$to_title] = 1; } foreach( array_keys($old_links_in_db) as $to_title ) { if( !isset($wiki_links_in_content_table[$to_title]) ) { $query = "DELETE FROM `".BIT_DB_PREFIX."liberty_content_links` WHERE `from_content_id`=? and `to_title` = ?"; $result = $this->mDb->query( $query, array( $from_content_id, $to_title ) ); } } } function expungeLinks( $pContentId ) { if( !empty( $pContentId ) ) { // remove any cached file pointing to this page $links = $this->mDb->getCol( "SELECT `from_content_id` FROM `".BIT_DB_PREFIX."liberty_content_links` WHERE to_content_id=?", array( $pContentId ) ); foreach( $links as $content_id ) { LibertyContent::expungeCacheFile( $content_id ); } $this->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."liberty_content_links` WHERE from_content_id=? OR to_content_id=?", array( $pContentId, $pContentId ) ); } } /* old database intensive pageExists check // Use liberty_content_links to get all the existing links in a single query function pageExists( $pTitle, $pContentId, $pCommonObject ) { $pTitle = strtolower( $pTitle ); if( !empty( $pContentId ) ) { if( empty( $this->mPageLookup ) ) { $query = "SELECT LOWER( lc.`title` ) AS `hash_key`, `page_id`, lc.`content_id`, `description`, lc.`last_modified`, lc.`title` FROM `".BIT_DB_PREFIX."liberty_content_links` lcl INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lcl.`to_content_id`=lc.`content_id` ) INNER JOIN `".BIT_DB_PREFIX."wiki_pages` wp ON( wp.`content_id`=lc.`content_id` ) WHERE lcl.`from_content_id`=? ORDER BY lc.`title`"; if( $result = $this->mDb->query( $query, array( $pContentId ) ) ) { $lastTitle = ''; while( $row = $result->fetchRow() ) { if( $row['title'] == $lastTitle ) { // TODO - need to check ensure that liberty_content_links duplicate are properly inserted - spiderr } $this->mPageLookup[$row['hash_key']][] = $row; $lastTitle = $row['title']; } } } } if( !isset( $this->mPageLookup[$pTitle] ) ) { $this->mPageLookup[$pTitle] = $pCommonObject->pageExists( $pTitle ); if( !empty( $this->mPageLookup[$pTitle] ) && ( count( $this->mPageLookup[$pTitle] ) == 1 ) ) { // $this->mDb->query( "INSERT INTO `".BIT_DB_PREFIX."liberty_content_links` ( `from_content_id`, `to_content_id` ) VALUES ( ?, ? )" , array( $pContentId, $this->mPageLookup[$pTitle][0]['content_id'] ) ); } } return( !empty( $this->mPageLookup[$pTitle] ) ? $this->mPageLookup[$pTitle] : NULL ); } */ function getAllPages( $pContentId ) { global $gBitSystem; $ret = array(); if( $gBitSystem->isPackageActive( 'wiki' ) && @BitBase::verifyId( $pContentId ) ) { $query = "SELECT `page_id`, lc.`content_id`, `description`, lc.`last_modified`, lc.`title` FROM `".BIT_DB_PREFIX."liberty_content_links` lcl INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lcl.`to_content_id`=lc.`content_id` ) INNER JOIN `".BIT_DB_PREFIX."wiki_pages` wp ON( wp.`content_id`=lc.`content_id` ) WHERE lcl.`from_content_id`=? ORDER BY lc.`title`"; if( $result = $this->mDb->query( $query, array( $pContentId ) ) ) { $lastTitle = ''; while( $row = $result->fetchRow() ) { if( array_key_exists( strtolower( $row['title'] ), $ret ) ) { $row['description'] = tra( 'Multiple pages with this name' ); } $ret[strtolower( $row['title'] )] = $row; } } } return $ret; } function pageExists( $pTitle, $pPageList, $pCommonObject, $pContentId ) { $ret = FALSE; if( !empty( $pTitle ) && !empty( $pPageList ) ) { if( array_key_exists( strtolower( $pTitle ), $pPageList ) ) { $ret = $pPageList[strtolower( $pTitle )]; } } // final attempt to get page details if( empty( $ret ) ) { if( $ret = $pCommonObject->pageExists( $pTitle, FALSE, $pContentId ) ) { if( count( $ret ) > 1 ) { $ret[0]['description'] = tra( 'Multiple pages with this name' ); } $ret = $ret[0]; } } return $ret; } function parse_data_raw($data) { $data = $this->parseData($data); $data = str_replace( WIKI_PKG_URL."index", WIKI_PKG_URL."index_raw", $data ); return $data; } // This recursive function handles pre- and no-parse sections and plugins function parse_first(&$data, &$preparsed, &$noparsed, &$pCommonObject) { global $gLibertySystem; $this->parse_pp_np($data, $preparsed, $noparsed); // Handle pre- and no-parse sections parse_data_plugins( $data, $preparsed, $noparsed, $this, $pCommonObject ); } // AWC ADDITION // This function replaces pre- and no-parsed sections with unique keys // and saves the section contents for later reinsertion. function parse_pp_np(&$data, &$preparsed, &$noparsed) { // Find all sections delimited by ~pp~ ... ~/pp~ // and replace them in the data stream with a unique key preg_match_all("/\~pp\~((.|\n)*?)\~\/pp\~/", $data, $preparse); if( count( $preparse[0] ) ) { foreach (array_unique($preparse[1])as $pp) { $key = md5(BitSystem::genPass()); $aux["key"] = $key; $aux["data"] = $pp; $preparsed[] = $aux; $data = str_replace("~pp~$pp~/pp~", $key, $data); } // Temporary remove
 tags too
			// TODO: Is this a problem if user insert 
 but after parsing
			//	   will get 
 (lowercase)?? :)
			preg_match_all("/(<[Pp][Rr][Ee]>)((.|\n)*?)(<\/[Pp][Rr][Ee]>)/", $data, $preparse);
			$idx = 0;

			foreach (array_unique($preparse[2])as $pp) {
				$key = md5(BitSystem::genPass());

				$aux["key"] = $key;
				$aux["data"] = $pp;
				$preparsed[] = $aux;
				$data = str_replace($preparse[1][$idx] . $pp . $preparse[4][$idx], $key, $data);
				$idx = $idx + 1;
			}
		}

		if( preg_match("!\~np\~(.*?)\~/np\~!s", $data, $preparse) ) {
			// Find all sections delimited by ~np~ ... ~/np~
			$new_data = '';
			$nopa = '';
			$state = true;
			$skip = false;

			$dlength=strlen($data);
			for ($i = 0; $i < $dlength; $i++) {
				$tag5 = substr($data, $i, 5);
				$tag4 = substr($tag5, 0, 4);
				$tag1 = substr($tag4, 0, 1);

				// Beginning of a noparse section found
				if ($state && $tag4 == '~np~') {
					$i += 3;
					$state = false;
					$skip = true;
				}

				// Termination of a noparse section found
				if (!$state && ($tag5 == '~/np~')) {
					$state = true;
					$i += 4;
					$skip = true;
					$key = md5(BitSystem::genPass());
					$new_data .= $key;
					$aux["key"] = $key;
					$aux["data"] = $nopa;
					$noparsed[] = $aux;
					$nopa = '';
				}

				if (!$skip) { // This character is not part of a noparse tag
					if ($state) { // This character is not within a noparse section
					$new_data .= $tag1;
					} else { // This character is within a noparse section
					$nopa .= $tag1;
					}
				} else { // Tag is now skipped over
					$skip = false;
				}
			}
			$data = $new_data;
		}
	}


	// This function handles wiki codes for those special HTML characters
	// that textarea won't leave alone.
	function parse_htmlchar(&$data) {
		// cleaning some user input
		$data = preg_replace("/&(?!([a-z]{1,7};))/", "&", $data);

		// oft-used characters (case insensitive)
		$data = preg_replace("/~bull~/i", "•", $data);
		$data = preg_replace("/~bs~/i", "\", $data);
		$data = preg_replace("/~hs~/i", " ", $data);
		$data = preg_replace("/~amp~/i", "&", $data);
		$data = preg_replace("/~ldq~/i", "“", $data);
		$data = preg_replace("/~rdq~/i", "”", $data);
		$data = preg_replace("/~lsq~/i", "‘", $data);
		$data = preg_replace("/~rsq~/i", "’", $data);
		$data = preg_replace("/~c~/i", "©", $data);
		$data = preg_replace("/~--~/", "—", $data);
		$data = preg_replace("/ -- /", " — ", $data);
		$data = preg_replace("/~lt~/i", "<", $data);
		$data = preg_replace("/~gt~/i", ">", $data);

		// HTML numeric character entities
		$data = preg_replace("/~([0-9]+)~/", "&#$1;", $data);
	}

	function parse_smileys( $pData ) {
		global $gBitSystem, $gBitSmarty;
		if( defined( "SMILEYS_PKG_URL" ) && $gBitSystem->isPackageActive( 'smileys' ) ) {
			preg_match_all( "/\(:([^:]+):\)/", $pData, $smileys );
			require_once $gBitSmarty->_get_plugin_filepath( 'function', 'biticon' );
			$smileys[0] = array_unique( $smileys[0] );
			$smileys[1] = array_unique( $smileys[1] );
			if( !empty( $smileys[1] ) ) {
				foreach( $smileys[1] as $key => $smiley ) {
					$biticon = array(
						'ipackage' => 'smileys',
						'iname' => $smiley,
						'iexplain' => $smiley,
						'iforce' => 'icon',
					);
					$pData = preg_replace( "/".preg_quote( $smileys[0][$key] )."/", smarty_function_biticon( $biticon, $gBitSmarty ), $pData );
				}
			}
		}

		return $pData;
	}

	function parse_comment_data( $pData ) {
		// rel=\"nofollow\" is support for Google's Preventing comment spam
		// http://www.google.com/googleblog/2005/01/preventing-comment-spam.html
		$pData = preg_replace("/\[([^\|\]]+)\|([^\]]+)\]/", "$2", $pData);

		// Segundo intento reemplazar los [link] comunes
		$pData = preg_replace("/\[([^\]\|]+)\]/", "$1", $pData);

		// Llamar aqui a parse smileys
		$pData = $this->parse_smileys($pData);
		$pData = preg_replace("/---/", "
", $pData); // Reemplazar --- por
return $pData; } function get_language($user = false) { static $bitLanguage = false; global $gBitUser, $gBitSystem; if( empty( $bitLanguage ) ) { if( $gBitUser->isValid() ) { $bitLanguage = $gBitUser->getPreference('bitLanguage', 'en'); } else { $bitLanguage = $this->getPreference('bitLanguage', 'en'); } } return $bitLanguage; } function get_locale($user = false) { # TODO move to admin preferences screen static $locales = array( 'cs' => 'cs_CZ', 'de' => 'de_DE', 'dk' => 'da_DK', 'en' => 'en_US', 'fr' => 'fr_FR', 'he' => 'he_IL', # hebrew 'it' => 'it_IT', # italian 'pl' => 'pl_PL', # polish 'po' => 'po', 'ru' => 'ru_RU', 'es' => 'es_ES', 'sw' => 'sw_SW', # swahili 'tw' => 'tw_TW', ); if (!isset($locale) or !$locale) { $locale = ''; if (isset($locales[$this->get_language($user)])) $locale = $locales[$this->get_language($user)]; #print "
get_locale(): locale=$locale\n
"; } return $locale; } function get_links($data) { $links = array(); // Match things like [...], but ignore things like [[foo]. // -Robin if (preg_match_all("/(?isFeatureActive( 'liberty_cache_pages' ) ) { foreach ($links as $link) { if( !$pCommonObject->isCached( $link ) ) { $pCommonObject->cacheUrl($link); } } } } function how_many_at_start($str, $car) { $cant = 0; $i = 0; while (($i < strlen($str)) && (isset($str{$i})) && ($str{$i}== $car)) { $i++; $cant++; } return $cant; } function parse_mediawiki_tables( $data ) { //DEBUG: $data = "\n\n" . $data; /* Find all matches to {|...|} with no {| inside. */ while (preg_match('/\n\{\|(.*?)\n\|\}/sm', $data, $matches)) { //DEBUG: vd($matches); $table_data = str_replace("\r", "", $matches[1]); $table_data = str_replace('||', "\n|", $table_data); while (preg_match('/^![^!]+!!/m', $table_data)) { /* Replace !! with \n! but ONLY in !-defined header rows. */ $table_data = preg_replace('/^!([^!]+)!!/m', "!$1\n!", $table_data); } if (substr($table_data, 0, 1) != "\n") { /* We have table parameters. */ list($table_params, $table_data) = explode("\n", $table_data, 2); $table_params = trim($table_params); /* FIXME: This attempt to support foo:bar table params needs help! if (strlen($table_params)) { $table_params = preg_replace("/\b(\w+):/", '$1=', $table_params); } */ } else { $table_params = ''; } $content = ""; $lines = explode("\n", $table_data); $row = 0; foreach ($lines as $line) { if ((substr($line, 0, 1) == '|') || (substr($line, 0, 1) == '!')) { if (preg_match('/^\|\+\s*(.+)$/', $line, $row_matches)) { $content .= ""; } else if (preg_match('/^\|-\s*(.+)?$/', $line, $row_matches)) { if ($row) { $content .= ''; $row++; } else { $row = 1; } $content .= ''; } else if (preg_match('/^([\|!])\s*([^\|]+\s*\|)?\s*(.*)$/', $line, $row_matches)) { if (! $row) { $content .= ''; $row = 1; } $content .= '' . $row_matches[3] . ''; } else { $content .= ""; } } else { $content .= ""; } } $content .= '
$row_matches[1]
'; $data = str_replace($matches[0], $content, $data); } //DEBUG: $data .= "\n\n"; return $data; } function parse_data( $pParseHash, &$pCommonObject ) { global $gBitSystem, $gBitUser, $page; $data = $pParseHash['data']; $contentId = $pParseHash['content_id']; // this is used for setting the links when section editing is enabled $section_count = 1; if( $gBitSystem->isPackageActive( 'wiki' ) ) { require_once( WIKI_PKG_PATH.'BitPage.php' ); } // get a list of pages this page links to $pageList = $this->getAllPages( $contentId ); // if the object isn't loaded, we'll try and get the content prefs manually if( !empty( $pCommonObject->mPrefs ) ) { $contentPrefs = $pCommonObject->mPrefs; } elseif( empty( $pCommonObject->mContentId ) && !empty( $contentId ) ) { $contentPrefs = LibertyContent::loadPreferences( $contentId ); } // disable HTML in wiki page for now - very disruptive. should be changed into a per page setting - xing if( !empty( $contentPrefs['content_enter_html'] ) ) { // this is copied and pasted from format.bithtml.php - xing // Strip all evil tags that remain // this comes out of gBitSystem->getConfig() set in Liberty Admin $acceptableTags = $gBitSystem->getConfig( 'approved_html_tags', DEFAULT_ACCEPTABLE_TAGS ); // Destroy all script code "manually" - strip_tags will leave code inline as plain text if( !preg_match( '/\/', $acceptableTags ) ) { $data = preg_replace( "/(\)/si", '', $data ); } $data = strip_tags( $data, $acceptableTags ); } elseif( !$gBitSystem->isFeatureActive( 'content_allow_html' ) ) { // convert HTML to chars $data = htmlspecialchars( $data, ENT_NOQUOTES, 'UTF-8' ); } // Process pre_handlers here foreach ($this->pre_handlers as $handler) { $data = $handler($data); } $data = preg_replace( '/(\)\))('.WIKI_WORDS_REGEX.')(\(\()/', "~np~" . "$2" . "~/np~", $data); // Handle pre- and no-parse sections and plugins $preparsed = array(); $noparsed = array(); $this->parse_first($data, $preparsed, $noparsed, $pCommonObject); // Extract [link] sections (to be re-inserted later) $noparsedlinks = array(); // This section matches [...]. // Added handling for [[foo] sections. -rlpowell preg_match_all("/(?parse_htmlchar($data); //$data = strip_tags($data); // BiDi markers $bidiCount = 0; $bidiCount = preg_match_all("/(\{l2r\})/", $data, $pages); $bidiCount += preg_match_all("/(\{r2l\})/", $data, $pages); $data = preg_replace("/\{l2r\}/", "
", $data); $data = preg_replace("/\{r2l\}/", "
", $data); $data = preg_replace("/\{lm\}/", "‎", $data); $data = preg_replace("/\{rm\}/", "‏", $data); // smileys $data = $this->parse_smileys($data); // Parse MediaWiki-style pipe syntax tables. if ((strpos($data, "\n{|") !== FALSE) && (strpos($data, "\n|}") !== FALSE)) { $data = $this->parse_mediawiki_tables($data); } // ============================================= this should go - xing // Replace dynamic variables // Dynamic variables are similar to dynamic content but they are editable // from the page directly, intended for short data, not long text but text // will work too // Now won't match HTML-style '%nn' letter codes. if (preg_match_all("/%([^% 0-9][^% 0-9][^% ]*)%/",$data,$dvars)) { // remove repeated elements $dvars = array_unique($dvars[1]); // Now replace each dynamic variable by a pair composed of the // variable value and a text field to edit the variable. Each foreach($dvars as $dvar) { $query = "select `data` from `".BIT_DB_PREFIX."liberty_dynamic_variables` where `name`=?"; $result = $this->mDb->query($query,Array($dvar)); if($result->numRows()) { $value = $result->fetchRow(); $value = $value["data"]; } else { //Default value is NULL $value = "NaV"; } // Now build 2 divs $id = 'dyn_'.$dvar; if( $gBitUser->hasPermission( 'p_wiki_edit_dynvar' ) ) { $span1 = "$value"; $span2 = ""; } else { $span1 = "$value"; $span2 = ''; } $html = $span1.$span2; //It's important to replace only once $dvar_preg = preg_quote( $dvar ); $data = preg_replace("+%$dvar_preg%+",$html,$data,1); //Further replacements only with the value $data = str_replace("%$dvar%",$value,$data); } //At the end put an update button //
$data='
'.$data.'
'; } /* ============================================= obsolete - this looks as though it should be a liberty plugin - xing // Replace dynamic content occurrences if (preg_match_all("/\{content +id=([0-9]+)\}/", $data, $dcs)) { for ($i = 0; $i < count($dcs[0]); $i++) { $repl = $this->get_actual_content($dcs[1][$i]); $data = str_replace($dcs[0][$i], $repl, $data); } } // Replace Dynamic content with random selection if (preg_match_all("/\{rcontent +id=([0-9]+)\}/", $data, $dcs)) { for ($i = 0; $i < count($dcs[0]); $i++) { $repl = $this->get_random_content($dcs[1][$i]); $data = str_replace($dcs[0][$i], $repl, $data); } } */ // Replace boxes $data = preg_replace("/\^([^\^]+)\^/", "
$1
", $data); // Replace colors ~~color:text~~ $data = preg_replace("/\~\~([^\:]+):([^\~]+)\~\~/", "$2", $data); // Replace background colors ++color:text++ $data = preg_replace("/\+\+([^\s][^\: ]+):([^\+]+)\+\+/", "$2", $data); // Underlined text $data = preg_replace("/===([^\=]+)===/", "$1", $data); // Center text $data = preg_replace("/::(.+?)::/", "
$1
", $data); // Line breaks $data = preg_replace('/%%%/', '
', $data); // New syntax for wiki pages ((name|desc)) Where desc can be anything preg_match_all("/\(\(($this->mWikiWordRegex)\|(.+?)\)\)/", $data, $pages); for ($i = 0; $i < count($pages[1]); $i++) { $pattern = $pages[0][$i]; $pattern = preg_quote($pattern, "/"); $pattern = "/" . $pattern . "/"; // Replace links to external wikis $repl2 = true; if (strstr($pages[1][$i], ':')) { $wexs = explode(':', $pages[1][$i]); if (count($wexs) == 2) { $wkname = $wexs[0]; if ($this->mDb->getOne("select count(*) from `".BIT_DB_PREFIX."wiki_ext` where `name`=?",array($wkname)) == 1) { $wkurl = $this->mDb->getOne("select `extwiki` from `".BIT_DB_PREFIX."wiki_ext` where `name`=?",array($wkname)); $wkurl = '' . $wexs[1] . ''; $data = preg_replace($pattern, "$wkurl", $data); $repl2 = false; } } } if ($repl2) { // 24-Jun-2003, by zaufi // TODO: future optimize: get page description and modification time at once. // text[0] = link description (previous format) // text[1] = timeout in seconds (new field) // text[2..N] = drop $text = explode("|", $pages[5][$i]); if( $exists = $this->pageExists( $pages[1][$i], $pageList, $pCommonObject, $contentId ) ) { $modTime = count( $exists ) == 1 ? (isset( $exists['last_modified'] ) ? (int)$exists['last_modified'] : 0 ) : 0; $uri_ref = WIKI_PKG_URL."index.php?page=" . urlencode($pages[1][$i]); $repl = ''.( (strlen(trim($text[0])) > 0 ? $text[0] : $pages[1][$i]) ).''; // Check is timeout expired? if (isset($text[1]) && (time() - $modTime ) < intval($text[1])) { // Append small 'new' image. TODO: possible 'updated' image more suitable... $repl .= ' '.tra('; } } else { $repl = strlen( trim( $text[0] ) ) > 0 ? $text[0] : $pages[1][$i]; if( $gBitUser->hasPermission( 'p_wiki_edit_page' ) ) { $uri_ref = WIKI_PKG_URL."edit.php?page=" . urlencode($pages[1][$i]); $repl = ' '.$repl.''; } } $data = preg_replace($pattern, "$repl", $data); } } // We need to remove ))wWikiWords(( before links get made. // users just need to be strict about not inserting spaces between // words and brackets $data = preg_replace( "! \){2} # check for )) ([\w_\-]+?) # any letter plus - and _ - placed in $1 \({2} # closing (( !x", "$1", $data ); // New syntax for wiki pages ((name)) Where name can be anything preg_match_all("/\({2}(.+?)\){2}/", $data, $pages); foreach (array_unique($pages[1])as $page_parse) { $repl2 = true; if (strstr($page_parse, ':')) { $wexs = explode(':', $page_parse); if (count($wexs) == 2) { $wkname = $wexs[0]; if ($this->mDb->getOne("select count(*) from `".BIT_DB_PREFIX."wiki_ext` where `name`=?",array($wkname)) == 1) { $wkurl = $this->mDb->getOne("select `extwiki` from `".BIT_DB_PREFIX."wiki_ext` where `name`=?",array($wkname)); $wkurl = '' . $wexs[1] . ''; $data = preg_replace("/\(\($page_parse\)\)/", "$wkurl", $data); $repl2 = false; } } } if ($repl2) { // This is a hack for now. page_exists_desc should not be needed here sicne blogs and articles use this function $exists = $this->pageExists( $page_parse, $pageList, $pCommonObject, $contentId ); $repl = BitPage::getDisplayLink( $page_parse, $exists ); $page_parse_pq = preg_quote($page_parse, "/"); $data = preg_replace("/\(\($page_parse_pq\)\)/", "$repl", $data); } } if ($gBitSystem->isPackageActive( 'hotwords' ) ) { if( empty( $hotwordlib ) ) { include_once(HOTWORDS_PKG_PATH."hotword_lib.php"); global $hotwordlib; $words = $hotwordlib->get_hotwords(); } } // Links to internal pages // If they are parenthesized then don't treat as links // Prevent ))PageName(( from being expanded \"\' //[A-Z][a-z0-9_\-]+[A-Z][a-z0-9_\-]+[A-Za-z0-9\-_]* if( $gBitSystem->isPackageActive( 'wiki' ) && $gBitSystem->isFeatureActive( 'wiki_words' ) ) { // The first part is now mandatory to prevent [Foo|MyPage] from being converted! // the {2} is curious but seems to prevent things like "__Administration / Modules__" getting linked - spiderr $pages = $this->extractWikiWords( $data ); foreach( $pages as $page_parse) { if( empty( $words ) || !array_key_exists( $page_parse, $words ) ) { if( $exists = $this->pageExists( $page_parse, $pageList, $pCommonObject, $contentId ) ) { $repl = BitPage::getDisplayLink( $page_parse, $exists ); } elseif( $gBitSystem->isFeatureActive( 'wiki_plurals') && $this->get_locale() == 'en_US' ) { // Link plural topic names to singular topic names if the plural // doesn't exist, and the language is english $plural_tmp = $page_parse; // Plurals like policy / policies $plural_tmp = preg_replace("/ies$/", "y", $plural_tmp); // Plurals like address / addresses $plural_tmp = preg_replace("/sses$/", "ss", $plural_tmp); // Plurals like box / boxes $plural_tmp = preg_replace("/([Xx])es$/", "$1", $plural_tmp); // Others, excluding ending ss like address(es) $plural_tmp = preg_replace("/([A-Za-rt-z])s$/", "$1", $plural_tmp); // prevent redundant pageExists calls if plurals are on, and plural is same as original word if( $page_parse != $plural_tmp ) { $exists = $this->pageExists( $plural_tmp, $pageList, $pCommonObject, $contentId ); } $repl = BitPage::getDisplayLink( $plural_tmp, $exists ); } else { $repl = BitPage::getDisplayLink( $page_parse, $exists ); } // use preg_quote instead // This original breaks numeric 'create page' links in tables for unregistered users $slashed = preg_replace( "/([\/\[\]\(\)])/", "\\\\$1", $page_parse ); //$data = preg_replace("/([ \n\t\r\,\;]|^)".$slashed."($|[ \n\t\r\,\;\.])/", "$1"."$repl"."$2", $data); $data = preg_replace( "#([\s\,\;])\b$slashed\b([\s\,\;\.])#", "$1 ".$repl."$2", $data); //$data = preg_replace( "/".preg_quote( $page_parse, "/" )."/", $repl, $data); //$data = str_replace($page_parse,$repl,$data); } } } // reinsert hash-replaced links into page foreach ($noparsedlinks as $np) { $data = str_replace($np["key"], $np["data"], $data); } // TODO: I think this is 1. just wrong and 2. not needed here? remove it? // Replace ))Words(( $data = preg_replace("/\(\(([^\)]+)\)\)/", "$1", $data); $links = $this->get_links($data); $notcachedlinks = $this->get_links_nocache($data); $cachedlinks = array_diff($links, $notcachedlinks); $this->cache_links($cachedlinks,$pCommonObject); // Note that there're links that are replaced foreach ($links as $link) { if ((strstr($link, $_SERVER["SERVER_NAME"])) || (!strstr($link, '//'))) { $class = ''; } else { $class = 'class="external"'; } // comments and anonymously created pages get nofollow if( $pCommonObject && (get_class( $pCommonObject ) == 'comments' || ( isset( $pCommonObject->mInfo['user_id'] ) && $pCommonObject->mInfo['user_id'] == ANONYMOUS_USER_ID ) ) ) { $class .= ' rel="nofollow" '; } // The (?isFeatureActive( 'liberty_cache_pages') && $pCommonObject->isCached( $link ) ) { //use of urlencode for using cached versions of dynamic sites $cosa = "(cache)"; //$link2 = str_replace("/","\/",$link); //$link2 = str_replace("?","\?",$link2); //$link2 = str_replace("&","\&",$link2); $link2 = str_replace("/", "\/", preg_quote($link)); $pattern = "/(?$1", $data); $pattern = "/(?$1 $cosa", $data); $pattern = "/(?$link $cosa", $data); } else { //$link2 = str_replace("/","\/",$link); //$link2 = str_replace("?","\?",$link2); //$link2 = str_replace("&","\&",$link2); $link2 = str_replace("/", "\/", preg_quote($link)); $pattern = "/(?$1", $data); $pattern = "/(?$link", $data); } } // Handle double square brackets. -rlpowell $data = str_replace( "[[", "[", $data ); if ($gBitSystem->getConfig('wiki_tables') != 'new') { // New syntax for tables if (preg_match_all("/\|\|(.*)\|\|/", $data, $tables)) { $maxcols = 1; $cols = array(); for ($i = 0; $i < count($tables[0]); $i++) { $rows = explode('||', $tables[0][$i]); $col[$i] = array(); for ($j = 0; $j < count($rows); $j++) { $cols[$i][$j] = explode('|', $rows[$j]); if (count($cols[$i][$j]) > $maxcols) $maxcols = count($cols[$i][$j]); } } for ($i = 0; $i < count($tables[0]); $i++) { $repl = ''; for ($j = 0; $j < count($cols[$i]); $j++) { $ncols = count($cols[$i][$j]); if ($ncols == 1 && !$cols[$i][$j][0]) continue; $repl .= ''; for ($k = 0; $k < $ncols; $k++) { $repl .= ''; } $repl .= '
'; } $repl .= '
'; $data = str_replace($tables[0][$i], $repl, $data); } } } else { // New syntax for tables // REWRITE THIS CODE if (preg_match_all("/\|\|(.*?)\|\|/s", $data, $tables)) { $maxcols = 1; $cols = array(); for ($i = 0; $i < count($tables[0]); $i++) { $rows = split("\n|\", $tables[0][$i]); $col[$i] = array(); for ($j = 0; $j < count($rows); $j++) { $rows[$j] = str_replace('||', '', $rows[$j]); $cols[$i][$j] = explode('|', $rows[$j]); if (count($cols[$i][$j]) > $maxcols) $maxcols = count($cols[$i][$j]); } } for ($i = 0; $i < count($tables[0]); $i++) { $repl = ''; for ($j = 0; $j < count($cols[$i]); $j++) { $ncols = count($cols[$i][$j]); if ($ncols == 1 && !$cols[$i][$j][0]) continue; $repl .= ''; for ($k = 0; $k < $ncols; $k++) { $repl .= ''; } $repl .= '
'; } $repl .= '
'; $data = str_replace($tables[0][$i], $repl, $data); } } } // change back any end of lines that were temporarily removed in parse_data_plugins $data = preg_replace( "/#EOL/", "\n", $data ); // 08-Jul-2003, by zaufi // HotWords will be replace only in ordinal text // It looks __realy__ goofy in Headers or Titles // Get list of HotWords if ( isset($hotwordlib) ) { $words = $hotwordlib->get_hotwords(); } else { $words = ''; } // Now tokenize the expression and process the tokens // Use tab and newline as tokenizing characters as well //// $lines = explode("\n", $data); $data = ''; $listbeg = array(); $divdepth = array(); $inTable = 0; // loop: process all lines foreach ($lines as $line) { // bitweaver now ignores leading space because it is *VERY* disturbing to unaware users - spiderr // unless 'feature_wiki_preserve_leading_blanks is set'. This is used for sites that have // migrated from TikiWiki and have lots of pages whose formatting depends on the presevation of leading spaces if (!$gBitSystem->isFeatureActive('wiki_preserve_leading_blanks')) { $line = trim( $line ); } // Check for titlebars... // NOTE: that title bar should be start from begining of line and // be alone on that line to be autoaligned... else it is old styled // styled title bar... if (substr(ltrim($line), 0, 2) == '-=' && substr(rtrim($line), -2, 2) == '=-') { // This is not list item -- must close lists currently opened while (count($listbeg)) $data .= array_shift($listbeg); // $align_len = strlen($line) - strlen(ltrim($line)); // My textarea size is about 120 space chars. //define('TEXTAREA_SZ', 120); // NOTE: That strict math formula (split into 3 areas) gives // bad visual effects... // $align = ($align_len < (TEXTAREA_SZ / 3)) ? "left" // : (($align_len > (2 * TEXTAREA_SZ / 3)) ? "right" : "center"); // // Going to introduce some heuristic here :) // Visualy (remember that space char is thin) center starts at 25 pos // and 'right' from 60 (HALF of full width!) -- thats all :) // // NOTE: Guess align only if more than 10 spaces before -=title=- if ($align_len > 10) { $align = ($align_len < 25) ? "left" : (($align_len > 60) ? "right" : "center"); $align = ' style="text-align: ' . $align . ';"'; } else { $align = ''; } // $line = trim($line); $line = '
' . substr($line, 2, strlen($line) - 4). '
'; $data .= $line; // TODO: Case is handled ... no need to check other conditions // (it is apriory known all they false, moreover sometimes // check procedure need > O(0) of compexity) // -- continue to next line... // MUST replace all remaining parse blocks to the same logic... continue; } // Replace old styled titlebars if (strlen($line) != strlen($line = preg_replace("/-=(.+?)=-/", "
$1
", $line))) { $data .= $line; continue; } // check if we are inside a table, if so, ignore monospaced and do // not insert
$inTable += substr_count($line, "isFeatureActive('wiki_monosp') && $inTable == 0) { // This is not list item -- must close lists currently opened while (count($listbeg)) $data .= array_shift($listbeg); // If the first character is space then // change spaces for   $line = '' . str_replace(' ', ' ', substr($line, 1)). ''; } // Replace Hotwords before begin if ($gBitSystem->isPackageActive( 'hotwords' ) ) { $line = $hotwordlib->replace_hotwords($line, $words); } // Replace monospaced text $line = preg_replace("/-\+(.*?)\+-/", "$1", $line); // Replace bold text $line = preg_replace("/__(.*?)__/", "$1", $line); $line = preg_replace("/\'\'(.*?)\'\'/", "$1", $line); // Replace definition lists $line = preg_replace("/^;([^:]+):([^\n]+)/", "
$1
$2
", $line); if (0) { $line = preg_replace("/\[([^\|]+)\|([^\]]+)\]/", "$2", $line); // Segundo intento reemplazar los [link] comunes $line = preg_replace("/\[([^\]]+)\]/", "$1", $line); $line = preg_replace("/\-\=([^=]+)\=\-/", "
$1
", $line); } // This line is parseable then we have to see what we have if (substr($line, 0, 3) == '---') { // This is not list item -- must close lists currently opened while (count($listbeg)) $data .= array_shift($listbeg); $line = '
'; } else { $litype = substr($line, 0, 1); if ($litype == '*' || $litype == '#') { $listlevel = $this->how_many_at_start($line, $litype); $liclose = ''; $addremove = 0; if ($listlevel < count($listbeg)) { while ($listlevel != count($listbeg)) $data .= array_shift($listbeg); if (substr(current($listbeg), 0, 5) != '') $liclose = ''; } elseif ($listlevel > count($listbeg)) { $listyle = ''; while ($listlevel != count($listbeg)) { array_unshift($listbeg, ($litype == '*' ? '' : '')); if ($listlevel == count($listbeg)) { $listate = substr($line, $listlevel, 1); if (($listate == '+' || $listate == '-') && !($litype == '*' && !strstr(current($listbeg), '') || $litype == '#' && !strstr(current($listbeg), ''))) { $thisid = 'id' . microtime() * 1000000; $data .= '
[' . ($listate == '-' ? '+' : '-') . ']'; $listyle = ' id="' . $thisid . '" style="display:' . ($listate == '+' ? 'block' : 'none') . ';"'; $addremove = 1; } } $data .= ($litype == '*' ? "" : ""); } $liclose = ''; } if ($litype == '*' && !strstr(current($listbeg), '') || $litype == '#' && !strstr(current($listbeg), '')) { $data .= array_shift($listbeg); $listyle = ''; $listate = substr($line, $listlevel, 1); if (($listate == '+' || $listate == '-')) { $thisid = 'id' . microtime() * 1000000; $data .= '
[' . ($listate == '-' ? '+' : '-') . ']'; $listyle = ' id="' . $thisid . '" style="display:' . ($listate == '+' ? 'block' : 'none') . ';"'; $addremove = 1; } $data .= ($litype == '*' ? "" : ""); $liclose = ''; array_unshift($listbeg, ($litype == '*' ? '' : '')); } $line = $liclose . '
  • ' . substr($line, $listlevel + $addremove); if (substr(current($listbeg), 0, 5) != '
  • ') array_unshift($listbeg, '' . array_shift($listbeg)); } elseif ($litype == '+') { // Must append paragraph for list item of given depth... $listlevel = $this->how_many_at_start($line, $litype); // Close lists down to requested level while ($listlevel < count($listbeg)) $data .= array_shift($listbeg); if (count($listbeg)) { if (substr(current($listbeg), 0, 5) != '') { array_unshift($listbeg, '' . array_shift($listbeg)); $liclose = '
  • '; } else $liclose = '
    '; } else $liclose = ''; $line = $liclose . substr($line, count($listbeg)); } else { // This is not list item -- must close lists currently opened while (count($listbeg)) $data .= array_shift($listbeg); // Get count of (possible) header signs at start $hdrlevel = $this->how_many_at_start($line, '!'); // If 1st char on line is '!' and its count less than 6 (max in HTML) if ($litype == '!' && $hdrlevel > 0 && $hdrlevel <= 6) { // Remove possible hotwords replaced :) // Umm, *why*? Taking this out lets page // links in headers work, which can be nice. // -rlpowell // $line = strip_tags($line); // OK. Parse headers here... $anchor = ''; $aclose = ''; $addremove = 0; // Close lower level divs if opened for (;current($divdepth) >= $hdrlevel; array_shift($divdepth)) $data .= '
  • '; // May be spesial signs present after '!'s? $divstate = substr($line, $hdrlevel, 1); if ($divstate == '+' || $divstate == '-') { // OK. Must insert flipper after HEADER, and then open new div... $thisid = 'id' . microtime() * 1000000; $aclose = '[' . ($divstate == '-' ? '+' : '-') . ']'; $aclose .= '
    '; array_unshift($divdepth, $hdrlevel); $addremove = 1; } $edit_link = ''; if( $gBitSystem->isFeatureActive( 'wiki_section_edit' ) && $gBitUser->hasPermission( 'p_wiki_edit_page' ) ) { if( $hdrlevel == $gBitSystem->getConfig( 'wiki_section_edit' ) ) { $edit_url = WIKI_PKG_URL."edit.php?content_id=".$contentId."&action=edit_sectin&section=".$section_count++; $edit_link = '['.tra( "edit" ).']'; } } $line = $edit_link . $anchor . "" . substr($line, $hdrlevel + $addremove) . "" . $aclose ; } elseif (!strcmp($line, "...page...")) { // Close lists and divs currently opened while (count($listbeg)) $data .= array_shift($listbeg); while (count($divdepth)) { $data .= '
    '; array_shift ($divdepth); } // Leave line unchanged... index.php will split wiki here $line = "...page..."; } else { // Usual paragraph. if ($inTable == 0 && !preg_match("/\{maketoc.*?\}/i",$line)) { $line .= '
    '; } } } } $data .= $line; } // Close lists may remains opened while (count($listbeg)) { $data .= array_shift($listbeg); } // Close header divs may remains opened for ($i = 1; $i <= count($divdepth); $i++) { $data .= '
    '; } // Close BiDi DIVs if any for ($i = 0; $i < $bidiCount; $i++) { $data .= ""; } foreach ($noparsed as $np) { $data = str_replace($np["key"], $np["data"], $data); } foreach ($preparsed as $pp) { $data = str_replace($pp["key"], "
    " . $pp["data"] . "
    ", $data); } // Process pos_handlers here foreach ($this->pos_handlers as $handler) { $data = $handler($data); } global $gLibertySystem; // create a table of contents for this page // this function is called manually, since it processes the HTML code if( preg_match( "/\{maketoc.*?\}/i", $data ) && @$gLibertySystem->mPlugins['datamaketoc']['is_active'] == 'y' ) { $data = data_maketoc($data); } return $data; } } ?>