00001 00116 * ... 00117 * writer->setProps(props); 00118 * @endcode 00119 * 00120 * You could set the playlist's creation time like this: 00121 * 00122 * @code 00123 * XspfDateTime dateTime(2006, 8, 28, 11, 30, 11, 1, 0); 00124 * props.lendDate(&dateTime); 00125 * @endcode 00126 * 00127 * Similar to the steal/get duality introduced earlier you have to choose 00128 * between the "lend" and "give" function family when setting 00129 * information. The whole thing again is only about memory ownership: 00130 * The lend functions do not transfer ownership, the give functions do. 00131 * The give family also offers to copy the memory or to assign 00132 * existing memory. To make this more clear calling 00133 * 00134 * @code 00135 * props.giveTitle(_PT("Some title"), XspfData::TRANSFER); 00136 * @endcode 00137 * 00138 * would be a bad idea since the memory would not be copied but still 00139 * be deleted on destruction. You should use 00140 * 00141 * @code 00142 * props.lendTitle(_PT("Some title")); 00143 * @endcode 00144 * 00145 * in this case. 00146 * 00147 * Back to the writer: When you have created a XspfWriter instance 00148 * you can let it write its content to file: 00149 * 00150 * @code 00151 * writer.writeFile(_PT("TEST.xspf")); 00152 * @endcode 00153 * 00154 * In this case that would make a valid playlist without any tracks. 00155 * So before writing the playlist you should add your tracks: 00156 * 00157 * @code 00158 * XspfTrack track; 00159 * ... 00160 * track.lendCreator(_PT("Breaking Benjamin")); 00161 * ... 00162 * writer.addTrack(track); 00163 * @endcode 00164 * 00165 * When addTrack() is called the track information is appended to an 00166 * internal buffer which is written when writeFile() is called eventually. 00167 * You can add the same track several times and you can call writeFile() 00168 * several times to write the same playlist to several files; 00169 * what you cannot do is add more tracks after writing the playlist 00170 * to a file: You will have to call reset() to start over with an empty track list first. 00171 * 00172 * 00173 * @section SEC_MALICIOUS Handling malicious XML 00174 * Let us assume you are using libxspf to power some kind of web service with XSPF 00175 * reading cabilities. Let us further assume this service can accept XSPF input 00176 * from a user. Due to the nature of XML your service would be vulnerable to 00177 * an <i>XML entity explosion attack</i>. What this means is that a rather small 00178 * malicious XML file can make the running XML processor a huge amount of memory 00179 * or CPU time or both. 00180 * 00181 * A popular example is <i>billion laughs</i>, of which an XSPF version 00182 * could look like this: 00183 * 00184 * @code 00185 * <?xml version="1.0"?> 00186 * <!DOCTYPE billion [ 00187 * <!ELEMENT billion (#PCDATA)> 00188 * <!ENTITY laugh0 "ha"> 00189 * <!ENTITY laugh1 "&laugh0;&laugh0;"> 00190 * <!ENTITY laugh2 "&laugh1;&laugh1;"> 00191 * <!ENTITY laugh3 "&laugh2;&laugh2;"> 00192 * <!ENTITY laugh4 "&laugh3;&laugh3;"> 00193 * ... 00194 * <!ENTITY laugh30 "&laugh29;&laugh29;"> 00195 * ]> 00196 * <playlist version="1" xmlns="http://xspf.org/ns/0/"> 00197 * <title>&laugh30;</title> 00198 * <trackList /> 00199 * </playlist> 00200 * @endcode 00201 * 00202 * With malicious XML detection enabled, libxspf sets certain limits 00203 * to the values of entities. Currently these limits are: 00204 * - Length of entity values 00205 * - Sum of lookups per entity value 00206 * - Lookup depth per entity value 00207 * 00208 * The above <i>billion laughs</i> example has these metrics: 00209 * <table border="0"> 00210 * <tr><td class="indexkey">Entity</td><td class="indexkey">Length</td><td class="indexkey">Lookup Sum</td><td class="indexkey">Lookup Depth</td></tr> 00211 * <tr><td class="indexvalue">laugh0</td><td class="indexvalue">2</td><td class="indexvalue">0</td><td class="indexvalue">0</td></tr> 00212 * <tr><td class="indexvalue">laugh1</td><td class="indexvalue">4</td><td class="indexvalue">2</td><td class="indexvalue">1</td></tr> 00213 * <tr><td class="indexvalue">laugh2</td><td class="indexvalue">8</td><td class="indexvalue">6</td><td class="indexvalue">2</td></tr> 00214 * <tr><td class="indexvalue">laugh3</td><td class="indexvalue">16</td><td class="indexvalue">14</td><td class="indexvalue">3</td></tr> 00215 * <tr><td class="indexvalue">laugh4</td><td class="indexvalue">32</td><td class="indexvalue">30</td><td class="indexvalue">4</td></tr> 00216 * <tr><td class="indexvalue">...</td><td class="indexvalue">...</td><td class="indexvalue">...</td><td class="indexvalue">...</td></tr> 00217 * <tr><td class="indexvalue">laugh30</td><td class="indexvalue">2,147,483,648</td><td class="indexvalue">2,147,483,646</td><td class="indexvalue">30</td></tr> 00218 * <tr><td class="indexvalue">laugh<i>n</i></td><td class="indexvalue">2^(<i>n</i>+1)</td><td class="indexvalue">2^(<i>n</i>+1)-2</td><td class="indexvalue"><i>n</i></td></tr> 00219 * </table> 00220 * 00221 * Looking at <i>laugh30</i> all three values are much higher than those of most peaceful XML files. 00222 * Through calling 00223 * 00224 * @code 00225 * reader.enableMaliciousXmlDetection(true); 00226 * @endcode 00227 * 00228 * you can make a XspfReader instance protocol these metrics in order to detect 00229 * malicious XML. Also, all of these metrics can be limited and adjusted individually; 00230 * for instance this is how to limit the lookup depth to a maximum of 2: 00231 * 00232 * @code 00233 * reader.limitLookupDepthPerEntityValue(true); 00234 * reader.setMaxLookupDepthPerEntityValue(2); 00235 * @endcode 00236 * 00237 * @attention 00238 * Malicious XML detection can only work for you if you are clear 00239 * about your software's use cases. Tune the detection parameters to 00240 * what you have to allow and reject everything else. 00241 */