libxspf
1.2.0
|
00001 /* 00002 * libxspf - XSPF playlist handling library 00003 * 00004 * Copyright (C) 2006-2008, Sebastian Pipping / Xiph.Org Foundation 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above 00012 * copyright notice, this list of conditions and the following 00013 * disclaimer. 00014 * 00015 * * Redistributions in binary form must reproduce the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer in the documentation and/or other materials 00018 * provided with the distribution. 00019 * 00020 * * Neither the name of the Xiph.Org Foundation nor the names of 00021 * its contributors may be used to endorse or promote products 00022 * derived from this software without specific prior written 00023 * permission. 00024 * 00025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00026 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00027 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00028 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00029 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00030 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00031 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00032 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00033 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00034 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00035 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 00036 * OF THE POSSIBILITY OF SUCH DAMAGE. 00037 * 00038 * Sebastian Pipping, sping@xiph.org 00039 */ 00040 00046 #ifndef XSPF_READER_H 00047 #define XSPF_READER_H 00048 00049 00050 #include "XspfDefines.h" 00051 #include <string> 00052 00053 00054 namespace Xspf { 00055 00056 00058 00059 // Messages with ONE "%s" in it 00060 #define XSPF_READER_TEXT_ONE_ATTRIBUTE_FORBIDDEN _PT("Attribute '%s' not allowed.") 00061 #define XSPF_READER_TEXT_ONE_EXPAT_ERROR _PT("Expat error '%s'") 00062 #define XSPF_READER_TEXT_ONE_ELEMENT_FORBIDDEN _PT("Element '%s' not allowed.") 00063 #define XSPF_READER_TEXT_ONE_ELEMENT_FORBIDDEN_VERSION_ZERO _PT("Element '%s' not allowed in XSPF-0.") 00064 #define XSPF_READER_TEXT_ONE_FILE_READING_ERROR _PT("File '%s' could not be read.") 00065 #define XSPF_READER_TEXT_ONE_WRONG_ROOT_NAME _PT("Root element must be '") XSPF_NS_HOME XSPF_NS_SEP_STRING _PT("playlist', not '%s'.") 00066 #define XSPF_READER_TEXT_ONE_WRONG_VERSION _PT("Version must be '0' or '1', not '%s'.") 00067 00068 // Messages with ZERO "%s" in it 00069 #define XSPF_READER_TEXT_ZERO_ATTRIBUTE_MISSING(name) _PT("Attribute '") name _PT("' missing.") 00070 #define XSPF_READER_TEXT_ZERO_ELEMENT_MISSING(ns, name) _PT("Element '") ns XSPF_NS_SEP_STRING name _PT("' missing.") 00071 #define XSPF_READER_TEXT_ZERO_ELEMENT_MISSING_VERSION_ZERO(ns, name) _PT("Element '") ns XSPF_NS_SEP_STRING name _PT("' missing. This is not allowed in XSPF-0.") 00072 #define XSPF_READER_TEXT_ZERO_FILENAME_NULL _PT("Filename must not be NULL.") 00073 #define XSPF_READER_TEXT_ZERO_TOO_MANY_ELEMENTS(ns, name) _PT("Only one '") ns XSPF_NS_SEP_STRING name _PT("' allowed.") 00074 #define XSPF_READER_TEXT_ZERO_WRONG_ATTRIBUTE_TYPE(attr, type) _PT("Attribute '") attr _PT("' is not a valid ") type _PT(".") 00075 #define XSPF_READER_TEXT_ZERO_WRONG_CONTENT_TYPE(ns, elem, type) _PT("Content of '") ns XSPF_NS_SEP_STRING elem _PT("' is not a valid ") type _PT(".") 00076 #define XSPF_READER_TEXT_ZERO_TEXT_FORBIDDEN(ns, elem) _PT("Content of '") ns XSPF_NS_SEP_STRING elem _PT("' must be whitespace or child elements, not text.") 00077 #define XSPF_READER_TEXT_ZERO_KEY_WITHOUT_VERSION(name) _PT("Attribute '") name _PT("' does not carry version information.") 00078 #define XSPF_READER_TEXT_ZERO_KEY_WITH_REL_URI(name) _PT("Attribute '") name _PT("' does not contain an absolute URI.") 00079 00081 00082 00086 enum XspfReaderReturnCode { 00087 XSPF_READER_SUCCESS, 00088 00089 XSPF_READER_ERROR_NO_INPUT, 00090 XSPF_READER_ERROR_ELEMENT_TOOMANY, 00091 XSPF_READER_ERROR_ELEMENT_FORBIDDEN, 00092 XSPF_READER_ERROR_ELEMENT_MISSING, 00093 XSPF_READER_ERROR_ATTRIBUTE_INVALID, 00094 XSPF_READER_ERROR_ATTRIBUTE_MISSING, 00095 XSPF_READER_ERROR_ATTRIBUTE_FORBIDDEN, 00096 XSPF_READER_ERROR_CONTENT_INVALID, 00097 XSPF_READER_ERROR_BASE_URI_USELESS, 00098 00099 XSPF_READER_WARNING_KEY_WITHOUT_VERSION, 00100 XSPF_READER_WARNING_KEY_WITH_REL_URI, 00101 00102 XSPF_READER_ERROR_MALICIOUS_SPACE, 00103 XSPF_READER_ERROR_MALICIOUS_LOOKUP_SUM, 00104 XSPF_READER_ERROR_MALICIOUS_LOOKUP_DEPTH, //< An entity's lookup depth is too high 00105 00106 // Insert new codes HERE! 00107 00108 // This one must come last! 00109 XSPF_READER_ERROR_EXPAT = 0x1000 00110 }; 00111 00112 00113 /* 00114 playlist 1 00115 title ? 00116 creator ? 00117 annotation ? 00118 info ? 00119 location ? 00120 identifier ? 00121 image ? 00122 date ? 00123 license ? 00124 attribution ? 00125 location * 00126 identifier * 00127 link * 00128 meta * 00129 extension * 00130 ... * 00131 trackList 1 00132 track +|* 00133 location * 00134 identifier * 00135 title ? 00136 creator ? 00137 annotation ? 00138 info ? 00139 image ? 00140 album ? 00141 trackNum (uint > 0) ? 00142 duration (uint) ? 00143 link * 00144 meta * 00145 extension * 00146 */ 00147 00151 enum XspfTag { 00152 // Stack returns 0 if empty 00153 TAG_UNKNOWN, 00154 00155 TAG_PLAYLIST, 00156 TAG_PLAYLIST_TITLE, 00157 TAG_PLAYLIST_CREATOR, 00158 TAG_PLAYLIST_ANNOTATION, 00159 TAG_PLAYLIST_INFO, 00160 TAG_PLAYLIST_LOCATION, 00161 TAG_PLAYLIST_IDENTIFIER, 00162 TAG_PLAYLIST_IMAGE, 00163 TAG_PLAYLIST_DATE, 00164 TAG_PLAYLIST_LICENSE, 00165 TAG_PLAYLIST_ATTRIBUTION, 00166 TAG_PLAYLIST_ATTRIBUTION_LOCATION, 00167 TAG_PLAYLIST_ATTRIBUTION_IDENTIFIER, 00168 TAG_PLAYLIST_LINK, 00169 TAG_PLAYLIST_META, 00170 TAG_PLAYLIST_EXTENSION, 00171 TAG_PLAYLIST_TRACKLIST, 00172 TAG_PLAYLIST_TRACKLIST_TRACK, 00173 TAG_PLAYLIST_TRACKLIST_TRACK_LOCATION, 00174 TAG_PLAYLIST_TRACKLIST_TRACK_IDENTIFIER, 00175 TAG_PLAYLIST_TRACKLIST_TRACK_TITLE, 00176 TAG_PLAYLIST_TRACKLIST_TRACK_CREATOR, 00177 TAG_PLAYLIST_TRACKLIST_TRACK_ANNOTATION, 00178 TAG_PLAYLIST_TRACKLIST_TRACK_INFO, 00179 TAG_PLAYLIST_TRACKLIST_TRACK_IMAGE, 00180 TAG_PLAYLIST_TRACKLIST_TRACK_ALBUM, 00181 TAG_PLAYLIST_TRACKLIST_TRACK_TRACKNUM, 00182 TAG_PLAYLIST_TRACKLIST_TRACK_DURATION, 00183 TAG_PLAYLIST_TRACKLIST_TRACK_LINK, 00184 TAG_PLAYLIST_TRACKLIST_TRACK_META, 00185 TAG_PLAYLIST_TRACKLIST_TRACK_EXTENSION, 00186 00187 // Insert XSPF-2 codes HERE! 00188 00189 // This one must come last! 00190 TAG_USER = 0x1000 00191 }; 00192 00193 00194 class XspfProps; 00195 class XspfDateTime; 00196 class XspfTrack; 00197 class XspfReaderCallback; 00198 template <class T> class XspfStack; 00199 class XspfChunkCallback; 00200 00201 class XspfExtensionReaderFactory; 00202 class XspfExtensionReader; 00203 class XspfReaderPrivate; 00204 00205 00209 class XspfReader { 00210 00211 private: 00213 XspfReaderPrivate * const d; 00214 00215 00216 public: 00222 XspfReader(XspfExtensionReaderFactory * handlerFactory = NULL); 00223 00229 XspfReader(XspfReader const & source); 00230 00236 XspfReader & operator=(XspfReader const & source); 00237 00241 ~XspfReader(); 00242 00254 int parseFile(XML_Char const * filename, XspfReaderCallback * callback, 00255 XML_Char const * baseUri); 00256 00269 int parseMemory(char const * memory, int numBytes, XspfReaderCallback * callback, 00270 XML_Char const * baseUri); 00271 00283 int parseChunks(XspfChunkCallback * inputCallback, 00284 XspfReaderCallback * dataCallback, XML_Char const * baseUri); 00285 00294 void limitLengthPerEntityValue(bool enabled); 00295 00304 void limitLookupSumPerEntityValue(bool enabled); 00305 00314 void limitLookupDepthPerEntityValue(bool enabled); 00315 00327 void enableMaliciousXmlDetection(bool enabled); 00328 00337 void setMaxLengthPerEntityValue(int maxLength); 00338 00347 void setMaxLookupSumPerEntityValue(int maxLookupSum); 00348 00357 void setMaxLookupDepthPerEntityValue(int maxLookupDepth); 00358 00359 private: 00363 void makeReusable(); 00364 00372 bool handleError(int code, XML_Char const * text); 00373 00382 bool handleError(int code, XML_Char const * format, XML_Char const * param); 00383 00390 void handleFatalError(int code, XML_Char const * text); 00391 00399 void handleFatalError(int code, XML_Char const * format, XML_Char const * param); 00400 00408 bool handleWarning(int code, XML_Char const * text); 00409 00414 void setExpatError(); 00415 00419 void stop(); 00420 00427 void handleStart(XML_Char const * fullName, XML_Char const ** atts); 00428 00436 bool handleStartOne(XML_Char const * fullName, XML_Char const ** atts); 00437 00445 bool handleStartTwo(XML_Char const * fullName, XML_Char const ** atts); 00446 00454 bool handleStartThree(XML_Char const * fullName, XML_Char const ** atts); 00455 00463 bool handleStartFour(XML_Char const * fullName, XML_Char const ** atts); 00464 00471 void handleCharacters(XML_Char const * s, int len); 00472 00479 void handleEntityDeclaration(XML_Char const * entityName, 00480 XML_Char const * value); 00481 00487 void handleEnd(XML_Char const * fullName); 00488 00495 bool handleEndOne(XML_Char const * fullName); 00496 00503 bool handleEndTwo(XML_Char const * fullName); 00504 00511 bool handleEndThree(XML_Char const * fullName); 00512 00519 bool handleEndFour(XML_Char const * fullName); 00520 00528 bool handlePlaylistAttribs(XML_Char const ** atts); 00529 00538 bool handleMetaLinkAttribs(XML_Char const ** atts, XML_Char const * & rel); 00539 00548 bool handleExtensionAttribs(XML_Char const ** atts, 00549 XML_Char const * & application); 00550 00557 bool handleNoAttribsExceptXmlBase(XML_Char const ** atts); 00558 00562 void clearError(); 00563 00571 static void masterStart(void * userData, XML_Char const * fullName, XML_Char const ** atts); 00572 00579 static void masterEnd(void * userData, XML_Char const * fullName); 00580 00588 static void masterCharacters(void * userData, XML_Char const * s, int len); 00589 00603 static void masterEntityDeclaration(void * userData, XML_Char const * entityName, 00604 int is_parameter_entity, XML_Char const * value, int value_length, 00605 XML_Char const * base, XML_Char const * systemId, XML_Char const * publicId, 00606 XML_Char const * notationName); 00607 00615 bool onBeforeParse(XspfReaderCallback * callback, 00616 XML_Char const * baseUri); 00617 00621 void onAfterParse(); 00622 00623 public: 00630 static bool isXmlBase(XML_Char const * attributeKey); 00631 00632 private: 00639 bool handleXmlBaseAttribute(XML_Char const * xmlBase); 00640 00648 XML_Char * makeAbsoluteUri(XML_Char const * sourceUri) const; 00649 00655 XspfStack<unsigned int> & getElementStack() const; 00656 00662 XspfStack<std::basic_string<XML_Char> > & getBaseUriStack() const; 00663 00670 void skipFromHere(); 00671 00682 bool checkAndSkipNamespace(XML_Char const * fullName, 00683 XML_Char const * & localName); 00684 00689 void notifySuccess() const; 00690 00691 friend class XspfExtensionReader; 00692 00693 }; 00694 00695 00696 } // namespace Xspf 00697 00698 #endif // XSPF_READER_H