ENHANCEMENT #3677 Added more rules for escaping reserved characters in XML to their proper entities e.g. ' => '

BUGFIX When exporting data from TableListField to a CSV via TableListField_Item->Fields(), don't convert the values to XML
MINOR Added test class ConvertTest with tests for various Convert functions



git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@77298 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sean Harvey 2009-05-20 03:09:50 +00:00
parent 5e8b144318
commit e768d955df
3 changed files with 90 additions and 51 deletions

View File

@ -22,27 +22,38 @@
*/
class Convert extends Object {
/**
* Convert a value to be suitable for an XML attribute.
*
* @param array|string $val String to escape, or array of strings
* @return array|string
*/
static function raw2att($val) {
if(is_array($val)) {
foreach($val as $k => $v) $val[$k] = self::raw2att($v);
return $val;
} else {
return str_replace(array('&','"',"'",'<','>'),array('&amp;','&quot;','&#39;','&lt;','&gt;'),$val);
return str_replace(array('&','"',"'",'<','>'), array('&amp;','&quot;','&apos;','&lt;','&gt;'), $val);
}
}
/**
* Convert a value to be suitable for an HTML attribute.
*
* This is useful for converting human readable values into
* a value suitable for an ID or NAME attribute.
*
* @see http://www.w3.org/TR/REC-html40/types.html#type-cdata
* @uses raw2att
* @uses Convert::raw2att()
* @param array|string $val String to escape, or array of strings
* @return array|string
*/
static function raw2htmlatt($val) {
if(is_array($val)) {
foreach($val as $k => $v) $val[$k] = self::raw2att($v);
foreach($val as $k => $v) $val[$k] = self::raw2htmlatt($v);
return $val;
} else {
$val = str_replace(array('&','"',"'",'<','>'),array('&amp;','&quot;','&#39;','&lt;','&gt;'),$val);
$val = self::raw2att($val);
$val = preg_replace('/[^a-zA-Z0-9\-_]*/', '', $val);
return $val;
}
@ -51,6 +62,7 @@ class Convert extends Object {
/**
* Ensure that text is properly escaped for XML.
*
* @see http://www.w3.org/TR/REC-xml/#dt-escape
* @param array|string $val String to escape, or array of strings
* @return array|string
*/
@ -59,7 +71,7 @@ class Convert extends Object {
foreach($val as $k => $v) $val[$k] = self::raw2xml($v);
return $val;
} else {
return str_replace(array('&', '<', '>', "\n"), array('&amp;', '&lt;', '&gt;', '<br />'), $val);
return str_replace(array('&','<','>',"\n",'"',"'"), array('&amp;','&lt;','&gt;','<br />','&quot;','&apos;'), $val);
}
}
@ -99,19 +111,17 @@ class Convert extends Object {
}
}
static function raw2sql($val) {
if(is_array($val)) {
foreach($val as $k => $v) $val[$k] = self::raw2sql($v);
return $val;
} else {
return DB::getConn()->addslashes($val);
}
}
/**
* Convert XML to raw text
* Convert XML to raw text.
* @uses html2raw()
* @todo Currently &#xxx; entries are stripped; they should be converted
*/
@ -119,20 +129,15 @@ class Convert extends Object {
if(is_array($val)) {
foreach($val as $k => $v) $val[$k] = self::xml2raw($v);
return $val;
} else {
// More complex text needs to use html2raw instaed
// More complex text needs to use html2raw instead
if(strpos($val,'<') !== false) return self::html2raw($val);
// For simpler stuff, a simple str_replace will do
else {
$converted = str_replace(array('&amp;', '&lt;', '&gt;', '&apos;'), array('&', '<', '>', "'"), $val);
$converted = str_replace(array('&amp;','&lt;','&gt;','&quot;','&apos;'), array('&','<','>','"',"'"), $val);
$converted = ereg_replace('&#[0-9]+;', '', $converted);
return $converted;
}
}
}
/**
* @deprecated 2.3 Functionality too ambiguous - not sure if its converting
@ -200,13 +205,9 @@ class Convert extends Object {
* @return mixed JSON safe string
*/
static function json2obj($val) {
//if(function_exists('json_decode')) {
// return json_decode($val);
//} else {
require_once(Director::baseFolder() . '/sapphire/thirdparty/json/JSON.php');
$json = new Services_JSON();
return $json->decode($val);
//}
}
/**
@ -264,8 +265,6 @@ class Convert extends Object {
return '{' . implode( ', ', $result ) . '}';
}
/**
* Create a link if the string is a valid URL
* @param string The string to linkify
@ -278,18 +277,6 @@ class Convert extends Object {
return $string;
}
/**
* Create a link if the string is a valid URL
* @param string The string to linkify
* @return A link to the URL if string is a URL
*/
/*static function mailtoIfMatch($string) {
if( preg_match( '/^[a-z+]+\:\/\/[a-zA-Z0-9$-_.+?&=!*\'()%]+$/', $string ) )
return "<a href=\"$string\">$string</a>";
else
return $string;
}*/
/**
* Simple conversion of HTML to plaintext.
*

View File

@ -957,7 +957,7 @@ JS
}
$fieldItem = new TableListField_Item($item, $this);
$fields = $fieldItem->Fields();
$fields = $fieldItem->Fields(false);
$columnData = array();
if($fields) foreach($fields as $field) {
$value = $field->Value;
@ -1241,16 +1241,16 @@ class TableListField_Item extends ViewableData {
return $this->parent;
}
function Fields() {
function Fields($xmlSafe = true) {
$list = $this->parent->FieldList();
foreach($list as $fieldName => $fieldTitle) {
$value = "";
// This supports simple FieldName syntax
if(strpos($fieldName,'.') === false) {
$value = ($this->item->XML_val($fieldName)) ? $this->item->XML_val($fieldName) : $this->item->$fieldName;
// This support the syntax fieldName = Relation.RelatedField
$value = ($this->item->XML_val($fieldName) && $xmlSafe) ? $this->item->XML_val($fieldName) : $this->item->$fieldName;
} else {
// This supports the syntax fieldName = Relation.RelatedField
$fieldNameParts = explode('.', $fieldName) ;
$tmpItem = $this->item;
for($j=0;$j<sizeof($fieldNameParts);$j++) {
@ -1285,7 +1285,6 @@ class TableListField_Item extends ViewableData {
}
}
$fields[] = new ArrayData(array(
"Name" => $fieldName,
"Title" => $fieldTitle,

53
tests/ConvertTest.php Normal file
View File

@ -0,0 +1,53 @@
<?php
/**
* Test various functions on the {@link Convert} class.
* @package sapphire
* @subpackage tests
*/
class ConvertTest extends SapphireTest {
/**
* Tests {@link Convert::raw2att()}
*/
function testRaw2Att() {
$val1 = '<input type="text">';
$this->assertEquals('&lt;input type=&quot;text&quot;&gt;', Convert::raw2att($val1), 'Special characters are escaped');
$val2 = 'This is some normal text.';
$this->assertEquals('This is some normal text.', Convert::raw2att($val2), 'Normal text is not escaped');
}
/**
* Tests {@link Convert::raw2htmlatt()}
*/
function testRaw2HtmlAtt() {
$val1 = '<input type="text">';
$this->assertEquals('ltinputtypequottextquotgt', Convert::raw2htmlatt($val1), 'Special characters are escaped');
$val2 = 'This is some normal text.';
$this->assertEquals('Thisissomenormaltext', Convert::raw2htmlatt($val2), 'Normal text is not escaped');
}
/**
* Tests {@link Convert::raw2xml()}
*/
function testRaw2Xml() {
$val1 = '<input type="text">';
$this->assertEquals('&lt;input type=&quot;text&quot;&gt;', Convert::raw2xml($val1), 'Special characters are escaped');
$val2 = 'This is some normal text.';
$this->assertEquals('This is some normal text.', Convert::raw2xml($val2), 'Normal text is not escaped');
}
/**
* Tests {@link Convert::xml2raw()}
*/
function testXml2Raw() {
$val1 = '&lt;input type=&quot;text&quot;&gt;';
$this->assertEquals('<input type="text">', Convert::xml2raw($val1), 'Special characters are escaped');
$val2 = 'This is some normal text.';
$this->assertEquals('This is some normal text.', Convert::xml2raw($val2), 'Normal text is not escaped');
}
}