Index: Parser.php
===================================================================
RCS file: /root/phase3/includes/Parser.php,v
retrieving revision 1.327
diff -u -r1.327 Parser.php
--- Parser.php	11 Oct 2004 22:10:14 -0000	1.327
+++ Parser.php	12 Oct 2004 02:33:39 -0000
@@ -203,32 +203,80 @@
 		return dechex(mt_rand(0, 0x7fffffff)) . dechex(mt_rand(0, 0x7fffffff));
 	}
 
+	/**
+	 * Extracts parameters from a tag
+	 * and returns as an associative list in form param => value
+	 *
+	 * example extractParams('<tag param1="val1" param2="val2">')
+	 * returns array( "param1" => "val1", "param2" => "val2")
+	 *
+	 * @access private
+	 * @static
+	 */
+	function extractParams($tag) {
+		$params = array();
+		//regexp to match param="value" pairs
+		//regexp allows for backslash escaped quote marks in value
+		// (\x5C"|[^"]) means match \" or anything except "
+
+		$dquot_str_re = '("(\x5C"|[^"])*")';
+		$squot_str_re = '(\'(\x5C\'|[^\'])*\')';
+		$param_regexp = "/(\w+)=($dquot_str_re|$squot_str_re)/";
+
+		preg_match_all( $param_regexp, $tag, $matches ) ;
+		foreach ( $matches[1] as $key => $param_name ) {
+			$paramval = $matches[2][$key];
+			//enscape escaped " marks
+			$paramval = preg_replace('/\x5C"/', '"', $paramval);
+			$params[$param_name] = $paramval;
+		}
+		
+		return $params;
+	}
+
 	/** 
 	 * Replaces all occurrences of <$tag>content</$tag> in the text
-	 * with a random marker and returns the new text. the output parameter
-	 * $content will be an associative array filled with data on the form
-	 * $unique_marker => content.
+	 * with a random marker and returns the new text. 
+	 * the output parameter $content will be an array filled 
+	 * with data $unique_marker => content, where content is the content of the tag
+	 * the output parameter $tags will be an associative array filled 
+	 * with data $unique_marker => tag, where tag is the full opening tag
+	 * the output parameter $params will be an associative array filled 
+	 * with data $unique_marker => params, where params is an associative
+	 * array of the parameters of the tag in the form param_name => param
 	 * 
-	 * If $content is already set, the additional entries will be appended
+	 * If the output parameters are already set, the additional entries will be appended
 	 * If $tag is set to STRIP_COMMENTS, the function will extract
 	 * <!-- HTML comments -->
 	 *
 	 * @access private
 	 * @static
 	 */
-	function extractTags($tag, $text, &$content, $uniq_prefix = ''){
+	function extractTagsAndParams($tag, $text, &$content, &$tags, &$params, $uniq_prefix = ''){
 		$rnd = $uniq_prefix . '-' . $tag . Parser::getRandomString();
 		if ( !$content ) {
 			$content = array( );
 		}
 		$n = 1;
 		$stripped = '';
+	
+		if ( !$tags ) {
+			$tags = array( );
+		}
+		
+		if ( !$params ) {
+			$params = array( );
+		}
+
+		$dquot_str_re = '("(\x5C"|[^"])*")';
+		$squot_str_re = '(\'(\x5C\'|[^\'])*\')';
+		$param_regexp = "(\s+\w+=($dquot_str_re|$squot_str_re))*";
 
 		while ( '' != $text ) {
 			if($tag==STRIP_COMMENTS) {
 				$p = preg_split( '/<!--/i', $text, 2 );
 			} else {
-				$p = preg_split( "/<\\s*$tag\\s*>/i", $text, 2 );
+				$p = preg_split( "/<\\s*$tag$param_regexp\\s*>/i", $text, 2 );
 			}
 			$stripped .= $p[0];
 			if ( ( count( $p ) < 2 ) || ( '' == $p[1] ) ) {
@@ -239,8 +287,11 @@
 				} else {
 					$q = preg_split( "/<\\/\\s*$tag\\s*>/i", $p[1], 2 );
 				}
+				preg_match( "/<\\s*$tag$param_regexp\\s*>/i", $text, $match );
 				$marker = $rnd . sprintf('%08X', $n++);
 				$content[$marker] = $q[0];
+				$tags[$marker] = $match[0];
+				$params[$marker] = Parser::extractParams($match[0]);
 				$stripped .= $marker;
 				$text = $q[1];
 			}
@@ -249,6 +300,21 @@
 	}
 
 	/**
+	 * Wrapper function for extractTagsAndParams
+	 * for cases where $tags and $params isn't needed
+	 * i.e. where tags will never have params, like <nowiki>
+	 *
+	 * @access private
+	 * @static
+	 */
+	function extractTags($tag, $text, &$content, $uniq_prefix = '') {
+		$dummy_tags = array ();
+		$dummy_params = array ();
+		
+		return Parser::extractTagsAndParams($tag, $text, $content, $dummy_tags, $dummy_params, $uniq_prefix);
+	}
+	
+	/**
 	 * Strips and renders nowiki, pre, math, hiero
 	 * If $render is set, performs necessary rendering operations on plugins
 	 * Returns the text, and fills an array with data needed in unstrip()
@@ -333,13 +399,16 @@
 		# Extensions
 		foreach ( $this->mTagHooks as $tag => $callback ) {
 			$ext_contents[$tag] = array();
-			$text = Parser::extractTags( $tag, $text, $ext_content[$tag], $uniq_prefix );
+			$text = Parser::extractTagsAndParams( $tag, $text, $ext_content[$tag], 
+												  $ext_tags[$tag], $ext_params[$tag], $uniq_prefix );
 			foreach( $ext_content[$tag] as $marker => $content ) {
+				$full_tag = $ext_tags[$tag][$marker];
+				$params = $ext_params[$tag][$marker];
 				if ( $render ) {
-					$ext_content[$tag][$marker] = $callback( $content );
+					$ext_content[$tag][$marker] = $callback( $content, $params );
 				} else {
-					$ext_content[$tag][$marker] = "<$tag>$content</$tag>";
-				}
+					$ext_content[$tag][$marker] = "$full_tag$content</$tag>";
+			}
 			}
 		}
 
