[xiph-commits] r15982 - websites/validator.xspf.org

sping at svn.xiph.org sping at svn.xiph.org
Tue May 5 15:41:30 PDT 2009


Author: sping
Date: 2009-05-05 15:41:30 -0700 (Tue, 05 May 2009)
New Revision: 15982

Added:
   websites/validator.xspf.org/REPOSITORY_HAS_MOVED.txt
Removed:
   websites/validator.xspf.org/COPYING
   websites/validator.xspf.org/check.py
   websites/validator.xspf.org/hello_uri.py
   websites/validator.xspf.org/xspflogo-1.5.gif
Log:
Move validator from svn to git

Deleted: websites/validator.xspf.org/COPYING
===================================================================
--- websites/validator.xspf.org/COPYING	2009-05-05 12:40:48 UTC (rev 15981)
+++ websites/validator.xspf.org/COPYING	2009-05-05 22:41:30 UTC (rev 15982)
@@ -1,165 +0,0 @@
-		   GNU LESSER GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
-  This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
-  0. Additional Definitions. 
-
-  As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
-  "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
-  An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
-  A "Combined Work" is a work produced by combining or linking an
-Application with the Library.  The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
-  The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
-  The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
-  1. Exception to Section 3 of the GNU GPL.
-
-  You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
-  2. Conveying Modified Versions.
-
-  If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
-   a) under this License, provided that you make a good faith effort to
-   ensure that, in the event an Application does not supply the
-   function or data, the facility still operates, and performs
-   whatever part of its purpose remains meaningful, or
-
-   b) under the GNU GPL, with none of the additional permissions of
-   this License applicable to that copy.
-
-  3. Object Code Incorporating Material from Library Header Files.
-
-  The object code form of an Application may incorporate material from
-a header file that is part of the Library.  You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
-   a) Give prominent notice with each copy of the object code that the
-   Library is used in it and that the Library and its use are
-   covered by this License.
-
-   b) Accompany the object code with a copy of the GNU GPL and this license
-   document.
-
-  4. Combined Works.
-
-  You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
-   a) Give prominent notice with each copy of the Combined Work that
-   the Library is used in it and that the Library and its use are
-   covered by this License.
-
-   b) Accompany the Combined Work with a copy of the GNU GPL and this license
-   document.
-
-   c) For a Combined Work that displays copyright notices during
-   execution, include the copyright notice for the Library among
-   these notices, as well as a reference directing the user to the
-   copies of the GNU GPL and this license document.
-
-   d) Do one of the following:
-
-       0) Convey the Minimal Corresponding Source under the terms of this
-       License, and the Corresponding Application Code in a form
-       suitable for, and under terms that permit, the user to
-       recombine or relink the Application with a modified version of
-       the Linked Version to produce a modified Combined Work, in the
-       manner specified by section 6 of the GNU GPL for conveying
-       Corresponding Source.
-
-       1) Use a suitable shared library mechanism for linking with the
-       Library.  A suitable mechanism is one that (a) uses at run time
-       a copy of the Library already present on the user's computer
-       system, and (b) will operate properly with a modified version
-       of the Library that is interface-compatible with the Linked
-       Version. 
-
-   e) Provide Installation Information, but only if you would otherwise
-   be required to provide such information under section 6 of the
-   GNU GPL, and only to the extent that such information is
-   necessary to install and execute a modified version of the
-   Combined Work produced by recombining or relinking the
-   Application with a modified version of the Linked Version. (If
-   you use option 4d0, the Installation Information must accompany
-   the Minimal Corresponding Source and Corresponding Application
-   Code. If you use option 4d1, you must provide the Installation
-   Information in the manner specified by section 6 of the GNU GPL
-   for conveying Corresponding Source.)
-
-  5. Combined Libraries.
-
-  You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
-   a) Accompany the combined library with a copy of the same work based
-   on the Library, uncombined with any other library facilities,
-   conveyed under the terms of this License.
-
-   b) Give prominent notice with the combined library that part of it
-   is a work based on the Library, and explaining where to find the
-   accompanying uncombined form of the same work.
-
-  6. Revised Versions of the GNU Lesser General Public License.
-
-  The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
-  Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
-  If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.

Added: websites/validator.xspf.org/REPOSITORY_HAS_MOVED.txt
===================================================================
--- websites/validator.xspf.org/REPOSITORY_HAS_MOVED.txt	                        (rev 0)
+++ websites/validator.xspf.org/REPOSITORY_HAS_MOVED.txt	2009-05-05 22:41:30 UTC (rev 15982)
@@ -0,0 +1,7 @@
+- The Online XSPF Validator has moved to *Git*.  The repository is over here:
+  http://git.xiph.org/?p=validator-xspf-org.git;a=summary
+
+- Git works well with *Windows*, please check out msysgit:
+  http://code.google.com/p/msysgit/
+
+Thanks for your attention.


