This is in trunk. It's for an upcoming webtop release, which uses trunk. I filed this bug: http://www.openlaszlo.org/jira/browse/LPP-3773
A On Mar 22, Max Carlson wrote: > A few questions: > > Does this patch apply to trunk or legals/4.0? Also, there should really be a > bug filed against it so QA can verify the fix. And, please use the > svn-new/editchange/review scripts if it's in legals. Thanks! > > -Max > > Adam Wolff wrote: > > Summary: Newlines are not currently escaped in XML serialization. > > New Features: > > Bugs Fixed: N/A > > > > Technical > > Reviewer: max > > QA Reviewer: pablo > > Doc Reviewer: n/a > > > > Documentation: > > Release Notes: > > XML serialization has been updated to escape newlines in attribute values. > > > > Details: > > W3 character escaping says that the canonical form of CR uses an escape > > code. > > Server code that we're writing appears to support this. > > http://www.w3.org/TR/1999/WD-xml-c14n-19991109.html#charescaping > > > > NB that the linefeed or carriage return would be a reasonable > > choice here, but I went with carriage return since that best > > matches the definition of Javascript charCode 13. > > > > > > Tests: > > This is hard to test without server support, as the > > LFC allows literal newlines in attribute values. > > > > Files: > > WEB-INF/lps/lfc/data/LzDataNode.as > > > > =================================================================== > > --- WEB-INF/lps/lfc/data/LzDataNode.as (revision 4120) > > +++ WEB-INF/lps/lfc/data/LzDataNode.as (working copy) > > @@ -108,11 +108,16 @@ > > var olen = t.length; > > var r = ""; > > for ( var i = 0; i < olen; i++ ){ > > - var c = t.charAt( i ); > > - if ( this.__LZescapechars[ c ] != null ){ > > - r += this.__LZescapechars[ c ]; > > + //handle newlines > > + if ( t.charCodeAt( i ) == 13 ){ > > + r += "
"; > > } else { > > - r += c; > > + var c = t.charAt( i ); > > + if ( this.__LZescapechars[ c ] != null ){ > > + r += this.__LZescapechars[ c ]; > > + } else { > > + r += c; > > + } > > } > > } > > > > > > ------------------------------------------------------------------------ > > > > /****************************************************************************** > > * LzDataNode.as > > *****************************************************************************/ > > > > //* A_LZ_COPYRIGHT_BEGIN > > ****************************************************** > > //* Copyright 2001-2006 Laszlo Systems, Inc. All Rights Reserved. > > * > > //* Use is subject to license terms. > > * > > //* A_LZ_COPYRIGHT_END > > ******************************************************** > > > > //============================================================================== > > // DEFINE OBJECT: LzDataNode > > // > > // LzDataNode is the abstract baseclass for LzDataElement and LzDataText. > > //============================================================================== > > var LzDataNode = Class( "LzDataNode" , null, function (){ this.childNodes = > > []; } ); > > > > //@field Number nodeType: The type of this node -- ELEMENT_NODE or TEXT_NODE > > LzDataNode.prototype.nodeType = null; > > > > //@field LzDataNode ownerDocument: The ownerDocument of this node. > > LzDataNode.prototype.ownerDocument = null; > > > > //@field LzDataNode parentNode: The name of this node. > > LzDataNode.prototype.parentNode = null; > > LzDataNode.prototype.onparentNode = null; > > > > //@problem: how do I document these? > > LzDataNode.ELEMENT_NODE = 1; > > LzDataNode.TEXT_NODE = 3; > > LzDataNode.DOCUMENT_NODE = 9; > > > > //------------------------------------------------------------------------------ > > // Returns the sibling before this one this node's parentNodes List of > > children > > // @return LzDataNode: The node preceeding this one in this node's > > childNodes > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.getPreviousSibling = function (){ > > if ( this.parentNode.__LZcoDirty ) this.parentNode.__LZupdateCO(); > > return this.parentNode.childNodes[ this.__LZo - 1 ]; > > } > > > > //------------------------------------------------------------------------------ > > // @keywords private > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.getPreviousSibling.dependencies = function( who, self > > ){ > > return [ this.parentNode , "childNodes" , this , "parentNode" ]; > > } > > > > //------------------------------------------------------------------------------ > > // Returns the sibling after this one this node's parentNodes List of > > children > > // @return LzDataNode: The node succeeding this one in this node's > > childNodes > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.getNextSibling = function (){ > > if ( this.parentNode.__LZcoDirty ) this.parentNode.__LZupdateCO(); > > return this.parentNode.childNodes[ this.__LZo + 1 ]; > > } > > > > //------------------------------------------------------------------------------ > > // @keywords private > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.getNextSibling.dependencies = function( who, self ){ > > return [ this.parentNode , "childNodes" , this , "parentNode" ]; > > } > > > > //------------------------------------------------------------------------------ > > // Tells whether the given node is above this one in the node hierarchy. > > // @param LzDataElement el: The LzDataElement to test to see if it is above > > // this one > > // @param Boolean allowself: If true, this function returns true if the > > given > > // node is the same as this node. > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.childOf = function ( el , allowself ) { > > var p = allowself ? this : this.parentNode > > while ( p ){ > > if ( p == el ) return true; > > p = p.parentNode; > > } > > return false; > > } > > > > //------------------------------------------------------------------------------ > > // Sets the LzDataNode which is the ownerDocument for this node. > > // @param LzDataNode ownerDoc: The LzDataNode to act as the ownerDocument > > for > > // this node. > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.setOwnerDocument = function ( ownerDoc ){ > > this.ownerDocument = ownerDoc; > > for ( var i = 0; i < this.childNodes.length; i++ ){ > > this.childNodes[ i ] .setOwnerDocument( ownerDoc ); > > } > > > > this.onownerDocument.sendEvent( ownerDoc ); > > } > > > > //this is similar to the escape routine in LzText, but that one's shorter > > //since flash it's just for escaping <> > > LzDataNode.prototype.__LZescapechars = {}; > > LzDataNode.prototype.__LZescapechars[ "&" ] = "&" ; > > LzDataNode.prototype.__LZescapechars[ "<" ] = "<" ; > > LzDataNode.prototype.__LZescapechars[ ">" ] = ">" ; > > LzDataNode.prototype.__LZescapechars[ '"' ] = """ ; > > LzDataNode.prototype.__LZescapechars[ "'" ] = "'" ; > > //------------------------------------------------------------------------------ > > // @keywords private > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.__LZXMLescape = function ( t ){ > > if ( typeof( t ) != "string" ) return t; > > > > var olen = t.length; > > var r = ""; > > for ( var i = 0; i < olen; i++ ){ > > //handle newlines > > if ( t.charCodeAt( i ) == 13 ){ > > r += "
"; > > } else { > > var c = t.charAt( i ); > > if ( this.__LZescapechars[ c ] != null ){ > > r += this.__LZescapechars[ c ]; > > } else { > > r += c; > > } > > } > > } > > > > return r; > > } > > > > //------------------------------------------------------------------------------ > > // @keywords private > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.__LZlockFromUpdate = function ( locker ){ > > this.ownerDocument.__LZdoLock( locker ); > > } > > > > //------------------------------------------------------------------------------ > > // @keywords private > > //------------------------------------------------------------------------------ > > LzDataNode.prototype.__LZunlockFromUpdate = function ( locker ){ > > this.ownerDocument.__LZdoUnlock( locker ); > > } > > > > //----------------------------------------------------------------------------- > > // Converts string to XML data. > > // @param String str: A valid string of XML. If the string is simple text, > > or > > // that there isn't a single root element, this function returns null. In > > cases > > // where the string is an invalid but well formatted snippet of XML, this > > // function will close any tags to make for a valid XML document > > // @param boolean trimwhitespace: if true, text nodes have whitespace > > trimmed from start and end. > > // @return LzDataElement: An LzDataElement which is the top of the hierarchy > > // generated from the string > > //----------------------------------------------------------------------------- > > LzDataNode.stringToLzData = function( str, trimwhitespace, stripnsprefix ) { > > var xmlobj = new XML(); > > xmlobj.ignoreWhite = true; > > xmlobj.parseXML( str ); > > if ( xmlobj.childNodes.length != 1 ) return null; > > var lfcnode = LzLoader.prototype.copyFlashXML(xmlobj, trimwhitespace, > > stripnsprefix); > > var fc = lfcnode.removeChild( lfcnode.getFirstChild() ); if ( fc > > instanceof LzDataText ) return null; > > return fc; > > } > > > > LzDataNode.whitespaceChars = {' ': true, '\r': true, '\n': true, '\t': > > true}; > > > > > > //------------------------------------------------------------------------------ > > // @keywords private > > // trim whitespace from start and end of string > > //------------------------------------------------------------------------------ > > LzDataNode.trim = function( str ) { > > var whitech = LzDataNode.whitespaceChars; > > var len = str.length; > > var sindex = 0; > > var eindex = str.length -1; > > var ch; > > while (sindex < len) { > > ch = str.charAt(sindex); > > if (whitech[ch] != true) break; > > sindex++; > > } > > > > while (eindex > sindex) { > > ch = str.charAt(eindex); > > if (whitech[ch] != true) break; > > eindex--; > > } > > return str.slice(sindex,eindex+1); > > } > >
