parse_readme_contents( $file_contents ); } function parse_readme_contents( $file_contents ) { $file_contents = str_replace(array("\r\n", "\r"), "\n", $file_contents); $file_contents = trim($file_contents); if ( 0 === strpos( $file_contents, "\xEF\xBB\xBF" ) ) $file_contents = substr( $file_contents, 3 ); // Markdown transformations $file_contents = preg_replace( "|^###([^#]+)#*?\s*?\n|im", '=$1='."\n", $file_contents ); $file_contents = preg_replace( "|^##([^#]+)#*?\s*?\n|im", '==$1=='."\n", $file_contents ); $file_contents = preg_replace( "|^#([^#]+)#*?\s*?\n|im", '===$1==='."\n", $file_contents ); // === Plugin Name === // Must be the very first thing. if ( !preg_match('|^===(.*)===|', $file_contents, $_name) ) return []; // require a name $name = trim($_name[1], '='); $name = $this->sanitize_text( $name ); $file_contents = $this->chop_string( $file_contents, $_name[0] ); // Requires at least: 1.5 if ( preg_match('|Requires at least:(.*)|i', $file_contents, $_requires_at_least) ) $requires_at_least = $this->sanitize_text($_requires_at_least[1]); else $requires_at_least = NULL; // Tested up to: 2.1 if ( preg_match('|Tested up to:(.*)|i', $file_contents, $_tested_up_to) ) $tested_up_to = $this->sanitize_text( $_tested_up_to[1] ); else $tested_up_to = NULL; // Requires PHP: 5.2.4 if ( preg_match('|Requires PHP:(.*)|i', $file_contents, $_requires_php) ) { $requires_php = $this->sanitize_text( $_requires_php[1] ); } else { $requires_php = null; } // Stable tag: 10.4-ride-the-fire-eagle-danger-day if ( preg_match('|Stable tag:(.*)|i', $file_contents, $_stable_tag) ) $stable_tag = $this->sanitize_text( $_stable_tag[1] ); else $stable_tag = NULL; // we assume trunk, but don't set it here to tell the difference between specified trunk and default trunk // Tags: some tag, another tag, we like tags if ( preg_match('|Tags:(.*)|i', $file_contents, $_tags) ) { $tags = preg_split('|,[\s]*?|', trim($_tags[1])); foreach ( array_keys($tags) as $t ) $tags[$t] = $this->sanitize_text( $tags[$t] ); } else { $tags = []; } // Contributors: markjaquith, mdawaffe, zefrank $contributors = []; if ( preg_match('|Contributors:(.*)|i', $file_contents, $_contributors) ) { $temp_contributors = preg_split('|,[\s]*|', trim($_contributors[1])); foreach ( array_keys($temp_contributors) as $c ) { $tmp_sanitized = $this->user_sanitize( $temp_contributors[$c] ); if ( strlen(trim($tmp_sanitized)) > 0 ) $contributors[$c] = $tmp_sanitized; unset($tmp_sanitized); } } // Donate Link: URL if ( preg_match('|Donate link:(.*)|i', $file_contents, $_donate_link) ) $donate_link = esc_url( $_donate_link[1] ); else $donate_link = NULL; // togs, conts, etc are optional and order shouldn't matter. So we chop them only after we've grabbed their values. foreach ( array('tags', 'contributors', 'requires_at_least', 'tested_up_to', 'stable_tag', 'donate_link') as $chop ) { if ( $$chop ) { $_chop = '_' . $chop; $file_contents = $this->chop_string( $file_contents, ${$_chop}[0] ); } } $file_contents = trim($file_contents); // short-description fu if ( !preg_match('/(^(.*?))^[\s]*=+?[\s]*.+?[\s]*=+?/ms', $file_contents, $_short_description) ) $_short_description = array( 1 => &$file_contents, 2 => &$file_contents ); $short_desc_filtered = $this->sanitize_text( $_short_description[2] ); $short_desc_length = strlen($short_desc_filtered); $short_description = substr($short_desc_filtered, 0, 150); if ( $short_desc_length > strlen($short_description) ) $truncated = true; else $truncated = false; if ( $_short_description[1] ) $file_contents = $this->chop_string( $file_contents, $_short_description[1] ); // yes, the [1] is intentional // == Section == // Break into sections // $_sections[0] will be the title of the first section, $_sections[1] will be the content of the first section // the array alternates from there: title2, content2, title3, content3... and so forth $_sections = preg_split('/^[\s]*==[\s]*(.+?)[\s]*==/m', $file_contents, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); $sections = []; for ( $i=0; $i < count($_sections); $i +=2 ) { $title = $this->sanitize_text( $_sections[$i] ); if ( isset($_sections[$i+1]) ) { $content = preg_replace('/(^[\s]*)=[\s]+(.+?)[\s]+=/m', '$1
|)(.*?)(
|)!s", array( __CLASS__,'decodeit'), $text);
$text = str_replace(array("\r\n", "\r"), "\n", $text);
if ( !$markdown ) {
// This gets the "inline" code blocks, but can't be used with Markdown.
$text = preg_replace_callback("|(`)(.*?)`|", array( __CLASS__, 'encodeit'), $text);
// This gets the "block level" code blocks and converts them to PRE CODE
$text = preg_replace_callback("!(^|\n)`(.*?)`!s", array( __CLASS__, 'encodeit'), $text);
} else {
// Markdown can do inline code, we convert bbPress style block level code to Markdown style
$text = preg_replace_callback("!(^|\n)([ \t]*?)`(.*?)`!s", array( __CLASS__, 'indent'), $text);
}
return $text;
}
function indent( $matches ) {
$text = $matches[3];
$text = preg_replace('|^|m', $matches[2] . ' ', $text);
return $matches[1] . $text;
}
function encodeit( $matches ) {
if ( function_exists('encodeit') ) // bbPress native
return encodeit( $matches );
$text = trim($matches[2]);
$text = htmlspecialchars($text, ENT_QUOTES);
$text = str_replace(array("\r\n", "\r"), "\n", $text);
$text = preg_replace("|\n\n\n+|", "\n\n", $text);
$text = str_replace('<', '<', $text);
$text = str_replace('>', '>', $text);
$text = "$text
";
if ( "`" != $matches[1] )
$text = "$text"; return $text; } function decodeit( $matches ) { if ( function_exists('decodeit') ) // bbPress native return decodeit( $matches ); $text = $matches[2]; $trans_table = array_flip(get_html_translation_table(HTML_ENTITIES)); $text = strtr($text, $trans_table); $text = str_replace('
' == $matches[1] )
$text = "\n$text\n";
return "`$text`";
}
} // end class
endif;