Property changes on: websites/validator.xspf.org/REPOSITORY_HAS_MOVED.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Deleted: websites/validator.xspf.org/check.py
===================================================================
--- websites/validator.xspf.org/check.py	2009-05-05 12:40:48 UTC (rev 15981)
+++ websites/validator.xspf.org/check.py	2009-05-05 22:41:30 UTC (rev 15982)
@@ -1,1404 +0,0 @@
-#! /usr/bin/python
-# coding: utf-8
-# -----------------------------------------------------------------------
-# Online XSPF Validator
-# Copyright (C) 2007-2008, Sebastian Pipping / Xiph.Org Foundation
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Sebastian Pipping, sping at xiph.org
-#
-# -----------------------------------------------------------------------
-# REQUIREMENTS
-# -----------------------------------------------------------------------
-# * Python 2.4 or later (for current line attribute of Expat parser)
-# * Ft.Lib.Uri of 4Suite (http://4suite.org/)
-#   (package python-4suite-xml in Debian testing/unstable)
-#
-# -----------------------------------------------------------------------
-# HISTORY
-# -----------------------------------------------------------------------
-# 2008-09-19 -- Elias Pipping <elias at pipping.org>,
-#               Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: Malicious XML detection added
-#       (might turn out to strict or too loose but it's a start)
-#
-# 2008-09-06 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: Now closing files properly
-#   * Added: Bring back "https" scheme support unintentionally
-#       removed two days ago
-#
-# 2008-09-04 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: [SECURITY] Accessing local files was possible
-#       through using file URIs like file:///etc/passwd
-#   * Fixed: [SECURITY] XSS vulnerability existed with URIs like
-#       [..]check.py?uri=[..javascript..]
-#   * Fixed: [SECURITY] XSS vulnerability existed for
-#       certain XSPF input, e.g. in attribute //playlist.version.
-#       This did not require an existing file as the input could
-#       directly passed through URIs like
-#       [..]check.py?pasted=[..javascript..]&submitPasted=Submit
-#   * Fixed: Required attributes 'rel' (<link>/<meta>)
-#        and 'application' (<extention>) were not reported missing
-#        Related test case files from <for_version_1/fail> are:
-#        - playlist-extension-application-missing.xspf
-#        - playlist-link-rel-missing.xspf
-#        - playlist-meta-rel-missing.xspf
-#        - track-extension-application-missing.xspf
-#        - track-link-rel-missing.xspf
-#        - track-meta-rel-missing.xspf
-#
-# 2008-08-25 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: 'xml:base' attribute now allowed anywhere, was
-#       root node only before
-#   * Fixed: Error "Attribute '<value>' not allowed" was shown
-#       instead of "Attribute '<key>' not allowed".
-#
-# 2008-07-31 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: Support for 'xml:base' attribute added
-#   * Fixed: Support for XML namespaces added
-#   * Fixed: Additional invalid root attributes now rejected
-#
-# 2007-10-04 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Changed: Link bar updated
-#
-# 2007-10-03 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Added: Button embedding how-to
-#
-# 2007-09-24 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: Another bug in whitespace handling
-#   * Added: Finally made testable from the command line
-#
-# 2007-09-21 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Added: RFC 3986 URI validation
-#   * Fixed: Whitespace handling fixes copied over from libSpiff
-#   * Changed: Code re-licensed under LGPLv3 (LGPL-Any before) to be
-#       able to use 4Suite's Apache-licensed URI validation code
-#       (http://www.gnu.org/licenses/lgpl-3.0.html)
-#
-# 2007-08-09 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: Ivo's changes repaired to have same look again
-#       I use tables when pixel-exact layout is need since
-#       CSS support in browsers is not good enough yet
-#
-# 2007-07-30 -- Ivo Emanuel Gonçalves <justivo gmail.com>
-#
-#   * Some HTML and CSS fixes
-#
-# 2007-07-25 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Changes: License changed from GPL to LGPL
-#       (http://www.gnu.org/licenses/lgpl-2.1.html)
-#
-# 2007-02-18 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Added: License header for source code release
-#
-# 2007-01-20 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Changed: URI checking removed until proper parser available
-#
-# 2007-01-09 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Fixed: No highlighting on XML error bug fixed
-#
-# 2006-10-09 -- Sebastian Pipping <webmaster at hartwork.org>
-#
-#   * Changed: "Valid" now on the top
-#
-# 2006-10-04 -- Sebastian Pipping <webmaster at hartwork.org>
-# ------------------------------------------------------------------------------
-
-import cgi
-############## import cgitb; cgitb.enable()
-import urllib2
-import sys
-import xml.parsers.expat
-import re
-
-try:
-    from Ft.Lib import Uri
-except ImportError:
-    print "ERROR: Package 'Ft.Lib' is missing. On Debian testing/unstable run:\n" \
-            "sudo apt-get install python-4suite-xml"
-    sys.exit(2)
-
-print "Content-Type: text/html"     # HTML is following
-print                               # blank line, end of headers
-
-
-# Get the basename of this script
-# co = sys._getframe().f_code
-# SELFBASE = co.co_filename
-
-
-def isSafeDownloadTarget(candidate):
-    schemeOrNone = Uri.GetScheme(candidate)
-    if schemeOrNone == None:
-        return False
-    scheme = schemeOrNone.lower()
-    allowedSchemes = set(["http", "https"])
-    return scheme in allowedSchemes
-
-
-print """
-<html lang="en" dir="ltr">
-	<head>
-		<title>XSPF Validator &mdash; Validate your playlists</title>
-		<style type="text/css">
-			body {
-				background-color:rgb(230,230,230);
-				margin:0;
-			}
-
-			body, td, h1, h2, h3, h4 {
-				font-family:Verdana, sans-serif;
-			}
-
-			a {
-				color:rgb(130,130,130);
-				text-decoration:none;
-			}
-			
-			td.vert {
-				background-color:rgb(180,180,180);
-				font-size:1pt;
-				width:2px;
-				padding:0px;
-			}
-			td.number {
-				text-align:right;
-				vertical-align:top;
-				padding-top:3px;
-				padding-bottom:3px;
-				padding-right:8px;
-			}
-			a.number {
-				color:#000000;
-				text-decoration:underline;
-			}
-			td.error {
-				padding-left:8px;
-			}
-			td.horz {
-				background-color:rgb(180,180,180);
-				font-size:1px;
-				height:2px;
-				padding:0;
-				line-height:1px;
-			}
-			span.invalid {
-				text-transform:uppercase;
-				padding-left:2px;
-				color:red;
-				font-weight:bold;
-			}
-			span.valid {
-				text-transform:uppercase;
-				padding-left:2px;
-				color:green;
-				font-weight:bold;
-			}
-
-			td.lineNumber {
-				background-color:rgb(222,222,222);
-				font-family:"Courier New", monospace;
-				text-align:right;
-				vertical-align:top;
-				padding-top:3px;
-				padding-bottom:3px;
-				padding-left:8px;
-				padding-right:4px;
-			}
-			td.lineVert {
-					background-color:rgb(0,0,0);
-					font-size:1pt;
-					width:1px;
-					padding:0;
-			}
-			td.lineOdd {
-				font-family:"Courier New", monospace;
-				background-color:rgb(236,236,236);
-				padding-top:3px;
-				padding-bottom:3px;
-				padding-left:4px;
-				padding-right:8px;
-			}
-			td.lineEven {
-				font-family:"Courier New", monospace;
-				background-color:rgb(250,250,250);
-				padding-top:3px;
-				padding-bottom:3px;
-				padding-left:4px;
-				padding-right:8px;
-			}
-			td.lineBad {
-				font-family:"Courier New", monospace;
-				background-color:rgb(255,188,188);
-				padding-top:3px;
-				padding-bottom:3px;
-				padding-left:4px;
-				padding-right:8px;
-			}
-			
-			a.blackLink {
-				color:#000000;
-				text-decoration:none;
-			}
-			a.anchor {
-				color:#000000;
-				text-decoration:none;
-			}
-		</style>
-	</head>
-	<body>
-		<!-- CENTERING -->
-		<table height="100%" style="width:100%">
-			<tr>
-				<td align="center" valign="middle" style="padding:10px">
-					<!-- BORDER -->"""
-
-
-valid = False
-intro = ""
-input = ""
-
-shellMode = False
-if (len(sys.argv) == 3) and (sys.argv[1] == "--shell"):
-    shellMode = True
-    try:
-        f = open(sys.argv[2])
-        try:
-            input = f.read()
-        finally:
-            f.close()
-
-    except IOError:
-        pass
-
-    if input != "":
-        intro = "Validating local file<br><b><i>" + sys.argv[2] + "</i></b><br><br>"
-
-else:
-    form = cgi.FieldStorage()
-    if form.has_key("pasted") and form.has_key("submitPasted"):
-        input = form.getlist("pasted")[0]
-        if input != "":
-            intro = "Validating pasted text<br><br>"
-
-    elif form.has_key("uploaded") and form.has_key("submitUploaded"):
-        uploaded = form["uploaded"]
-        if uploaded.file:
-            try:
-                input = uploaded.file.read()
-            except IOError:
-                pass
-            finally:
-                uploaded.file.close()
-
-        if input != "":
-            intro = "Validating uploaded file<br><b><i>" + cgi.escape(uploaded.filename) + "</i></b><br><br>"
-
-    elif form.has_key("url"): ### and form.has_key("submitUrl")
-        url = form.getlist("url")[0]
-
-        if not isSafeDownloadTarget(url):
-            intro = """<b style="color:red;">Download location not considered safe.<br>Please do <em>not</em> attack this site. Thanks.</b><br><br>"""
-        else:
-            try:
-                file = urllib2.urlopen(url)
-                try:
-                    input = file.read()
-                finally:
-                    file.close()
-                
-            except ValueError:
-                intro = """<b style="color:red;">Invalid URL.</b><br><br>"""
-
-            except Exception: ### urllib2.URLError:
-                # One of 404, non-existent host, IPv6 (not supported), ...
-                intro = """<b style="color:red">Could not download from URL.</b><br><br>"""
-
-            if input != "":
-                intro = "Validating data from URL<br><b><i><a href=\"" + cgi.escape(url, True) \
-                        + "\" class=\"blackLink\">" + cgi.escape(url) + "</a></i></b><br><br>"
-
-
-lineHeads = [0]
-if input != "":
-    index = -1
-    while 1:
-        index = input.find("\x0A", index + 1)
-        if index == -1:
-            break
-        lineHeads.append(index + 1)
-
-
-
-if input == "":
-    # Formular 600
-    print """
-					<table cellpadding="0" cellspacing="0" width="600" style="border:1px solid rgb(180,180,180); background-color:#FFF;">"""
-else:
-    # Results 800
-    print """
-					<table cellpadding="0" cellspacing="0" width="750" style="border:1px solid rgb(180,180,180); background-color:#FFF;">"""
-
-print """
-						<tr>"""
-
-
-if input == "":
-    # Formular centered
-    print """
-							<td align="center" style="padding-top:60px; padding-bottom:60px">
-								<form action="" accept-charset="UTF-8" enctype="multipart/form-data" method="post">
-								<!-- CONTENT -->
-								<table>"""
-
-else:
-    # Results full width
-    print """
-							<td style="padding-top:60px; padding-bottom:50px;">
-								<!-- CONTENT -->
-								<table style="width:100%;">"""
-
-
-print """
-									<tr>
-										<td style="padding-bottom: 20px;" align="center"><img src="xspflogo-1.5.gif" style="width:297px; height:83px; border:0;" alt=""></td>
-									</tr>"""
-
-
-if input == "":
-    if intro != "":
-        print """
-									<tr>
-										<td style="width:100%;" align="center">"""
-        print intro
-        print """
-									</tr>"""
-
-    # Formular
-    print """
-									<tr>
-										<td style="padding-bottom:16px;">
-											Validate a Spiff playlist from ...
-										</td>
-									</tr>
-									<tr>
-										<td>
-											URL<br>
-											<input name="url" size="60" style="width: 350px;" type="text">
-										</td>
-									</tr>
-									<tr>
-										<td style="padding-bottom:20px">
-											<input name="submitUrl" value="Submit" type="submit">
-										</td>
-									</tr>
-									<tr>
-										<td>
-											Uploaded file<br>
-											<input name="uploaded" maxlength="100000" accept="text/*" size="41" type="file">
-										</td>
-									</tr>
-									<tr>
-										<td style="padding-bottom:20px;">
-											<input name="submitUploaded" value="Submit" type="submit">
-										</td>
-									</tr>
-									<tr>
-										<td>
-											Pasted text<br>
-											<textarea cols="60" rows="5" name="pasted" style="width: 350px;"></textarea>
-										</td>
-									</tr>
-									<tr>
-										<td>
-											<input name="submitPasted" value="Submit" type="submit">
-										</td>
-									</tr>"""
-
-else:
-    print """
-									<tr>
-										<td style="padding-left:60px; padding-right:60px">"""
-    print intro
-
-    stack = []
-    valid = True
-    version = -1
-    accum = ""
-
-    TAG_UNKNOWN = 0
-    TAG_PLAYLIST = 1
-    TAG_PLAYLIST_TITLE = 2
-    TAG_PLAYLIST_CREATOR = 3
-    TAG_PLAYLIST_ANNOTATION = 4
-    TAG_PLAYLIST_INFO = 5
-    TAG_PLAYLIST_LOCATION = 6
-    TAG_PLAYLIST_IDENTIFIER = 7
-    TAG_PLAYLIST_IMAGE = 8
-    TAG_PLAYLIST_DATE = 9
-    TAG_PLAYLIST_LICENSE = 10
-    TAG_PLAYLIST_ATTRIBUTION = 11
-    TAG_PLAYLIST_ATTRIBUTION_LOCATION = 12
-    TAG_PLAYLIST_ATTRIBUTION_IDENTIFIER = 13
-    TAG_PLAYLIST_LINK = 14
-    TAG_PLAYLIST_META = 15
-    TAG_PLAYLIST_EXTENSION = 16
-    TAG_PLAYLIST_TRACKLIST = 17
-    TAG_PLAYLIST_TRACKLIST_TRACK = 18
-    TAG_PLAYLIST_TRACKLIST_TRACK_LOCATION = 19
-    TAG_PLAYLIST_TRACKLIST_TRACK_IDENTIFIER = 20
-    TAG_PLAYLIST_TRACKLIST_TRACK_TITLE = 21
-    TAG_PLAYLIST_TRACKLIST_TRACK_CREATOR = 22
-    TAG_PLAYLIST_TRACKLIST_TRACK_ANNOTATION = 23
-    TAG_PLAYLIST_TRACKLIST_TRACK_INFO = 24
-    TAG_PLAYLIST_TRACKLIST_TRACK_IMAGE = 25
-    TAG_PLAYLIST_TRACKLIST_TRACK_ALBUM = 26
-    TAG_PLAYLIST_TRACKLIST_TRACK_TRACKNUM = 27
-    TAG_PLAYLIST_TRACKLIST_TRACK_DURATION = 28
-    TAG_PLAYLIST_TRACKLIST_TRACK_LINK = 29
-    TAG_PLAYLIST_TRACKLIST_TRACK_META = 30
-    TAG_PLAYLIST_TRACKLIST_TRACK_EXTENSION = 31
-
-    skipAbove = -1
-
-    firstPlaylistAnnotation = True
-    firstPlaylistAttribution = True
-    firstPlaylistCreator = True
-    firstPlaylistDate = True
-    firstPlaylistIdentifier = True
-    firstPlaylistImage = True
-    firstPlaylistInfo = True
-    firstPlaylistLicense = True
-    firstPlaylistLocation = True
-    firstPlaylistTitle = True
-    firstPlaylistTrackList = True
-    firstTrackTitle = True
-    firstTrackCreator = True
-    firstTrackAnnotation = True
-    firstTrackInfo = True
-    firstTrackImage = True
-    firstTrackAlbum = True
-    firstTrackTrackNum = True
-    firstTrackDuration = True
-    firstTrack = True
-
-    dateRegex = re.compile("^(-?\\d\\d\\d\\d)-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])T([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(\\.\\d+)?([+-](((0[0-9]|1[0-3]):[0-5][0-9])|14:00)|Z)?$")
-
-    SPIFF_NS_HOME = "http://xspf.org/ns/0/"
-    SPIFF_NS_SEP_CHAR = " "
-    XML_NS_HOME = "http://www.w3.org/XML/1998/namespace"
-
-    checker = xml.parsers.expat.ParserCreate(None, SPIFF_NS_SEP_CHAR)
-
-
-#############################################################################################
-
-
-errorTable = ""
-
-
-def nsXspf(localName):
-    return SPIFF_NS_HOME + SPIFF_NS_SEP_CHAR + localName
-
-
-def nsXml(localName):
-    return XML_NS_HOME + SPIFF_NS_SEP_CHAR + localName
-
-
-def startErrorTable():
-    if globals()["errorTable"] == "":
-        globals()["errorTable"] += """
-											<h3>Error protocol:</h3>
-											<table cellspacing="0">
-											<tr><td class="number">Line</td><td class="number">Col</td><td class="vert">&nbsp;</td><td class="error">Error</td></tr>
-											<tr height="1"><td class="horz">&nbsp;</td><td class="horz">&nbsp;</td><td class="horz">&nbsp;</td><td class="horz">&nbsp;</td></tr>"""
-
-
-# line is one-based
-def addError(line, col, escapedError):
-    globals()["errorTable"] += "<tr><td class=\"number\"><a href=\"#bad_" + str(line) + "\" class=\"number\">" + str(line) + "</a></td><td class=\"number\">" + str(col) + "</td><td class=\"vert\">&nbsp;</td><td class=\"error\">" + escapedError + "</td></tr>"
-
-
-def stopErrorTable():
-    if globals()["errorTable"] != "":
-        globals()["errorTable"] += """
-											</table>
-											<br>
-											<br>"""
-
-    else:
-        globals()["errorTable"] += """
-											<br>"""
-
-
-sourceTable = ""
-lastLine = -1
-
-
-def startSourceTable():
-    if globals()["sourceTable"] == "":
-        globals()["sourceTable"] = """
-											<h3>Processed input:</h3>
-											<table cellspacing="0">"""
-
-
-def stopSourceTable():
-    startSourceTable()
-
-    # Add missing lines
-    LAST = globals()["lastLine"]
-    ALL = len(globals()["lineHeads"])
-    if LAST < ALL - 1:
-        moreSourceLinesIncluding(ALL - 1, False)
-    globals()["sourceTable"] += """
-											</table>
-											<br>
-											<br>"""
-
-
-# lineNumber is zero-based
-def addSourceLine(lineNumber, badFlag):
-    globals()["sourceTable"] += """
-											<tr>
-												<td class="lineNumber">""" + str(lineNumber + 1) + """</td>
-												<td class="lineVert">&nbsp;</td>"""
-    if badFlag:
-        globals()["sourceTable"] += """
-												<td class="lineBad"><a name=\"bad_""" + str(lineNumber + 1) + """\" class=\"anchor\">"""
-    elif lineNumber % 2:
-        globals()["sourceTable"] += """
-												<td class="lineEven">"""
-    else:
-        globals()["sourceTable"] += """
-												<td class="lineOdd">"""
-
-    # Last line or normal?
-    if lineNumber == len(globals()["lineHeads"]) - 1:
-        line = input[lineHeads[lineNumber]:]
-    else:
-        line = input[lineHeads[lineNumber]:lineHeads[lineNumber + 1] - 1]
-
-    MAX_CHARS_PER_LINE = 100
-    line2 = line[0:MAX_CHARS_PER_LINE]
-    for i in range(MAX_CHARS_PER_LINE, len(line), MAX_CHARS_PER_LINE):
-        line2 += "\n" + line[i:i + MAX_CHARS_PER_LINE]
-    globals()["sourceTable"] += cgi.escape(line2).replace("\t", "&nbsp;&nbsp;").replace(" ", "&nbsp;").replace("\n", "<br>")
-    if badFlag:
-        globals()["sourceTable"] += """</a>"""
-    globals()["sourceTable"] += """</td>
-											</tr>"""
-
-
-# lineNumber is zero-based
-def moreSourceLinesIncluding(lineNumber, badFlag):
-    LAST = globals()["lastLine"]
-    if lineNumber <= LAST:
-        return
-
-    for i in range(LAST + 1, lineNumber):
-        addSourceLine(i, False)
-    addSourceLine(lineNumber, badFlag)
-    globals()["lastLine"] = lineNumber
-
-
-def fail(text):
-    globals()["valid"] = False
-
-    startErrorTable()
-    addError(checker.CurrentLineNumber, checker.CurrentColumnNumber + 1, text)
-
-    startSourceTable()
-    moreSourceLinesIncluding(checker.CurrentLineNumber - 1, True)
-
-
-def handlePlaylistAttribs(atts):
-    versionFound = False
-    keys = atts.keys()
-    for i in range(len(atts)):
-        name = keys[i]
-        if name == "version":
-            dummyVersion = atts.values()[i]
-            if dummyVersion == "0":
-                globals()["version"] = 0
-            elif dummyVersion == "1":
-                globals()["version"] = 1
-            else:
-                fail("Version must be <i>0</i> or <i>1</i>, not '" + cgi.escape(dummyVersion) + "'.")
-                globals()["version"] = 1
-            versionFound = True
-        elif name == nsXml("base"):
-            xmlBase = atts.values()[i]
-            if not isUri(xmlBase):
-                fail("Attribute <i>xml:base</i> is not a URI.")
-        else:
-            fail("Attribute '" + cgi.escape(name) + "' not allowed.")
-
-    if not versionFound:
-        fail("Attribute <i>version</i> missing.")
-
-
-def handleNoAttribsExceptXmlBase(atts):
-    keys = atts.keys()
-    for i in range(len(atts)):
-        name = keys[i]
-        if name == nsXml("base"):
-            xmlBase = atts.values()[i]
-            if not isUri(xmlBase):
-                fail("Attribute <i>xml:base</i> is not a URI.")
-        else:
-            fail("Attribute '" + cgi.escape(keys[i]) + "' not allowed.")
-
-
-def handleExtensionAttribs(atts):
-    size = len(atts)
-    applicationFound = False
-    for i in range(size):
-        name = atts.keys()[i]
-        if name == "application":
-            if not isUri(atts.values()[i]):
-                fail("Attribute <i>application</i> is not a URI.")
-            applicationFound = True
-        elif name == nsXml("base"):
-            xmlBase = atts.values()[i]
-            if not isUri(xmlBase):
-                fail("Attribute <i>xml:base</i> is not a URI.")
-        else:
-            fail("Attribute '" + cgi.escape(name) + "' not allowed.")
-    if not applicationFound:
-        fail("Attribute <i>application</i> missing.")
-
-
-def handleMetaLinkAttribs(atts):
-    size = len(atts)
-    relFound = False
-    for i in range(size):
-        name = atts.keys()[i]
-        if name == "rel":
-            if not isUri(atts.values()[i]):
-                fail("Attribute <i>rel</i> is not a URI.")
-            relFound = True
-        elif name == nsXml("base"):
-            xmlBase = atts.values()[i]
-            if not isUri(xmlBase):
-                fail("Attribute <i>xml:base</i> is not a URI.")
-        else:
-            fail("Attribute '" + cgi.escape(name) + "' not allowed.")
-    if not relFound:
-        fail("Attribute <i>rel</i> missing.")
-
-
-def handleStartOne(name, atts):
-    if name != nsXspf("playlist"):
-        # fail("Element '" + cgi.escape(name) + "' not allowed.")
-        fail("Root element must be <i>playlist</i>, not '" + cgi.escape(name) + "'.")
-    else:
-        handlePlaylistAttribs(atts)
-    globals()["stack"].append(TAG_PLAYLIST)
-
-
-def handleStartTwo(name, atts):
-    if name == nsXspf("annotation"):
-        if not globals()["firstPlaylistAnnotation"]:
-            fail("Only one <i>annotation</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistAnnotation"] = False
-        globals()["stack"].append(TAG_PLAYLIST_ANNOTATION)
-
-    elif name == nsXspf("attribution"):
-        if not globals()["firstPlaylistAttribution"]:
-            fail("Only one <i>attribution</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistAttribution"] = False
-        globals()["stack"].append(TAG_PLAYLIST_ATTRIBUTION)
-
-    elif name == nsXspf("creator"):
-        if not globals()["firstPlaylistCreator"]:
-            fail("Only one <i>creator</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistCreator"] = False
-        globals()["stack"].append(TAG_PLAYLIST_CREATOR)
-
-    elif name == nsXspf("date"):
-        if not globals()["firstPlaylistDate"]:
-            fail("Only one <i>date</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistDate"] = False
-        globals()["stack"].append(TAG_PLAYLIST_DATE)
-
-    elif name == nsXspf("extension"):
-        if globals()["version"] == 0:
-            fail("Element <i>" + cgi.escape(name) + "</i> not allowed in XSPF-0.")
-        else:
-            handleExtensionAttribs(atts)
-        globals()["stack"].append(TAG_PLAYLIST_EXTENSION)
-        # Skip extension body
-        globals()["skipAbove"] = 2
-
-    elif name == nsXspf("identifier"):
-        if not globals()["firstPlaylistIdentifier"]:
-            fail("Only one <i>identifier</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistIdentifier"] = False
-        globals()["stack"].append(TAG_PLAYLIST_IDENTIFIER)
-
-    elif name == nsXspf("image"):
-        if not globals()["firstPlaylistImage"]:
-            fail("Only one <i>image</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistImage"] = False
-        globals()["stack"].append(TAG_PLAYLIST_IMAGE)
-
-    elif name == nsXspf("info"):
-        if not globals()["firstPlaylistInfo"]:
-            fail("Only one <i>info</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistInfo"] = False
-        globals()["stack"].append(TAG_PLAYLIST_INFO)
-
-    elif name == nsXspf("license"):
-        if not globals()["firstPlaylistLicense"]:
-            fail("Only one <i>license</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistLicense"] = False
-        globals()["stack"].append(TAG_PLAYLIST_LICENSE)
-
-    elif name == nsXspf("link"):
-        handleMetaLinkAttribs(atts)
-        globals()["stack"].append(TAG_PLAYLIST_LINK)
-
-    elif name == nsXspf("location"):
-        if not globals()["firstPlaylistLocation"]:
-            fail("Only one <i>location</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistLocation"] = False
-        globals()["stack"].append(TAG_PLAYLIST_LOCATION)
-
-    elif name == nsXspf("meta"):
-        handleMetaLinkAttribs(atts)
-        globals()["stack"].append(TAG_PLAYLIST_META)
-
-    elif name == nsXspf("title"):
-        if not globals()["firstPlaylistTitle"]:
-            fail("Only one <i>title</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistTitle"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TITLE)
-
-    elif name == nsXspf("trackList"):
-        globals()["firstPlaylistTrackList"]
-        if not globals()["firstPlaylistTrackList"]:
-            fail("Only one <i>trackList</i> allowed for <i>playlist</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstPlaylistTrackList"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST)
-
-    else:
-        fail("Element <i>" + cgi.escape(name) + "</i> not allowed.")
-        globals()["stack"].append(TAG_UNKNOWN)
-        # Skip body of forbidden element
-#        globals()["skipAbove"]
-        globals()["skipAbove"] = 2
-
-
-def handleStartThree(name, atts):
-    stackTop = globals()["stack"][len(globals()["stack"]) - 1]
-    if stackTop == TAG_PLAYLIST_ATTRIBUTION:
-        if name == nsXspf("identifier"):
-            handleNoAttribsExceptXmlBase(atts)
-            globals()["stack"].append(TAG_PLAYLIST_ATTRIBUTION_IDENTIFIER)
-
-        elif name == nsXspf("location"):
-            handleNoAttribsExceptXmlBase(atts)
-            globals()["stack"].append(TAG_PLAYLIST_ATTRIBUTION_IDENTIFIER)
-
-        else:
-            fail("Element <i>" + cgi.escape(name) + "</i> not allowed.")
-            globals()["stack"].append(TAG_UNKNOWN)
-            # Skip body of forbidden element
-#            globals()["skipAbove"]
-            globals()["skipAbove"] = 3
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST:
-        if name == nsXspf("track"):
-            handleNoAttribsExceptXmlBase(atts)
-            globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK)
-
-        else:
-            fail("Element <i>" + cgi.escape(name) + "</i> not allowed.")
-            globals()["stack"].append(TAG_UNKNOWN)
-            # Skip body of forbidden element
-            globals()["skipAbove"] = 3
-
-        globals()["firstTrack"] = False
-
-    else:
-        fail("Element <i>" + cgi.escape(name) + "</i> not allowed.")
-        globals()["stack"].append(TAG_UNKNOWN)
-        # Skip body of forbidden element
-#        globals()["skipAbove"]
-        globals()["skipAbove"] = 3
-
-
-def handleStartFour(name, atts):
-    if name == nsXspf("album"):
-        if not globals()["firstTrackAlbum"]:
-            fail("Only one <i>album</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackAlbum"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_ALBUM)
-
-    elif name == nsXspf("annotation"):
-        if not globals()["firstTrackAnnotation"]:
-            fail("Only one <i>annotation</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackAnnotation"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_ANNOTATION)
-
-    elif name == nsXspf("creator"):
-        if not globals()["firstTrackCreator"]:
-            fail("Only one <i>creator</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackCreator"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_CREATOR)
-
-    elif name == nsXspf("duration"):
-        if not globals()["firstTrackDuration"]:
-            fail("Only one <i>duration</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackDuration"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_DURATION)
-
-    elif name == nsXspf("extension"):
-        if globals()["version"] == 0:
-            fail("Element <i>" + cgi.escape(name) + "</i> not allowed in XSPF-0.")
-        else:
-            handleExtensionAttribs(atts)
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_EXTENSION)
-        # Skip extension body
-        globals()["skipAbove"] = 4
-
-    elif name == nsXspf("identifier"):
-        handleNoAttribsExceptXmlBase(atts)
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_IDENTIFIER)
-
-    elif name == nsXspf("image"):
-        if not globals()["firstTrackImage"]:
-            fail("Only one <i>image</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackImage"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_IMAGE)
-
-    elif name == nsXspf("info"):
-        if not globals()["firstTrackInfo"]:
-            fail("Only one <i>info</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackInfo"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_INFO)
-
-    elif name == nsXspf("link"):
-        handleMetaLinkAttribs(atts)
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_LINK)
-
-    elif name == nsXspf("location"):
-        handleNoAttribsExceptXmlBase(atts)
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_LOCATION)
-
-    elif name == nsXspf("meta"):
-        handleMetaLinkAttribs(atts)
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_META)
-
-    elif name == nsXspf("trackNum"):
-        if not globals()["firstTrackTrackNum"]:
-            fail("Only one <i>trackNum</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackTrackNum"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_TRACKNUM)
-
-    elif name == nsXspf("title"):
-        if not globals()["firstTrackTitle"]:
-            fail("Only one <i>title</i> allowed for <i>track</i>.")
-        else:
-            handleNoAttribsExceptXmlBase(atts)
-        globals()["firstTrackTitle"] = False
-        globals()["stack"].append(TAG_PLAYLIST_TRACKLIST_TRACK_TITLE)
-
-    else:
-        fail("Element <i>" + cgi.escape(name) + "</i> not allowed.")
-        globals()["stack"].append(TAG_UNKNOWN)
-        # Skip body of forbidden element
-        globals()["skipAbove"] = 4
-
-
-def handleStart(name, atts):
-    newLevel = len(globals()["stack"]) + 1
-    if (globals()["skipAbove"] != -1) and (newLevel > globals()["skipAbove"]):
-        globals()["stack"].append(TAG_UNKNOWN)
-        return
-
-    if newLevel == 1:
-        handleStartOne(name, atts)
-    elif newLevel == 2:
-        handleStartTwo(name, atts)
-    elif newLevel == 3:
-        handleStartThree(name, atts)
-    elif newLevel == 4:
-        handleStartFour(name, atts)
-    else:
-        fail("Element <i>" + cgi.escape(name) + "</i> not allowed.")
-        globals()["stack"].append(TAG_UNKNOWN)
-        # Skip body of forbidden element
-        globals()["skipAbove"] = 4
-
-
-def handleEndOne(name):
-    if globals()["firstPlaylistTrackList"]:
-        fail("Element <i>trackList</i> missing.")
-
-
-def handleEndTwo(name):
-    stackTop = globals()["stack"][len(globals()["stack"]) - 1]
-
-    # Collapse elements
-    # NOTE: whitespace in the middle of <dateTime>,
-    # <nonNegativeInteger>, and <anyURI> is illegal anyway
-    # which is why we we only cut head and tail here
-    if stackTop in [TAG_PLAYLIST_INFO, TAG_PLAYLIST_LOCATION, \
-            TAG_PLAYLIST_IDENTIFIER, TAG_PLAYLIST_IMAGE, TAG_PLAYLIST_DATE, \
-            TAG_PLAYLIST_LICENSE, TAG_PLAYLIST_LINK, TAG_PLAYLIST_META]:
-        globals()["accum"] = globals()["accum"].strip()
-
-    if stackTop == TAG_PLAYLIST_DATE:
-        if not isDateTime(globals()["accum"]):
-            fail("Content of <i>date</i> is not a dateTime.")
-
-    elif stackTop == TAG_PLAYLIST_IDENTIFIER:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>identifier</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_IMAGE:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>image</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_INFO:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>info</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_LICENSE:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>license</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_LINK:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>link</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_LOCATION:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>location</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST:
-        if (globals()["version"] == 0) and (globals()["firstTrack"]):
-            fail("Element <i>track</i> missing. This is not allowed in XSPF-0.")
-
-    globals()["accum"] = ""
-
-
-def handleEndThree(name):
-    stackTop = globals()["stack"][len(globals()["stack"]) - 1]
-
-    # Collapse elements
-    # NOTE: whitespace in the middle of <dateTime>,
-    # <nonNegativeInteger>, and <anyURI> is illegal anyway
-    # which is why we we only cut head and tail here
-    if stackTop in [TAG_PLAYLIST_ATTRIBUTION_IDENTIFIER, \
-            TAG_PLAYLIST_ATTRIBUTION_LOCATION]:
-        globals()["accum"] = globals()["accum"].strip()
-
-    if stackTop == TAG_PLAYLIST_ATTRIBUTION_IDENTIFIER:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>identifier</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_ATTRIBUTION_LOCATION:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>location</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST_TRACK:
-        globals()["firstTrackTitle"] = True
-        globals()["firstTrackCreator"] = True
-        globals()["firstTrackAnnotation"] = True
-        globals()["firstTrackInfo"] = True
-        globals()["firstTrackImage"] = True
-        globals()["firstTrackAlbum"] = True
-        globals()["firstTrackTrackNum"] = True
-        globals()["firstTrackDuration"] = True
-
-    globals()["accum"] = ""
-
-
-def handleEndFour(name):
-    stackTop = globals()["stack"][len(globals()["stack"]) - 1]
-
-    # Collapse elements
-    # NOTE: whitespace in the middle of <dateTime>,
-    # <nonNegativeInteger>, and <anyURI> is illegal anyway
-    # which is why we we only cut head and tail here
-    if stackTop in [TAG_PLAYLIST_TRACKLIST_TRACK_LOCATION, \
-            TAG_PLAYLIST_TRACKLIST_TRACK_IDENTIFIER, \
-            TAG_PLAYLIST_TRACKLIST_TRACK_INFO, \
-            TAG_PLAYLIST_TRACKLIST_TRACK_IMAGE, \
-            TAG_PLAYLIST_TRACKLIST_TRACK_TRACKNUM, \
-            TAG_PLAYLIST_TRACKLIST_TRACK_DURATION, \
-            TAG_PLAYLIST_TRACKLIST_TRACK_LINK, \
-            TAG_PLAYLIST_TRACKLIST_TRACK_META]:
-        globals()["accum"] = globals()["accum"].strip()
-
-    if stackTop == TAG_PLAYLIST_TRACKLIST_TRACK_DURATION:
-        if not globals()["accum"].isdigit():
-            fail("Content of <i>duration</i> is not an unsigned integer.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST_TRACK_IDENTIFIER:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>identifier</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST_TRACK_IMAGE:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>image</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST_TRACK_INFO:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>info</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST_TRACK_LINK:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>link</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST_TRACK_LOCATION:
-        if not isUri(globals()["accum"]):
-            fail("Content of <i>location</i> is not a URI.")
-
-    elif stackTop == TAG_PLAYLIST_TRACKLIST_TRACK_TRACKNUM:
-        if not globals()["accum"].isdigit() or (globals()["accum"] == "0"):
-            fail("Content of <i>trackNum</i> is not an unsigned integer greater zero.")
-
-    globals()["accum"] = ""
-
-
-def handleEnd(name):
-    level = len(globals()["stack"])
-    if globals()["skipAbove"] == level:
-        globals()["skipAbove"] = -1
-    elif globals()["skipAbove"] > level:
-        globals()["stack"].pop()
-        return
-
-    if level == 1:
-        handleEndOne(name)
-    elif level == 2:
-        handleEndTwo(name)
-    elif level == 3:
-        handleEndThree(name)
-    elif level == 4:
-        handleEndFour(name)
-
-    globals()["stack"].pop()
-
-
-def handleCharacters(s):
-    level = len(globals()["stack"])
-    if (globals()["skipAbove"] != -1) and (level > globals()["skipAbove"]):
-        return
-
-    stackTop = stack[len(stack) - 1]
-    if level == 1:
-        if stackTop == TAG_PLAYLIST:
-            if s.strip() != "":
-                fail("No character data allowed")
-
-    elif level == 2:
-        if stackTop in [TAG_PLAYLIST_TRACKLIST, \
-                TAG_PLAYLIST_ATTRIBUTION]:
-            if s.strip() != "":
-                fail("No character data allowed")
-
-        else:
-            globals()["accum"] += s
-
-    elif level == 3:
-        if (stackTop == TAG_PLAYLIST_TRACKLIST_TRACK):
-            if s.strip() != "":
-                fail("No character data allowed")
-
-        else:
-            globals()["accum"] += s
-
-    elif level == 4:
-        globals()["accum"] += s
-
-
-entityNameToValueLen = {}
-
-
-def handleEntityDeclaration(entityName, is_parameter_entity, value, base, systemId, publicId, notationName):
-    MAX_LEN_PER_ENTITY_VALUE = 1000
-    MAX_LOOKUP_SUM_PER_ENTITY = 100
-    MAX_LOOKUP_DEPTH_PER_ENTITY = 3
-
-    valueLen = 0
-    lookupSum = 0
-    lookupDepth = 0
-
-    iter = re.finditer("&[^&;]+;", value)
-    lastend = 0
-    try:
-        while True:
-            match = iter.next()
-            start = match.start()
-            end = match.end()
-            valueLen += start - lastend
-
-            entityRefName = value[start + 1: end - 1]
-            try:
-                entityInfo = entityNameToValueLen[entityRefName]
-            except KeyError:
-                entityInfo = {
-                    'valueLen' : 1,
-                    'lookupSum' : 0,
-                    'lookupDepth' : 0,
-                }
-            valueLen += entityInfo['valueLen']
-            lookupSum += 1 + entityInfo['lookupSum']
-            lookupDepth = max(1 + entityInfo['lookupDepth'], lookupDepth)
-
-            lastend = end
-    except StopIteration:
-        valueLen += len(value) - lastend
-
-
-    # Panic if necessary
-    keepParsing = False
-    if valueLen > MAX_LEN_PER_ENTITY_VALUE:
-        fail("Entity takes too much space")
-    elif lookupSum > MAX_LOOKUP_SUM_PER_ENTITY:
-        fail("Entity requires too many lookups")
-    elif lookupDepth > MAX_LOOKUP_DEPTH_PER_ENTITY:
-        fail("Entity requires too deep lookup")
-    else:
-        keepParsing = True
-    if not keepParsing:
-        raise Exception("MALICIOUS")
-
-    # Save to map
-    entityNameToValueLen[entityName] = {
-        'valueLen' : valueLen,
-        'lookupSum' : lookupSum,
-        'lookupDepth' : lookupDepth,
-    }
-
-
-def isUri(text):
-    return Uri.MatchesUriRefSyntax(text)
-
-
-def isDateTime(text):
-    match = globals()["dateRegex"].match(text)
-    if not match:
-        return False
-
-    # Year- and month-specific day check
-    year = int(match.group(1))
-    month = int(match.group(2))
-    day = int(match.group(3))
-    if month == 2:
-        if day in [30, 31]:
-            return False
-
-        elif day == 29:
-            if (((year % 400) != 0) and (((year % 4) != 0) or ((year % 100) == 0))):
-                # Not a leap year
-                return False;
-
-    elif month in [4, 6, 9, 11]:
-        if day > 30:
-            return False
-
-    return True
-
-
-#############################################################################################
-
-
-if input != "":
-    # Results
-    checker.StartElementHandler = handleStart
-    checker.EndElementHandler = handleEnd
-    checker.CharacterDataHandler = handleCharacters
-    checker.EntityDeclHandler = handleEntityDeclaration
-
-    fatal = False
-    reason = ""
-    try:
-        checker.Parse(input, 1)
-    except xml.parsers.expat.ExpatError:
-        reason = "Invalid XML"
-        fatal = True
-    except Exception:
-        reason = "<b style=\"color:red;\">Input considered malicious. Please do <em>not</em> attack this site. Thanks.</b>"
-        fatal = True
-
-    if fatal:
-        errorLineOneBased = checker.ErrorLineNumber
-        startErrorTable()
-        addError(errorLineOneBased, checker.ErrorColumnNumber, reason)
-        startSourceTable()
-        moreSourceLinesIncluding(errorLineOneBased - 1, True)
-        valid = False
-
-
-    print """
-											<h3>Result:</h3>"""
-
-    if valid:
-        print """
-											<span class="valid">Valid</span>
-
-											<br>
-											<br>
-
-											<br>
-											
-											<h3>Congratulations!</h3>
-											<p style="text-align:justify">
-											<em>You care about interoperability and that shows: The content you provided is valid XSPF!</em><br>
-											<br>
-											To show you care and to promote XSPF, you may add this button to any page that serves
-											valid XSPF files. Here is HTML code that you can use to add the button:
-											</p>
-											
-											<center>
-												<!-- Two elements with horizintal space in between -->
-												<table border="0" cellpadding="0" cellspacing="10" style="margin-top:20px;margin-bottom:20px">
-													<tr>
-														<td>
-															<!-- Square border around the the button image -->
-															<table border="0" cellpadding="0" cellspacing="1" width="104" height="104" style="background-color:rgb(230,230,230);">
-																<tr>
-																	<!-- Button image demo -->
-																	<td valign="center" align="center" bgcolor="#FFF"><img src="http://svn.xiph.org/websites/xspf.org/images/banners/valid-xspf.png" width="88" height="31" style="border:0" alt="Valid XSPF Playlist" title="This sexy button could promote XSPF on your website!"></td>
-																</tr>
-															</table>
-														</td>
-														<!-- Embed code -->
-														<td><textarea readonly style="width:410px;height:104px;background-color:rgb(250,250,250);"><a href="http://validator.xspf.org/referrer/"><img src="valid-xspf.png" width="88" height="31" style="border:0" alt="Valid XSPF Playlist" title="This website produces valid XSPF playlist files."></a></textarea></td>
-													</tr>
-												</table>
-											</center>
-
-											Well done, please come back soon!"""
-    else:
-        print """
-											<span class="invalid">Invalid</span>"""
-											
-											
-
-    print """
-											<br>
-											<br>"""
-
-
-    stopErrorTable()
-    print errorTable
-
-    stopSourceTable()
-    print sourceTable
-
-
-    print """	
-										</td>
-									</tr>
-								</table>"""
-
-else:
-    # Formular
-    print """	
-								</table>
-								</form>"""
-
-
-print """
-							</td>
-						</tr>
-						<tr>
-							<td align="center" style="padding-left:6px; padding-right:6px;">
-								<table cellpadding="0" cellspacing="0" height="1" style="width:100%; background-color:rgb(180,180,180);">
-									<tr>
-										<td style="font-size:1px; line-height:1px;">&nbsp;</td>
-									</tr>
-								</table>
-							</td>
-						</tr>
-						<tr>
-							<td align="center" style="font-size:9pt; padding-top:2px; padding-bottom:5px;">
-								<a href="https://trac.xiph.org/browser/websites/validator.xspf.org">Source Code</a>&nbsp;&nbsp;&nbsp;
-								<a href="https://trac.xiph.org/browser/trunk/xspf/testcase">Test Cases</a>&nbsp;&nbsp;&nbsp;
-								<a href="http://libspiff.sourceforge.net/">libSpiff</a>&nbsp;&nbsp;&nbsp;
-								<a href="http://xspf.org/xspf-v1.html">XSPF Spec</a>&nbsp;&nbsp;&nbsp;
-							</td>
-						</tr>
-					</table>
-				</td>
-			</tr>
-		</table>
-	</body>
-</html>"""
-
-
-if shellMode:
-    if valid:
-        sys.exit(0)
-
-    else:
-        sys.exit(1)

Deleted: websites/validator.xspf.org/hello_uri.py
===================================================================
--- websites/validator.xspf.org/hello_uri.py	2009-05-05 12:40:48 UTC (rev 15981)
+++ websites/validator.xspf.org/hello_uri.py	2009-05-05 22:41:30 UTC (rev 15982)
@@ -1,53 +0,0 @@
-#! /usr/bin/python
-# -----------------------------------------------------------------------
-# Online XSPF Validator
-# Copyright (C) 2007, Sebastian Pipping / Xiph.Org Foundation
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Sebastian Pipping, sping at xiph.org
-# -----------------------------------------------------------------------
-
-import sys
-try:
-    from Ft.Lib import Uri
-except ImportError:
-    print "ERROR: Package 'Ft.Lib' is missing. On Debian testing/unstable run:\n" \
-            "sudo apt-get install python-4suite-xml"
-    sys.exit(1)
-
-print "Content-Type: text/html"     # HTML is following
-print                               # blank line, end of headers
-
-
-def checkValidity(candidate):
-    print "* validUri(\"" + candidate + "\") == " \
-            + str(Uri.MatchesUriRefSyntax(candidate)) + "<br>"
-
-def isSafeDownloadTarget(candidate):
-    schemeOrNone = Uri.GetScheme(candidate)
-    return (schemeOrNone != None) and (schemeOrNone.lower() == "http")
-
-def checkSafety(candidate):
-    print "* safeUri(\"" + candidate + "\") == " \
-            + str(isSafeDownloadTarget(candidate)) + "<br>"
-
-
-checkValidity("http://www.xiph.org/")
-checkValidity("abc%20def")
-checkValidity("abc def")
-
-checkSafety("HTTP://www.example.org/")
-checkSafety("ftp://www.example.org/")

Deleted: websites/validator.xspf.org/xspflogo-1.5.gif
===================================================================
(Binary files differ)



More information about the commits mailing list