[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 — 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"> </td><td class="error">Error</td></tr>
- <tr height="1"><td class="horz"> </td><td class="horz"> </td><td class="horz"> </td><td class="horz"> </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\"> </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"> </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", " ").replace(" ", " ").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;"> </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>
- <a href="https://trac.xiph.org/browser/trunk/xspf/testcase">Test Cases</a>
- <a href="http://libspiff.sourceforge.net/">libSpiff</a>
- <a href="http://xspf.org/xspf-v1.html">XSPF Spec</a>
- </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