mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
Removing old feedvalidator, unused fab commands.
This commit is contained in:
parent
16b86fec3a
commit
eaa24a0412
2358 changed files with 0 additions and 85533 deletions
|
@ -137,7 +137,6 @@ these after the installation below.
|
|||
the `fabfile.py`. You should also have MySQL/PostgreSQL and MongoDB already installed.
|
||||
|
||||
fab -R local setup_python
|
||||
fab -R local setup_imaging
|
||||
fab -R local setup_mongoengine
|
||||
fab -R local setup_forked_mongoengine
|
||||
fab -R local setup_repo_local_settings
|
||||
|
|
24
fabfile.py
vendored
24
fabfile.py
vendored
|
@ -212,7 +212,6 @@ def setup_common():
|
|||
# setup_pymongo_repo()
|
||||
setup_logrotate()
|
||||
setup_nginx()
|
||||
# setup_imaging()
|
||||
setup_munin()
|
||||
|
||||
def setup_all():
|
||||
|
@ -458,25 +457,6 @@ def setup_libxml_code():
|
|||
def setup_psycopg():
|
||||
sudo('easy_install -U psycopg2')
|
||||
|
||||
# def setup_python():
|
||||
# # sudo('easy_install -U $(<%s)' %
|
||||
# # os.path.join(env.NEWSBLUR_PATH, 'config/requirements.txt'))
|
||||
# pip()
|
||||
# put('config/pystartup.py', '.pystartup')
|
||||
#
|
||||
# # with cd(os.path.join(env.NEWSBLUR_PATH, 'vendor/cjson')):
|
||||
# # sudo('python setup.py install')
|
||||
#
|
||||
# with settings(warn_only=True):
|
||||
# sudo('echo "import sys; sys.setdefaultencoding(\'utf-8\')" | sudo tee /usr/lib/python2.7/sitecustomize.py')
|
||||
# sudo("chmod a+r /usr/local/lib/python2.7/dist-packages/httplib2-0.8-py2.7.egg/EGG-INFO/top_level.txt")
|
||||
# sudo("chmod a+r /usr/local/lib/python2.7/dist-packages/python_dateutil-2.1-py2.7.egg/EGG-INFO/top_level.txt")
|
||||
# sudo("chmod a+r /usr/local/lib/python2.7/dist-packages/httplib2-0.8-py2.7.egg/httplib2/cacerts.txt")
|
||||
#
|
||||
# if env.user == 'ubuntu':
|
||||
# with settings(warn_only=True):
|
||||
# sudo('chown -R ubuntu.ubuntu /home/ubuntu/.python-eggs')
|
||||
|
||||
def setup_virtualenv():
|
||||
sudo('rm -fr ~/.cache') # Clean `sudo pip`
|
||||
sudo('pip install --upgrade virtualenv')
|
||||
|
@ -529,10 +509,6 @@ def solo_pip(role):
|
|||
pip()
|
||||
celery()
|
||||
|
||||
# PIL - Only if python-imaging didn't install through apt-get, like on Mac OS X.
|
||||
def setup_imaging():
|
||||
sudo('easy_install --always-unzip pil')
|
||||
|
||||
def setup_supervisor():
|
||||
sudo('apt-get -y install supervisor')
|
||||
put('config/supervisord.conf', '/etc/supervisor/supervisord.conf', use_sudo=True)
|
||||
|
|
290
vendor/feedvalidator/__init__.py
vendored
290
vendor/feedvalidator/__init__.py
vendored
|
@ -1,290 +0,0 @@
|
|||
"""$Id: __init__.py 699 2006-09-25 02:01:18Z rubys $"""
|
||||
|
||||
__author__ = "Sam Ruby <http://intertwingly.net/> and Mark Pilgrim <http://diveintomark.org/>"
|
||||
__version__ = "$Revision: 699 $"
|
||||
__date__ = "$Date: 2006-09-25 02:01:18 +0000 (Mon, 25 Sep 2006) $"
|
||||
__copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim"
|
||||
|
||||
import socket
|
||||
if hasattr(socket, 'setdefaulttimeout'):
|
||||
socket.setdefaulttimeout(10)
|
||||
Timeout = socket.timeout
|
||||
else:
|
||||
import timeoutsocket
|
||||
timeoutsocket.setDefaultSocketTimeout(10)
|
||||
Timeout = timeoutsocket.Timeout
|
||||
|
||||
import urllib2
|
||||
import logging
|
||||
from logging import *
|
||||
from xml.sax import SAXException
|
||||
from xml.sax.xmlreader import InputSource
|
||||
import re
|
||||
import xmlEncoding
|
||||
import mediaTypes
|
||||
from httplib import BadStatusLine
|
||||
|
||||
MAXDATALENGTH = 200000
|
||||
|
||||
def _validate(aString, firstOccurrenceOnly, loggedEvents, base, encoding, selfURIs=None):
|
||||
"""validate RSS from string, returns validator object"""
|
||||
from xml.sax import make_parser, handler
|
||||
from base import SAXDispatcher
|
||||
from exceptions import UnicodeError
|
||||
from cStringIO import StringIO
|
||||
|
||||
# By now, aString should be Unicode
|
||||
source = InputSource()
|
||||
source.setByteStream(StringIO(xmlEncoding.asUTF8(aString)))
|
||||
|
||||
validator = SAXDispatcher(base, selfURIs or [base], encoding)
|
||||
validator.setFirstOccurrenceOnly(firstOccurrenceOnly)
|
||||
|
||||
validator.loggedEvents += loggedEvents
|
||||
|
||||
# experimental RSS-Profile draft 1.06 support
|
||||
validator.setLiterals(re.findall('&(\w+);',aString))
|
||||
|
||||
xmlver = re.match("^<\?\s*xml\s+version\s*=\s*['\"]([-a-zA-Z0-9_.:]*)['\"]",aString)
|
||||
if xmlver and xmlver.group(1)<>'1.0':
|
||||
validator.log(logging.BadXmlVersion({"version":xmlver.group(1)}))
|
||||
|
||||
try:
|
||||
from xml.sax.expatreader import ExpatParser
|
||||
class fake_dtd_parser(ExpatParser):
|
||||
def reset(self):
|
||||
ExpatParser.reset(self)
|
||||
self._parser.UseForeignDTD(1)
|
||||
parser = fake_dtd_parser()
|
||||
except:
|
||||
parser = make_parser()
|
||||
|
||||
parser.setFeature(handler.feature_namespaces, 1)
|
||||
parser.setContentHandler(validator)
|
||||
parser.setErrorHandler(validator)
|
||||
parser.setEntityResolver(validator)
|
||||
if hasattr(parser, '_ns_stack'):
|
||||
# work around bug in built-in SAX parser (doesn't recognize xml: namespace)
|
||||
# PyXML doesn't have this problem, and it doesn't have _ns_stack either
|
||||
parser._ns_stack.append({'http://www.w3.org/XML/1998/namespace':'xml'})
|
||||
|
||||
def xmlvalidate(log):
|
||||
import libxml2
|
||||
from StringIO import StringIO
|
||||
from random import random
|
||||
|
||||
prefix="...%s..." % str(random()).replace('0.','')
|
||||
msg=[]
|
||||
libxml2.registerErrorHandler(lambda msg,str: msg.append(str), msg)
|
||||
|
||||
input = libxml2.inputBuffer(StringIO(xmlEncoding.asUTF8(aString)))
|
||||
reader = input.newTextReader(prefix)
|
||||
reader.SetParserProp(libxml2.PARSER_VALIDATE, 1)
|
||||
ret = reader.Read()
|
||||
while ret == 1: ret = reader.Read()
|
||||
|
||||
msg=''.join(msg)
|
||||
for line in msg.splitlines():
|
||||
if line.startswith(prefix): log(line.split(':',4)[-1].strip())
|
||||
validator.xmlvalidator=xmlvalidate
|
||||
|
||||
try:
|
||||
parser.parse(source)
|
||||
except SAXException:
|
||||
pass
|
||||
except UnicodeError:
|
||||
import sys
|
||||
exctype, value = sys.exc_info()[:2]
|
||||
validator.log(logging.UnicodeError({"exception":value}))
|
||||
|
||||
if validator.getFeedType() == TYPE_RSS1:
|
||||
try:
|
||||
from rdflib.syntax.parsers.RDFXMLHandler import RDFXMLHandler
|
||||
|
||||
class Handler(RDFXMLHandler):
|
||||
ns_prefix_map = {}
|
||||
prefix_ns_map = {}
|
||||
def add(self, triple): pass
|
||||
def __init__(self, dispatcher):
|
||||
RDFXMLHandler.__init__(self, self)
|
||||
self.dispatcher=dispatcher
|
||||
def error(self, message):
|
||||
self.dispatcher.log(InvalidRDF({"message": message}))
|
||||
|
||||
source.getByteStream().reset()
|
||||
parser.reset()
|
||||
parser.setContentHandler(Handler(parser.getContentHandler()))
|
||||
parser.setErrorHandler(handler.ErrorHandler())
|
||||
parser.parse(source)
|
||||
except:
|
||||
pass
|
||||
|
||||
return validator
|
||||
|
||||
def validateStream(aFile, firstOccurrenceOnly=0, contentType=None, base=""):
|
||||
loggedEvents = []
|
||||
|
||||
if contentType:
|
||||
(mediaType, charset) = mediaTypes.checkValid(contentType, loggedEvents)
|
||||
else:
|
||||
(mediaType, charset) = (None, None)
|
||||
|
||||
rawdata = aFile.read(MAXDATALENGTH)
|
||||
if aFile.read(1):
|
||||
raise ValidationFailure(logging.ValidatorLimit({'limit': 'feed length > ' + str(MAXDATALENGTH) + ' bytes'}))
|
||||
|
||||
encoding, rawdata = xmlEncoding.decode(mediaType, charset, rawdata, loggedEvents, fallback='utf-8')
|
||||
|
||||
validator = _validate(rawdata, firstOccurrenceOnly, loggedEvents, base, encoding)
|
||||
|
||||
if mediaType and validator.feedType:
|
||||
mediaTypes.checkAgainstFeedType(mediaType, validator.feedType, validator.loggedEvents)
|
||||
|
||||
return {"feedType":validator.feedType, "loggedEvents":validator.loggedEvents}
|
||||
|
||||
def validateString(aString, firstOccurrenceOnly=0, fallback=None, base=""):
|
||||
loggedEvents = []
|
||||
if type(aString) != unicode:
|
||||
encoding, aString = xmlEncoding.decode("", None, aString, loggedEvents, fallback)
|
||||
else:
|
||||
encoding = "utf-8" # setting a sane (?) default
|
||||
|
||||
if aString is not None:
|
||||
validator = _validate(aString, firstOccurrenceOnly, loggedEvents, base, encoding)
|
||||
return {"feedType":validator.feedType, "loggedEvents":validator.loggedEvents}
|
||||
else:
|
||||
return {"loggedEvents": loggedEvents}
|
||||
|
||||
def validateURL(url, firstOccurrenceOnly=1, wantRawData=0):
|
||||
"""validate RSS from URL, returns events list, or (events, rawdata) tuple"""
|
||||
loggedEvents = []
|
||||
request = urllib2.Request(url)
|
||||
request.add_header("Accept-encoding", "gzip, deflate")
|
||||
request.add_header("User-Agent", "FeedValidator/1.3")
|
||||
usock = None
|
||||
try:
|
||||
try:
|
||||
usock = urllib2.urlopen(request)
|
||||
rawdata = usock.read(MAXDATALENGTH)
|
||||
if usock.read(1):
|
||||
raise ValidationFailure(logging.ValidatorLimit({'limit': 'feed length > ' + str(MAXDATALENGTH) + ' bytes'}))
|
||||
|
||||
# check for temporary redirects
|
||||
if usock.geturl()<>request.get_full_url():
|
||||
from httplib import HTTPConnection
|
||||
spliturl=url.split('/',3)
|
||||
if spliturl[0]=="http:":
|
||||
conn=HTTPConnection(spliturl[2])
|
||||
conn.request("GET",'/'+spliturl[3].split("#",1)[0])
|
||||
resp=conn.getresponse()
|
||||
if resp.status<>301:
|
||||
loggedEvents.append(TempRedirect({}))
|
||||
|
||||
except BadStatusLine, status:
|
||||
raise ValidationFailure(logging.HttpError({'status': status.__class__}))
|
||||
|
||||
except urllib2.HTTPError, status:
|
||||
rawdata = status.read()
|
||||
lastline = rawdata.strip().split('\n')[-1].strip()
|
||||
if lastline in ['</rss>','</feed>','</rdf:RDF>']:
|
||||
loggedEvents.append(logging.HttpError({'status': status}))
|
||||
usock = status
|
||||
else:
|
||||
raise ValidationFailure(logging.HttpError({'status': status}))
|
||||
except urllib2.URLError, x:
|
||||
raise ValidationFailure(logging.HttpError({'status': x.reason}))
|
||||
except Timeout, x:
|
||||
raise ValidationFailure(logging.IOError({"message": 'Server timed out', "exception":x}))
|
||||
|
||||
if usock.headers.get('content-encoding', None) == None:
|
||||
loggedEvents.append(Uncompressed({}))
|
||||
|
||||
if usock.headers.get('content-encoding', None) == 'gzip':
|
||||
import gzip, StringIO
|
||||
try:
|
||||
rawdata = gzip.GzipFile(fileobj=StringIO.StringIO(rawdata)).read()
|
||||
except:
|
||||
import sys
|
||||
exctype, value = sys.exc_info()[:2]
|
||||
event=logging.IOError({"message": 'Server response declares Content-Encoding: gzip', "exception":value})
|
||||
raise ValidationFailure(event)
|
||||
|
||||
if usock.headers.get('content-encoding', None) == 'deflate':
|
||||
import zlib
|
||||
try:
|
||||
rawdata = zlib.decompress(rawdata, -zlib.MAX_WBITS)
|
||||
except:
|
||||
import sys
|
||||
exctype, value = sys.exc_info()[:2]
|
||||
event=logging.IOError({"message": 'Server response declares Content-Encoding: deflate', "exception":value})
|
||||
raise ValidationFailure(event)
|
||||
|
||||
mediaType = None
|
||||
charset = None
|
||||
|
||||
# Is the Content-Type correct?
|
||||
contentType = usock.headers.get('content-type', None)
|
||||
if contentType:
|
||||
(mediaType, charset) = mediaTypes.checkValid(contentType, loggedEvents)
|
||||
|
||||
# Check for malformed HTTP headers
|
||||
for (h, v) in usock.headers.items():
|
||||
if (h.find(' ') >= 0):
|
||||
loggedEvents.append(HttpProtocolError({'header': h}))
|
||||
|
||||
selfURIs = [request.get_full_url()]
|
||||
baseURI = usock.geturl()
|
||||
if not baseURI in selfURIs: selfURIs.append(baseURI)
|
||||
|
||||
# Get baseURI from content-location and/or redirect information
|
||||
if usock.headers.get('content-location', None):
|
||||
from urlparse import urljoin
|
||||
baseURI=urljoin(baseURI,usock.headers.get('content-location', ""))
|
||||
elif usock.headers.get('location', None):
|
||||
from urlparse import urljoin
|
||||
baseURI=urljoin(baseURI,usock.headers.get('location', ""))
|
||||
|
||||
if not baseURI in selfURIs: selfURIs.append(baseURI)
|
||||
usock.close()
|
||||
usock = None
|
||||
|
||||
mediaTypes.contentSniffing(mediaType, rawdata, loggedEvents)
|
||||
|
||||
encoding, rawdata = xmlEncoding.decode(mediaType, charset, rawdata, loggedEvents, fallback='utf-8')
|
||||
|
||||
if rawdata is None:
|
||||
return {'loggedEvents': loggedEvents}
|
||||
|
||||
rawdata = rawdata.replace('\r\n', '\n').replace('\r', '\n') # normalize EOL
|
||||
validator = _validate(rawdata, firstOccurrenceOnly, loggedEvents, baseURI, encoding, selfURIs)
|
||||
|
||||
# Warn about mismatches between media type and feed version
|
||||
if mediaType and validator.feedType:
|
||||
mediaTypes.checkAgainstFeedType(mediaType, validator.feedType, validator.loggedEvents)
|
||||
|
||||
params = {"feedType":validator.feedType, "loggedEvents":validator.loggedEvents}
|
||||
if wantRawData:
|
||||
params['rawdata'] = rawdata
|
||||
return params
|
||||
|
||||
finally:
|
||||
try:
|
||||
if usock: usock.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
__all__ = ['base',
|
||||
'channel',
|
||||
'compatibility',
|
||||
'image',
|
||||
'item',
|
||||
'logging',
|
||||
'rdf',
|
||||
'root',
|
||||
'rss',
|
||||
'skipHours',
|
||||
'textInput',
|
||||
'util',
|
||||
'validators',
|
||||
'validateURL',
|
||||
'validateString']
|
53
vendor/feedvalidator/author.py
vendored
53
vendor/feedvalidator/author.py
vendored
|
@ -1,53 +0,0 @@
|
|||
"""$Id: author.py 699 2006-09-25 02:01:18Z rubys $"""
|
||||
|
||||
__author__ = "Sam Ruby <http://intertwingly.net/> and Mark Pilgrim <http://diveintomark.org/>"
|
||||
__version__ = "$Revision: 699 $"
|
||||
__date__ = "$Date: 2006-09-25 02:01:18 +0000 (Mon, 25 Sep 2006) $"
|
||||
__copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim"
|
||||
|
||||
from base import validatorBase
|
||||
from validators import *
|
||||
|
||||
#
|
||||
# author element.
|
||||
#
|
||||
class author(validatorBase):
|
||||
def getExpectedAttrNames(self):
|
||||
return [(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#', u'parseType')]
|
||||
|
||||
def validate(self):
|
||||
if not "name" in self.children and not "atom_name" in self.children:
|
||||
self.log(MissingElement({"parent":self.name, "element":"name"}))
|
||||
|
||||
def do_name(self):
|
||||
return nonhtml(), nonemail(), nonblank(), noduplicates()
|
||||
|
||||
def do_email(self):
|
||||
return addr_spec(), noduplicates()
|
||||
|
||||
def do_uri(self):
|
||||
return nonblank(), rfc3987(), nows(), noduplicates()
|
||||
|
||||
def do_foaf_workplaceHomepage(self):
|
||||
return rdfResourceURI()
|
||||
|
||||
def do_foaf_homepage(self):
|
||||
return rdfResourceURI()
|
||||
|
||||
def do_foaf_weblog(self):
|
||||
return rdfResourceURI()
|
||||
|
||||
def do_foaf_plan(self):
|
||||
return text()
|
||||
|
||||
def do_foaf_firstName(self):
|
||||
return text()
|
||||
|
||||
def do_xhtml_div(self):
|
||||
from content import diveater
|
||||
return diveater()
|
||||
|
||||
# RSS/Atom support
|
||||
do_atom_name = do_name
|
||||
do_atom_email = do_email
|
||||
do_atom_uri = do_uri
|
511
vendor/feedvalidator/base.py
vendored
511
vendor/feedvalidator/base.py
vendored
|
@ -1,511 +0,0 @@
|
|||
"""$Id: base.py 744 2007-03-24 11:57:16Z rubys $"""
|
||||
|
||||
__author__ = "Sam Ruby <http://intertwingly.net/> and Mark Pilgrim <http://diveintomark.org/>"
|
||||
__version__ = "$Revision: 744 $"
|
||||
__date__ = "$Date: 2007-03-24 11:57:16 +0000 (Sat, 24 Mar 2007) $"
|
||||
__copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim"
|
||||
|
||||
from xml.sax.handler import ContentHandler
|
||||
from xml.sax.xmlreader import Locator
|
||||
from logging import NonCanonicalURI, NotUTF8
|
||||
import re
|
||||
|
||||
# references:
|
||||
# http://web.resource.org/rss/1.0/modules/standard.html
|
||||
# http://web.resource.org/rss/1.0/modules/proposed.html
|
||||
# http://dmoz.org/Reference/Libraries/Library_and_Information_Science/Technical_Services/Cataloguing/Metadata/RDF/Applications/RSS/Specifications/RSS1.0_Modules/
|
||||
namespaces = {
|
||||
"http://www.bloglines.com/about/specs/fac-1.0": "access",
|
||||
"http://webns.net/mvcb/": "admin",
|
||||
"http://purl.org/rss/1.0/modules/aggregation/": "ag",
|
||||
"http://purl.org/rss/1.0/modules/annotate/": "annotate",
|
||||
"http://media.tangent.org/rss/1.0/": "audio",
|
||||
"http://backend.userland.com/blogChannelModule": "blogChannel",
|
||||
"http://web.resource.org/cc/": "cc",
|
||||
"http://www.microsoft.com/schemas/rss/core/2005": "cf",
|
||||
"http://backend.userland.com/creativeCommonsRssModule": "creativeCommons",
|
||||
"http://purl.org/rss/1.0/modules/company": "company",
|
||||
"http://purl.org/rss/1.0/modules/content/": "content",
|
||||
"http://my.theinfo.org/changed/1.0/rss/": "cp",
|
||||
"http://purl.org/dc/elements/1.1/": "dc",
|
||||
"http://purl.org/dc/terms/": "dcterms",
|
||||
"http://purl.org/rss/1.0/modules/email/": "email",
|
||||
"http://purl.org/rss/1.0/modules/event/": "ev",
|
||||
"http://www.w3.org/2003/01/geo/wgs84_pos#": "geo",
|
||||
"http://geourl.org/rss/module/": "geourl",
|
||||
"http://www.georss.org/georss": "georss",
|
||||
"http://www.opengis.net/gml": "gml",
|
||||
"http://postneo.com/icbm": "icbm",
|
||||
"http://purl.org/rss/1.0/modules/image/": "image",
|
||||
"http://www.itunes.com/dtds/podcast-1.0.dtd": "itunes",
|
||||
"http://xmlns.com/foaf/0.1/": "foaf",
|
||||
"http://purl.org/rss/1.0/modules/link/": "l",
|
||||
"http://search.yahoo.com/mrss/": "media",
|
||||
"http://a9.com/-/spec/opensearch/1.1/": "opensearch",
|
||||
"http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
|
||||
"http://www.w3.org/2000/01/rdf-schema#": "rdfs",
|
||||
"http://purl.org/rss/1.0/modules/reference/": "ref",
|
||||
"http://purl.org/rss/1.0/modules/richequiv/": "reqv",
|
||||
"http://purl.org/rss/1.0/modules/rss091#": "rss091",
|
||||
"http://purl.org/rss/1.0/modules/search/": "search",
|
||||
"http://purl.org/rss/1.0/modules/slash/": "slash",
|
||||
"http://purl.org/rss/1.0/modules/servicestatus/": "ss",
|
||||
"http://hacks.benhammersley.com/rss/streaming/": "str",
|
||||
"http://purl.org/rss/1.0/modules/subscription/": "sub",
|
||||
"http://purl.org/rss/1.0/modules/syndication/": "sy",
|
||||
"http://purl.org/rss/1.0/modules/taxonomy/": "taxo",
|
||||
"http://purl.org/rss/1.0/modules/threading/": "thr",
|
||||
"http://purl.org/syndication/thread/1.0": "thr",
|
||||
"http://madskills.com/public/xml/rss/module/trackback/": "trackback",
|
||||
"http://wellformedweb.org/CommentAPI/": "wfw",
|
||||
"http://purl.org/rss/1.0/modules/wiki/": "wiki",
|
||||
"http://www.usemod.com/cgi-bin/mb.pl?ModWiki": "wiki",
|
||||
"http://schemas.xmlsoap.org/soap/envelope/": "soap",
|
||||
"http://www.w3.org/2005/Atom": "atom",
|
||||
"http://www.w3.org/1999/xhtml": "xhtml",
|
||||
"http://my.netscape.com/rdf/simple/0.9/": "rss090",
|
||||
"http://purl.org/net/rss1.1#": "rss11",
|
||||
"http://base.google.com/ns/1.0": "g",
|
||||
"http://www.w3.org/XML/1998/namespace": "xml",
|
||||
"http://openid.net/xmlns/1.0": "openid",
|
||||
"xri://$xrd*($v*2.0)": "xrd",
|
||||
"xri://$xrds": "xrds",
|
||||
}
|
||||
|
||||
def near_miss(ns):
|
||||
try:
|
||||
return re.match(".*\w", ns).group().lower()
|
||||
except:
|
||||
return ns
|
||||
|
||||
nearly_namespaces = dict([(near_miss(u),p) for u,p in namespaces.items()])
|
||||
|
||||
stdattrs = [(u'http://www.w3.org/XML/1998/namespace', u'base'),
|
||||
(u'http://www.w3.org/XML/1998/namespace', u'lang'),
|
||||
(u'http://www.w3.org/XML/1998/namespace', u'space')]
|
||||
|
||||
#
|
||||
# From the SAX parser's point of view, this class is the one responsible for
|
||||
# handling SAX events. In actuality, all this class does is maintain a
|
||||
# pushdown stack of the *real* content handlers, and delegates sax events
|
||||
# to the current one.
|
||||
#
|
||||
class SAXDispatcher(ContentHandler):
|
||||
|
||||
firstOccurrenceOnly = 0
|
||||
|
||||
def __init__(self, base, selfURIs, encoding):
|
||||
from root import root
|
||||
ContentHandler.__init__(self)
|
||||
self.lastKnownLine = 1
|
||||
self.lastKnownColumn = 0
|
||||
self.loggedEvents = []
|
||||
self.feedType = 0
|
||||
try:
|
||||
self.xmlBase = base.encode('idna')
|
||||
except:
|
||||
self.xmlBase = base
|
||||
self.selfURIs = selfURIs
|
||||
self.encoding = encoding
|
||||
self.handler_stack=[[root(self, base)]]
|
||||
self.literal_entities=[]
|
||||
self.defaultNamespaces = []
|
||||
|
||||
# experimental RSS-Profile draft 1.06 support
|
||||
def setLiterals(self, literals):
|
||||
for literal in literals:
|
||||
if literal not in self.literal_entities:
|
||||
self.literal_entities.append(literal)
|
||||
|
||||
def setDocumentLocator(self, locator):
|
||||
self.locator = locator
|
||||
ContentHandler.setDocumentLocator(self, self.locator)
|
||||
|
||||
def setFirstOccurrenceOnly(self, firstOccurrenceOnly=1):
|
||||
self.firstOccurrenceOnly = firstOccurrenceOnly
|
||||
|
||||
def startPrefixMapping(self, prefix, uri):
|
||||
for handler in iter(self.handler_stack[-1]):
|
||||
handler.namespace[prefix] = uri
|
||||
if uri and len(uri.split())>1:
|
||||
from xml.sax import SAXException
|
||||
self.error(SAXException('Invalid Namespace: %s' % uri))
|
||||
if prefix in namespaces.values():
|
||||
if not namespaces.get(uri,'') == prefix and prefix:
|
||||
from logging import ReservedPrefix
|
||||
preferredURI = [key for key, value in namespaces.items() if value == prefix][0]
|
||||
self.log(ReservedPrefix({'prefix':prefix, 'ns':preferredURI}))
|
||||
elif prefix=='wiki' and uri.find('usemod')>=0:
|
||||
from logging import ObsoleteWikiNamespace
|
||||
self.log(ObsoleteWikiNamespace({'preferred':namespaces[uri], 'ns':uri}))
|
||||
elif namespaces.has_key(uri):
|
||||
if not namespaces[uri] == prefix and prefix:
|
||||
from logging import NonstdPrefix
|
||||
self.log(NonstdPrefix({'preferred':namespaces[uri], 'ns':uri}))
|
||||
|
||||
def namespaceFor(self, prefix):
|
||||
return None
|
||||
|
||||
def startElementNS(self, name, qname, attrs):
|
||||
self.lastKnownLine = self.locator.getLineNumber()
|
||||
self.lastKnownColumn = self.locator.getColumnNumber()
|
||||
qname, name = name
|
||||
for handler in iter(self.handler_stack[-1]):
|
||||
handler.startElementNS(name, qname, attrs)
|
||||
|
||||
if len(attrs):
|
||||
present = attrs.getNames()
|
||||
unexpected = filter(lambda x: x not in stdattrs, present)
|
||||
for handler in iter(self.handler_stack[-1]):
|
||||
ean = handler.getExpectedAttrNames()
|
||||
if ean: unexpected = filter(lambda x: x not in ean, unexpected)
|
||||
for u in unexpected:
|
||||
if u[0] and near_miss(u[0]) not in nearly_namespaces:
|
||||
feedtype=self.getFeedType()
|
||||
if (not qname) and feedtype and (feedtype==TYPE_RSS2):
|
||||
from logging import InvalidExtensionAttr
|
||||
self.log(InvalidExtensionAttr({"attribute":u, "element":name}))
|
||||
continue
|
||||
from logging import UnexpectedAttribute
|
||||
if not u[0]: u=u[1]
|
||||
self.log(UnexpectedAttribute({"parent":name, "attribute":u, "element":name}))
|
||||
|
||||
def resolveEntity(self, publicId, systemId):
|
||||
if not publicId and not systemId:
|
||||
import cStringIO
|
||||
return cStringIO.StringIO()
|
||||
|
||||
try:
|
||||
def log(exception):
|
||||
from logging import SAXError
|
||||
self.log(SAXError({'exception':str(exception)}))
|
||||
if self.xmlvalidator:
|
||||
self.xmlvalidator(log)
|
||||
self.xmlvalidator=0
|
||||
except:
|
||||
pass
|
||||
|
||||
if (publicId=='-//Netscape Communications//DTD RSS 0.91//EN' and
|
||||
systemId=='http://my.netscape.com/publish/formats/rss-0.91.dtd'):
|
||||
from logging import ValidDoctype, DeprecatedDTD
|
||||
self.log(ValidDoctype({}))
|
||||
self.log(DeprecatedDTD({}))
|
||||
else:
|
||||
from logging import ContainsSystemEntity
|
||||
self.lastKnownLine = self.locator.getLineNumber()
|
||||
self.lastKnownColumn = self.locator.getColumnNumber()
|
||||
self.log(ContainsSystemEntity({}))
|
||||
from StringIO import StringIO
|
||||
return StringIO()
|
||||
|
||||
def skippedEntity(self, name):
|
||||
from logging import ValidDoctype
|
||||
if [e for e in self.loggedEvents if e.__class__ == ValidDoctype]:
|
||||
from htmlentitydefs import name2codepoint
|
||||
if name in name2codepoint: return
|
||||
from logging import UndefinedNamedEntity
|
||||
self.log(UndefinedNamedEntity({'value':name}))
|
||||
|
||||
def characters(self, string):
|
||||
self.lastKnownLine = self.locator.getLineNumber()
|
||||
self.lastKnownColumn = self.locator.getColumnNumber()
|
||||
for handler in iter(self.handler_stack[-1]):
|
||||
handler.characters(string)
|
||||
|
||||
def endElementNS(self, name, qname):
|
||||
self.lastKnownLine = self.locator.getLineNumber()
|
||||
self.lastKnownColumn = self.locator.getColumnNumber()
|
||||
qname, name = name
|
||||
for handler in iter(self.handler_stack[-1]):
|
||||
handler.endElementNS(name, qname)
|
||||
del self.handler_stack[-1]
|
||||
|
||||
def push(self, handlers, name, attrs, parent):
|
||||
if hasattr(handlers,'__iter__'):
|
||||
for handler in iter(handlers):
|
||||
handler.setElement(name, attrs, parent)
|
||||
handler.value=""
|
||||
handler.prevalidate()
|
||||
else:
|
||||
handlers.setElement(name, attrs, parent)
|
||||
handlers.value=""
|
||||
handlers.prevalidate()
|
||||
handlers = [handlers]
|
||||
self.handler_stack.append(handlers)
|
||||
|
||||
def log(self, event, offset=(0,0)):
|
||||
def findDuplicate(self, event):
|
||||
duplicates = [e for e in self.loggedEvents if e.__class__ == event.__class__]
|
||||
if duplicates and (event.__class__ in [NonCanonicalURI]):
|
||||
return duplicates[0]
|
||||
|
||||
for dup in duplicates:
|
||||
for k, v in event.params.items():
|
||||
if k != 'value':
|
||||
if not k in dup.params or dup.params[k] != v: break
|
||||
else:
|
||||
return dup
|
||||
|
||||
if event.params.has_key('element') and event.params['element']:
|
||||
if not isinstance(event.params['element'],tuple):
|
||||
event.params['element']=':'.join(event.params['element'].split('_', 1))
|
||||
elif event.params['element'][0]==u'http://www.w3.org/XML/1998/namespace':
|
||||
event.params['element'] = 'xml:' + event.params['element'][-1]
|
||||
if self.firstOccurrenceOnly:
|
||||
dup = findDuplicate(self, event)
|
||||
if dup:
|
||||
dup.params['msgcount'] = dup.params['msgcount'] + 1
|
||||
return
|
||||
event.params['msgcount'] = 1
|
||||
try:
|
||||
line = self.locator.getLineNumber() + offset[0]
|
||||
backupline = self.lastKnownLine
|
||||
column = (self.locator.getColumnNumber() or 0) + offset[1]
|
||||
backupcolumn = self.lastKnownColumn
|
||||
except AttributeError:
|
||||
line = backupline = column = backupcolumn = 1
|
||||
event.params['line'] = line
|
||||
event.params['backupline'] = backupline
|
||||
event.params['column'] = column
|
||||
event.params['backupcolumn'] = backupcolumn
|
||||
self.loggedEvents.append(event)
|
||||
|
||||
def error(self, exception):
|
||||
from logging import SAXError
|
||||
self.log(SAXError({'exception':str(exception)}))
|
||||
raise exception
|
||||
fatalError=error
|
||||
warning=error
|
||||
|
||||
def getFeedType(self):
|
||||
return self.feedType
|
||||
|
||||
def setFeedType(self, feedType):
|
||||
self.feedType = feedType
|
||||
|
||||
#
|
||||
# This base class for content handlers keeps track of such administrative
|
||||
# details as the parent of the current element, and delegating both log
|
||||
# and push events back up the stack. It will also concatenate up all of
|
||||
# the SAX events associated with character data into a value, handing such
|
||||
# things as CDATA and entities.
|
||||
#
|
||||
# Subclasses are expected to declare "do_name" methods for every
|
||||
# element that they support. These methods are expected to return the
|
||||
# appropriate handler for the element.
|
||||
#
|
||||
# The name of the element and the names of the children processed so
|
||||
# far are also maintained.
|
||||
#
|
||||
# Hooks are also provided for subclasses to do "prevalidation" and
|
||||
# "validation".
|
||||
#
|
||||
from logging import TYPE_RSS2
|
||||
|
||||
class validatorBase(ContentHandler):
|
||||
|
||||
def __init__(self):
|
||||
ContentHandler.__init__(self)
|
||||
self.value = ""
|
||||
self.attrs = None
|
||||
self.children = []
|
||||
self.isValid = 1
|
||||
self.name = None
|
||||
self.itunes = False
|
||||
self.namespace = {}
|
||||
|
||||
def setElement(self, name, attrs, parent):
|
||||
self.name = name
|
||||
self.attrs = attrs
|
||||
self.parent = parent
|
||||
self.dispatcher = parent.dispatcher
|
||||
self.line = self.dispatcher.locator.getLineNumber()
|
||||
self.col = self.dispatcher.locator.getColumnNumber()
|
||||
self.xmlLang = parent.xmlLang
|
||||
|
||||
if attrs and attrs.has_key((u'http://www.w3.org/XML/1998/namespace', u'base')):
|
||||
self.xmlBase=attrs.getValue((u'http://www.w3.org/XML/1998/namespace', u'base'))
|
||||
from validators import rfc3987
|
||||
self.validate_attribute((u'http://www.w3.org/XML/1998/namespace',u'base'),
|
||||
rfc3987)
|
||||
from urlparse import urljoin
|
||||
self.xmlBase = urljoin(parent.xmlBase, self.xmlBase)
|
||||
else:
|
||||
self.xmlBase = parent.xmlBase
|
||||
|
||||
return self
|
||||
|
||||
def simplename(self, name):
|
||||
if not name[0]: return name[1]
|
||||
return namespaces.get(name[0], name[0]) + ":" + name[1]
|
||||
|
||||
def namespaceFor(self, prefix):
|
||||
if self.namespace.has_key(prefix):
|
||||
return self.namespace[prefix]
|
||||
elif self.parent:
|
||||
return self.parent.namespaceFor(prefix)
|
||||
else:
|
||||
return None
|
||||
|
||||
def validate_attribute(self, name, rule):
|
||||
if not isinstance(rule,validatorBase): rule = rule()
|
||||
if isinstance(name,str): name = (None,name)
|
||||
rule.setElement(self.simplename(name), {}, self)
|
||||
rule.value=self.attrs.getValue(name)
|
||||
rule.validate()
|
||||
|
||||
def validate_required_attribute(self, name, rule):
|
||||
if self.attrs and self.attrs.has_key(name):
|
||||
self.validate_attribute(name, rule)
|
||||
else:
|
||||
from logging import MissingAttribute
|
||||
self.log(MissingAttribute({"attr": self.simplename(name)}))
|
||||
|
||||
def validate_optional_attribute(self, name, rule):
|
||||
if self.attrs and self.attrs.has_key(name):
|
||||
self.validate_attribute(name, rule)
|
||||
|
||||
def getExpectedAttrNames(self):
|
||||
None
|
||||
|
||||
def unknown_starttag(self, name, qname, attrs):
|
||||
from validators import any
|
||||
return any(self, name, qname, attrs)
|
||||
|
||||
def startElementNS(self, name, qname, attrs):
|
||||
if attrs.has_key((u'http://www.w3.org/XML/1998/namespace', u'lang')):
|
||||
self.xmlLang=attrs.getValue((u'http://www.w3.org/XML/1998/namespace', u'lang'))
|
||||
if self.xmlLang:
|
||||
from validators import iso639_validate
|
||||
iso639_validate(self.log, self.xmlLang, "xml:lang", name)
|
||||
|
||||
from validators import eater
|
||||
feedtype=self.getFeedType()
|
||||
if (not qname) and feedtype and (feedtype!=TYPE_RSS2):
|
||||
from logging import UndeterminableVocabulary
|
||||
self.log(UndeterminableVocabulary({"parent":self.name, "element":name, "namespace":'""'}))
|
||||
qname="null"
|
||||
if qname in self.dispatcher.defaultNamespaces: qname=None
|
||||
|
||||
nm_qname = near_miss(qname)
|
||||
if nearly_namespaces.has_key(nm_qname):
|
||||
prefix = nearly_namespaces[nm_qname]
|
||||
qname, name = None, prefix + "_" + name
|
||||
if prefix == 'itunes' and not self.itunes and not self.parent.itunes:
|
||||
if hasattr(self, 'setItunes'): self.setItunes(True)
|
||||
|
||||
# ensure all attribute namespaces are properly defined
|
||||
for (namespace,attr) in attrs.keys():
|
||||
if ':' in attr and not namespace:
|
||||
from logging import MissingNamespace
|
||||
self.log(MissingNamespace({"parent":self.name, "element":attr}))
|
||||
|
||||
if qname=='http://purl.org/atom/ns#':
|
||||
from logging import ObsoleteNamespace
|
||||
self.log(ObsoleteNamespace({"element":"feed"}))
|
||||
|
||||
for key, string in attrs.items():
|
||||
for c in string:
|
||||
if 0x80 <= ord(c) <= 0x9F or c == u'\ufffd':
|
||||
from validators import BadCharacters
|
||||
self.log(BadCharacters({"parent":name, "element":key[-1]}))
|
||||
|
||||
if qname:
|
||||
handler = self.unknown_starttag(name, qname, attrs)
|
||||
name="unknown_"+name
|
||||
else:
|
||||
try:
|
||||
self.child=name
|
||||
if name.startswith('dc_'):
|
||||
# handle "Qualified" Dublin Core
|
||||
handler = getattr(self, "do_" + name.replace("-","_").split('.')[0])()
|
||||
else:
|
||||
handler = getattr(self, "do_" + name.replace("-","_"))()
|
||||
except AttributeError:
|
||||
if name.find(':') != -1:
|
||||
from logging import MissingNamespace
|
||||
self.log(MissingNamespace({"parent":self.name, "element":name}))
|
||||
handler = eater()
|
||||
elif name.startswith('xhtml_'):
|
||||
from logging import MisplacedXHTMLContent
|
||||
self.log(MisplacedXHTMLContent({"parent": ':'.join(self.name.split("_",1)), "element":name}))
|
||||
handler = eater()
|
||||
else:
|
||||
from logging import UndefinedElement
|
||||
self.log(UndefinedElement({"parent": ':'.join(self.name.split("_",1)), "element":name}))
|
||||
handler = eater()
|
||||
|
||||
self.push(handler, name, attrs)
|
||||
|
||||
# MAP - always append name, even if already exists (we need this to
|
||||
# check for too many hour elements in skipHours, and it doesn't
|
||||
# hurt anything else)
|
||||
self.children.append(name)
|
||||
|
||||
def normalizeWhitespace(self):
|
||||
self.value = self.value.strip()
|
||||
|
||||
def endElementNS(self, name, qname):
|
||||
self.normalizeWhitespace()
|
||||
self.validate()
|
||||
if self.isValid and self.name:
|
||||
from validators import ValidElement
|
||||
self.log(ValidElement({"parent":self.parent.name, "element":name}))
|
||||
|
||||
def textOK(self):
|
||||
from validators import UnexpectedText
|
||||
self.log(UnexpectedText({"element":self.name,"parent":self.parent.name}))
|
||||
|
||||
def characters(self, string):
|
||||
if string.strip(): self.textOK()
|
||||
|
||||
line=column=0
|
||||
pc=' '
|
||||
for c in string:
|
||||
|
||||
# latin characters double encoded as utf-8
|
||||
if 0x80 <= ord(c) <= 0xBF:
|
||||
if 0xC2 <= ord(pc) <= 0xC3:
|
||||
try:
|
||||
string.encode('iso-8859-1').decode('utf-8')
|
||||
from validators import BadCharacters
|
||||
self.log(BadCharacters({"parent":self.parent.name, "element":self.name}), offset=(line,max(1,column-1)))
|
||||
except:
|
||||
pass
|
||||
pc = c
|
||||
|
||||
# win1252
|
||||
if 0x80 <= ord(c) <= 0x9F or c == u'\ufffd':
|
||||
from validators import BadCharacters
|
||||
self.log(BadCharacters({"parent":self.parent.name, "element":self.name}), offset=(line,column))
|
||||
column=column+1
|
||||
if ord(c) in (10,13):
|
||||
column=0
|
||||
line=line+1
|
||||
|
||||
self.value = self.value + string
|
||||
|
||||
def log(self, event, offset=(0,0)):
|
||||
if not event.params.has_key('element'):
|
||||
event.params['element'] = self.name
|
||||
self.dispatcher.log(event, offset)
|
||||
self.isValid = 0
|
||||
|
||||
def setFeedType(self, feedType):
|
||||
self.dispatcher.setFeedType(feedType)
|
||||
|
||||
def getFeedType(self):
|
||||
return self.dispatcher.getFeedType()
|
||||
|
||||
def push(self, handler, name, value):
|
||||
self.dispatcher.push(handler, name, value, self)
|
||||
|
||||
def leaf(self):
|
||||
from validators import text
|
||||
return text()
|
||||
|
||||
def prevalidate(self):
|
||||
pass
|
||||
|
||||
def validate(self):
|
||||
pass
|
30
vendor/feedvalidator/category.py
vendored
30
vendor/feedvalidator/category.py
vendored
|
@ -1,30 +0,0 @@
|
|||
"""$Id: category.py 699 2006-09-25 02:01:18Z rubys $"""
|
||||
|
||||
__author__ = "Sam Ruby <http://intertwingly.net/> and Mark Pilgrim <http://diveintomark.org/>"
|
||||
__version__ = "$Revision: 699 $"
|
||||
__date__ = "$Date: 2006-09-25 02:01:18 +0000 (Mon, 25 Sep 2006) $"
|
||||
__copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim"
|
||||
|
||||
from base import validatorBase
|
||||
from validators import *
|
||||
|
||||
#
|
||||
# author element.
|
||||
#
|
||||
class category(validatorBase, rfc3987_full, nonhtml):
|
||||
def getExpectedAttrNames(self):
|
||||
return [(None,u'term'),(None,u'scheme'),(None,u'label')]
|
||||
|
||||
def prevalidate(self):
|
||||
self.children.append(True) # force warnings about "mixed" content
|
||||
|
||||
if not self.attrs.has_key((None,"term")):
|
||||
self.log(MissingAttribute({"parent":self.parent.name, "element":self.name, "attr":"term"}))
|
||||
|
||||
if self.attrs.has_key((None,"scheme")):
|
||||
self.value=self.attrs.getValue((None,"scheme"))
|
||||
rfc3987_full.validate(self, extraParams={"element": "scheme"})
|
||||
|
||||
if self.attrs.has_key((None,"label")):
|
||||
self.value=self.attrs.getValue((None,"label"))
|
||||
nonhtml.validate(self)
|
20
vendor/feedvalidator/cf.py
vendored
20
vendor/feedvalidator/cf.py
vendored
|
@ -1,20 +0,0 @@
|
|||
# http://msdn.microsoft.com/XML/rss/sle/default.aspx
|
||||
|
||||
from base import validatorBase
|
||||
from validators import eater, text
|
||||
|
||||
class sort(validatorBase):
|
||||
def getExpectedAttrNames(self):
|
||||
return [(None,u'data-type'),(None,u'default'),(None,u'element'),(None, u'label'),(None,u'ns')]
|
||||
|
||||
class group(validatorBase):
|
||||
def getExpectedAttrNames(self):
|
||||
return [(None,u'element'),(None, u'label'),(None,u'ns')]
|
||||
|
||||
class listinfo(validatorBase):
|
||||
def do_cf_sort(self):
|
||||
return sort()
|
||||
def do_cf_group(self):
|
||||
return group()
|
||||
|
||||
class treatAs(text): pass
|
279
vendor/feedvalidator/channel.py
vendored
279
vendor/feedvalidator/channel.py
vendored
|
@ -1,279 +0,0 @@
|
|||
"""$Id: channel.py 711 2006-10-25 00:43:41Z rubys $"""
|
||||
|
||||
__author__ = "Sam Ruby <http://intertwingly.net/> and Mark Pilgrim <http://diveintomark.org/>"
|
||||
__version__ = "$Revision: 711 $"
|
||||
__date__ = "$Date: 2006-10-25 00:43:41 +0000 (Wed, 25 Oct 2006) $"
|
||||
__copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim"
|
||||
|
||||
from base import validatorBase
|
||||
from logging import *
|
||||
from validators import *
|
||||
from itunes import itunes_channel
|
||||
from extension import *
|
||||
|
||||
#
|
||||
# channel element.
|
||||
#
|
||||
class channel(validatorBase, rfc2396, extension_channel, itunes_channel):
|
||||
def __init__(self):
|
||||
self.link=None
|
||||
validatorBase.__init__(self)
|
||||
def validate(self):
|
||||
if not "description" in self.children:
|
||||
self.log(MissingDescription({"parent":self.name,"element":"description"}))
|
||||
if not "link" in self.children:
|
||||
self.log(MissingLink({"parent":self.name, "element":"link"}))
|
||||
if not "title" in self.children:
|
||||
self.log(MissingTitle({"parent":self.name, "element":"title"}))
|
||||
if not "dc_language" in self.children and not "language" in self.children:
|
||||
if not self.xmlLang:
|
||||
self.log(MissingDCLanguage({"parent":self.name, "element":"language"}))
|
||||
if self.children.count("image") > 1:
|
||||
self.log(DuplicateElement({"parent":self.name, "element":"image"}))
|
||||
if self.children.count("textInput") > 1:
|
||||
self.log(DuplicateElement({"parent":self.name, "element":"textInput"}))
|
||||
if self.children.count("skipHours") > 1:
|
||||
self.log(DuplicateElement({"parent":self.name, "element":"skipHours"}))
|
||||
if self.children.count("skipDays") > 1:
|
||||
self.log(DuplicateElement({"parent":self.name, "element":"skipDays"}))
|
||||
if self.attrs.has_key((rdfNS,"about")):
|
||||
self.value = self.attrs.getValue((rdfNS, "about"))
|
||||
rfc2396.validate(self, extraParams={"attr": "rdf:about"})
|
||||
if not "items" in self.children:
|
||||
self.log(MissingElement({"parent":self.name, "element":"items"}))
|
||||
|
||||
if self.itunes: itunes_channel.validate(self)
|
||||
|
||||
def do_image(self):
|
||||
from image import image
|
||||
return image(), noduplicates()
|
||||
|
||||
def do_textInput(self):
|
||||
from textInput import textInput
|
||||
return textInput(), noduplicates()
|
||||
|
||||
def do_textinput(self):
|
||||
if not self.attrs.has_key((rdfNS,"about")):
|
||||
# optimize for RSS 2.0. If it is not valid RDF, assume that it is
|
||||
# a simple misspelling (in other words, the error message will be
|
||||
# less than helpful on RSS 1.0 feeds.
|
||||
self.log(UndefinedElement({"parent":self.name, "element":"textinput"}))
|
||||
return eater(), noduplicates()
|
||||
|
||||
def do_link(self):
|
||||
return link(), noduplicates()
|
||||
|
||||
def do_title(self):
|
||||
return nonhtml(), noduplicates(), nonblank()
|
||||
|
||||
def do_description(self):
|
||||
return nonhtml(), noduplicates()
|
||||
|
||||
def do_blink(self):
|
||||
return blink(), noduplicates()
|
||||
|
||||
def do_atom_author(self):
|
||||
from author import author
|
||||
return author()
|
||||
|
||||
def do_atom_category(self):
|
||||
from category import category
|
||||
return category()
|
||||
|
||||
def do_atom_contributor(self):
|
||||
from author import author
|
||||
return author()
|
||||
|
||||
def do_atom_generator(self):
|
||||
from generator import generator
|
||||
return generator(), nonblank(), noduplicates()
|
||||
|
||||
def do_atom_id(self):
|
||||
return rfc2396_full(), noduplicates()
|
||||
|
||||
def do_atom_icon(self):
|
||||
return nonblank(), rfc2396(), noduplicates()
|
||||
|
||||
def do_atom_link(self):
|
||||
from link import link
|
||||
return link()
|
||||
|
||||
def do_atom_logo(self):
|
||||
return nonblank(), rfc2396(), noduplicates()
|
||||
|
||||
def do_atom_title(self):
|
||||
from content import textConstruct
|
||||
return textConstruct(), noduplicates()
|
||||
|
||||
def do_atom_subtitle(self):
|
||||
from content import textConstruct
|
||||
return textConstruct(), noduplicates()
|
||||
|
||||
def do_atom_rights(self):
|
||||
from content import textConstruct
|
||||
return textConstruct(), noduplicates()
|
||||
|
||||
def do_atom_updated(self):
|
||||
return rfc3339(), noduplicates()
|
||||
|
||||
def do_dc_creator(self):
|
||||
if "managingEditor" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"managingEditor", "ext":"dc:creator"}))
|
||||
return text() # duplicates allowed
|
||||
|
||||
def do_dc_subject(self):
|
||||
if "category" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"category", "ext":"dc:subject"}))
|
||||
return text() # duplicates allowed
|
||||
|
||||
def do_dc_date(self):
|
||||
if "pubDate" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"pubDate", "ext":"dc:date"}))
|
||||
return w3cdtf(), noduplicates()
|
||||
|
||||
def do_cc_license(self):
|
||||
if "creativeCommons_license" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"creativeCommons:license", "ext":"cc:license"}))
|
||||
return eater()
|
||||
|
||||
def do_creativeCommons_license(self):
|
||||
if "cc_license" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"creativeCommons:license", "ext":"cc:license"}))
|
||||
return rfc2396_full()
|
||||
|
||||
class rss20Channel(channel):
|
||||
def do_item(self):
|
||||
from item import rss20Item
|
||||
return rss20Item()
|
||||
|
||||
def do_category(self):
|
||||
return category()
|
||||
|
||||
def do_cloud(self):
|
||||
return cloud(), noduplicates()
|
||||
|
||||
do_rating = validatorBase.leaf # TODO test cases?!?
|
||||
|
||||
def do_ttl(self):
|
||||
return positiveInteger(), nonblank(), noduplicates()
|
||||
|
||||
def do_docs(self):
|
||||
return rfc2396_full(), noduplicates()
|
||||
|
||||
def do_generator(self):
|
||||
if "admin_generatorAgent" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"generator", "ext":"admin:generatorAgent"}))
|
||||
return text(), noduplicates()
|
||||
|
||||
def do_pubDate(self):
|
||||
if "dc_date" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"pubDate", "ext":"dc:date"}))
|
||||
return rfc822(), noduplicates()
|
||||
|
||||
def do_managingEditor(self):
|
||||
if "dc_creator" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"managingEditor", "ext":"dc:creator"}))
|
||||
return email(), noduplicates()
|
||||
|
||||
def do_webMaster(self):
|
||||
if "dc_publisher" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"webMaster", "ext":"dc:publisher"}))
|
||||
return email(), noduplicates()
|
||||
|
||||
def do_language(self):
|
||||
if "dc_language" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"language", "ext":"dc:language"}))
|
||||
return iso639(), noduplicates()
|
||||
|
||||
def do_copyright(self):
|
||||
if "dc_rights" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"copyright", "ext":"dc:rights"}))
|
||||
return nonhtml(), noduplicates()
|
||||
|
||||
def do_lastBuildDate(self):
|
||||
if "dcterms_modified" in self.children:
|
||||
self.log(DuplicateSemantics({"core":"lastBuildDate", "ext":"dcterms:modified"}))
|
||||
return rfc822(), noduplicates()
|
||||
|
||||
def do_skipHours(self):
|
||||
from skipHours import skipHours
|
||||
return skipHours()
|
||||
|
||||
def do_skipDays(self):
|
||||
from skipDays import skipDays
|
||||
return skipDays()
|
||||
|
||||
class rss10Channel(channel):
|
||||
def getExpectedAttrNames(self):
|
||||
return [(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#', u'about'),
|
||||
(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#', u'about')]
|
||||
|
||||
def prevalidate(self):
|
||||
if self.attrs.has_key((rdfNS,"about")):
|
||||
if not "abouts" in self.dispatcher.__dict__:
|
||||
self.dispatcher.__dict__["abouts"] = []
|
||||
self.dispatcher.__dict__["abouts"].append(self.attrs[(rdfNS,"about")])
|
||||
|
||||
def do_items(self): # this actually should be from the rss1.0 ns
|
||||
if not self.attrs.has_key((rdfNS,"about")):
|
||||
self.log(MissingAttribute({"parent":self.name, "element":self.name, "attr":"rdf:about"}))
|
||||
from item import items
|
||||
return items(), noduplicates()
|
||||
|
||||
def do_rdfs_label(self):
|
||||
return text()
|
||||
|
||||
def do_rdfs_comment(self):
|
||||
return text()
|
||||
|
||||
|
||||
class link(rfc2396_full):
|
||||
def validate(self):
|
||||
self.parent.link = self.value
|
||||
rfc2396_full.validate(self)
|
||||
|
||||
class blink(text):
|
||||
def validate(self):
|
||||
self.log(NoBlink({}))
|
||||
|
||||
class category(nonhtml):
|
||||
def getExpectedAttrNames(self):
|
||||
return [(None, u'domain')]
|
||||
|
||||
class cloud(validatorBase):
|
||||
def getExpectedAttrNames(self):
|
||||
return [(None, u'domain'), (None, u'path'), (None, u'registerProcedure'),
|
||||
(None, u'protocol'), (None, u'port')]
|
||||
def prevalidate(self):
|
||||
if (None, 'domain') not in self.attrs.getNames():
|
||||
self.log(MissingAttribute({"parent":self.parent.name, "element":self.name, "attr":"domain"}))
|
||||
else:
|
||||
self.log(ValidCloud({"parent":self.parent.name, "element":self.name, "attr":"domain"}))
|
||||
|
||||
try:
|
||||
if int(self.attrs.getValue((None, 'port'))) <= 0:
|
||||
self.log(InvalidIntegerAttribute({"parent":self.parent.name, "element":self.name, "attr":'port'}))
|
||||
else:
|
||||
self.log(ValidCloud({"parent":self.parent.name, "element":self.name, "attr":'port'}))
|
||||
except KeyError:
|
||||
self.log(MissingAttribute({"parent":self.parent.name, "element":self.name, "attr":'port'}))
|
||||
except ValueError:
|
||||
self.log(InvalidIntegerAttribute({"parent":self.parent.name, "element":self.name, "attr":'port'}))
|
||||
|
||||
if (None, 'path') not in self.attrs.getNames():
|
||||
self.log(MissingAttribute({"parent":self.parent.name, "element":self.name, "attr":"path"}))
|
||||
else:
|
||||
self.log(ValidCloud({"parent":self.parent.name, "element":self.name, "attr":"path"}))
|
||||
|
||||
if (None, 'registerProcedure') not in self.attrs.getNames():
|
||||
self.log(MissingAttribute({"parent":self.parent.name, "element":self.name, "attr":"registerProcedure"}))
|
||||
else:
|
||||
self.log(ValidCloud({"parent":self.parent.name, "element":self.name, "attr":"registerProcedure"}))
|
||||
|
||||
if (None, 'protocol') not in self.attrs.getNames():
|
||||
self.log(MissingAttribute({"parent":self.parent.name, "element":self.name, "attr":"protocol"}))
|
||||
else:
|
||||
self.log(ValidCloud({"parent":self.parent.name, "element":self.name, "attr":"protocol"}))
|
||||
## TODO - is there a list of accepted protocols for this thing?
|
||||
|
||||
return validatorBase.prevalidate(self)
|
37
vendor/feedvalidator/compatibility.py
vendored
37
vendor/feedvalidator/compatibility.py
vendored
|
@ -1,37 +0,0 @@
|
|||
"""$Id: compatibility.py 699 2006-09-25 02:01:18Z rubys $"""
|
||||
|
||||
__author__ = "Sam Ruby <http://intertwingly.net/> and Mark Pilgrim <http://diveintomark.org/>"
|
||||
__version__ = "$Revision: 699 $"
|
||||
__date__ = "$Date: 2006-09-25 02:01:18 +0000 (Mon, 25 Sep 2006) $"
|
||||
__copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim"
|
||||
|
||||
from logging import *
|
||||
|
||||
def _must(event):
|
||||
return isinstance(event, Error)
|
||||
|
||||
def _should(event):
|
||||
return isinstance(event, Warning)
|
||||
|
||||
def _may(event):
|
||||
return isinstance(event, Info)
|
||||
|
||||
def A(events):
|
||||
return [event for event in events if _must(event)]
|
||||
|
||||
def AA(events):
|
||||
return [event for event in events if _must(event) or _should(event)]
|
||||
|
||||
def AAA(events):
|
||||
return [event for event in events if _must(event) or _should(event) or _may(event)]
|
||||
|
||||
def AAAA(events):
|
||||
return events
|
||||
|
||||
def analyze(events, rawdata):
|
||||
for event in events:
|
||||
if isinstance(event,UndefinedElement):
|
||||
if event.params['parent'] == 'root':
|
||||
if event.params['element'].lower() in ['html','xhtml:html']:
|
||||
return "html"
|
||||
return None
|
151
vendor/feedvalidator/content.py
vendored
151
vendor/feedvalidator/content.py
vendored
|
@ -1,151 +0,0 @@
|
|||
"""$Id: content.py 699 2006-09-25 02:01:18Z rubys $"""
|
||||
|
||||
__author__ = "Sam Ruby <http://intertwingly.net/> and Mark Pilgrim <http://diveintomark.org/>"
|
||||
__version__ = "$Revision: 699 $"
|
||||
__date__ = "$Date: 2006-09-25 02:01:18 +0000 (Mon, 25 Sep 2006) $"
|
||||
__copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim"
|
||||
|
||||
from base import validatorBase
|
||||
from validators import *
|
||||
from logging import *
|
||||
#
|
||||
# item element.
|
||||
#
|
||||
class textConstruct(validatorBase,rfc2396,nonhtml):
|
||||
from validators import mime_re
|
||||
import re
|
||||
|
||||
def getExpectedAttrNames(self):
|
||||
return [(None, u'type'),(None, u'src')]
|
||||
|
||||
def normalizeWhitespace(self):
|
||||
pass
|
||||
|
||||
def maptype(self):
|
||||
if self.type.find('/') > -1:
|
||||
self.log(InvalidTextType({"parent":self.parent.name, "element":self.name, "attr":"type", "value":self.type}))
|
||||
|
||||
def prevalidate(self):
|
||||
if self.attrs.has_key((None,"src")):
|
||||
self.type=''
|
||||
else:
|
||||
self.type='text'
|
||||
if self.getFeedType() == TYPE_RSS2 and self.name != 'atom_summary':
|
||||
self.log(DuplicateDescriptionSemantics({"element":self.name}))
|
||||
|
||||
if self.attrs.has_key((None,"type")):
|
||||
self.type=self.attrs.getValue((None,"type"))
|
||||
if not self.type:
|
||||
self.log(AttrNotBlank({"parent":self.parent.name, "element":self.name, "attr":"type"}))
|
||||
|
||||
self.maptype()
|
||||
|
||||
if self.attrs.has_key((None,"src")):
|
||||
self.children.append(True) # force warnings about "mixed" content
|
||||
self.value=self.attrs.getValue((None,"src"))
|
||||
rfc2396.validate(self, errorClass=InvalidURIAttribute, extraParams={"attr": "src"})
|
||||
self.value=""
|
||||
|
||||
if not self.attrs.has_key((None,"type")):
|
||||
self.log(MissingTypeAttr({"parent":self.parent.name, "element":self.name, "attr":"type"}))
|
||||
|
||||
if self.type in ['text','html','xhtml'] and not self.attrs.has_key((None,"src")):
|
||||
pass
|
||||
elif self.type and not self.mime_re.match(self.type):
|
||||
self.log(InvalidMIMEType({"parent":self.parent.name, "element":self.name, "attr":"type", "value":self.type}))
|
||||
else:
|
||||
self.log(ValidMIMEAttribute({"parent":self.parent.name, "element":self.name, "attr":"type", "value":self.type}))
|
||||
|
||||
if not self.xmlLang:
|
||||
self.log(MissingDCLanguage({"parent":self.name, "element":"xml:lang"}))
|
||||
|
||||
def validate(self):
|
||||
if self.type in ['text','xhtml']:
|
||||
if self.type=='xhtml':
|
||||
nonhtml.validate(self, NotInline)
|
||||
else:
|
||||
nonhtml.validate(self, ContainsUndeclaredHTML)
|
||||
else:
|
||||
if self.type.find('/') > -1 and not (
|
||||
self.type.endswith('+xml') or self.type.endswith('/xml') or
|
||||
self.type.startswith('text/')):
|
||||
import base64
|
||||
try:
|
||||
self.value=base64.decodestring(self.value)
|
||||
if self.type.endswith('/html'): self.type='html'
|
||||
except:
|
||||
self.log(NotBase64({"parent":self.parent.name, "element":self.name,"value":self.value}))
|
||||
|
||||
if self.type=='html' or self.type.endswith("/html"):
|
||||
self.validateSafe(self.value)
|
||||
|
||||
if self.type.endswith("/html"):
|
||||
if self.value.find("<html")<0 and not self.attrs.has_key((None,"src")):
|
||||
self.log(HtmlFragment({"parent":self.parent.name, "element":self.name,"value":self.value, "type":self.type}))
|
||||
else:
|
||||
nonhtml.validate(self, ContainsUndeclaredHTML)
|
||||
|
||||
if not self.value and len(self.children)==0 and not self.attrs.has_key((None,"src")):
|
||||
self.log(NotBlank({"parent":self.parent.name, "element":self.name}))
|
||||
|
||||
def textOK(self):
|
||||
if self.children: validatorBase.textOK(self)
|
||||
|
||||
def characters(self, string):
|
||||
for c in string:
|
||||
if 0x80 <= ord(c) <= 0x9F or c == u'\ufffd':
|
||||
from validators import BadCharacters
|
||||
self.log(BadCharacters({"parent":self.parent.name, "element":self.name}))
|
||||
if (self.type=='xhtml') and string.strip() and not self.value.strip():
|
||||
self.log(MissingXhtmlDiv({"parent":self.parent.name, "element":self.name}))
|
||||
validatorBase.characters(self,string)
|
||||
|
||||
def startElementNS(self, name, qname, attrs):
|
||||
if (self.type<>'xhtml') and not (
|
||||
self.type.endswith('+xml') or self.type.endswith('/xml')):
|
||||
self.log(UndefinedElement({"parent":self.name, "element":name}))
|
||||
|
||||
if self.type=="xhtml":
|
||||
if name<>'div' and not self.value.strip():
|
||||
self.log(MissingXhtmlDiv({"parent":self.parent.name, "element":self.name}))
|
||||
elif qname not in ["http://www.w3.org/1999/xhtml"]:
|
||||
self.log(NotHtml({"parent":self.parent.name, "element":self.name, "message":"unexpected namespace: %s" % qname}))
|
||||
|
||||
if self.type=="application/xhtml+xml":
|
||||
if name<>'html':
|
||||
self.log(HtmlFragment({"parent":self.parent.name, "element":self.name,"value":self.value, "type":self.type}))
|
||||
elif qname not in ["http://www.w3.org/1999/xhtml"]:
|
||||
self.log(NotHtml({"parent":self.parent.name, "element":self.name, "message":"unexpected namespace: %s" % qname}))
|
||||
|
||||
if self.attrs.has_key((None,"mode")):
|
||||
if self.attrs.getValue((None,"mode")) == 'escaped':
|
||||
self.log(NotEscaped({"parent":self.parent.name, "element":self.name}))
|
||||
|
||||
if name=="div" and qname=="http://www.w3.org/1999/xhtml":
|
||||
handler=diveater()
|
||||
else:
|
||||
handler=eater()
|
||||
self.children.append(handler)
|
||||
self.push(handler, name, attrs)
|
||||
|
||||
# treat xhtml:div as part of the content for purposes of detecting escaped html
|
||||
class diveater(eater):
|
||||
def __init__(self):
|
||||
eater.__init__(self)
|
||||
self.mixed = False
|
||||
def textOK(self):
|
||||
pass
|
||||
def characters(self, string):
|
||||
validatorBase.characters(self, string)
|
||||
def startElementNS(self, name, qname, attrs):
|
||||
if not qname:
|
||||
self.log(MissingNamespace({"parent":"xhtml:div", "element":name}))
|
||||
self.mixed = True
|
||||
eater.startElementNS(self, name, qname, attrs)
|
||||
def validate(self):
|
||||
if not self.mixed: self.parent.value += self.value
|
||||
|
||||
class content(textConstruct):
|
||||
def maptype(self):
|
||||
if self.type == 'multipart/alternative':
|
||||
self.log(InvalidMIMEType({"parent":self.parent.name, "element":self.name, "attr":"type", "value":self.type}))
|
50
vendor/feedvalidator/demo/.htaccess
vendored
50
vendor/feedvalidator/demo/.htaccess
vendored
|
@ -1,50 +0,0 @@
|
|||
Options +ExecCGI -MultiViews
|
||||
AddHandler cgi-script .cgi
|
||||
AddType image/x-icon ico
|
||||
|
||||
RewriteRule ^check$ check.cgi
|
||||
|
||||
DirectoryIndex index.html check.cgi
|
||||
|
||||
# MAP - bad bots are killing the server (everybody links to their validation results and the bots dutifully crawl it)
|
||||
RewriteEngine on
|
||||
RewriteCond %{HTTP_USER_AGENT} BecomeBot [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} Crawler [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} FatBot [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} Feed24 [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} Gigabot [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} Googlebot [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} htdig [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} HttpClient
|
||||
RewriteCond %{HTTP_USER_AGENT} HTTrack [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} IQSearch [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} msnbot [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} NaverBot [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} OmniExplorer [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} SietsCrawler [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} Thunderbird [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} TurnitinBot [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} User-Agent [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} Yahoo!.Slurp [OR]
|
||||
RewriteRule check - [F,L]
|
||||
|
||||
# fastcgi
|
||||
RewriteCond /home/rubys/public_html/fvstat/status -f
|
||||
RewriteRule check.cgi(.*)$ http://localhost:8080/rubys/feedvalidator.org/$1 [P]
|
||||
|
||||
<Files check.cgi>
|
||||
Deny from feeds01.archive.org
|
||||
Deny from feedvalidator.org
|
||||
Deny from new.getfilesfast.com
|
||||
Deny from gnat.yodlee.com
|
||||
Deny from master.macworld.com
|
||||
Deny from 62.244.248.104
|
||||
Deny from 207.97.204.219
|
||||
Deny from ik63025.ikexpress.com
|
||||
Deny from 65-86-180-70.client.dsl.net
|
||||
Deny from vanadium.sabren.com
|
||||
</Files>
|
||||
|
||||
<Files config.py>
|
||||
ForceType text/plain
|
||||
</Files>
|
26
vendor/feedvalidator/demo/LICENSE
vendored
26
vendor/feedvalidator/demo/LICENSE
vendored
|
@ -1,26 +0,0 @@
|
|||
The Feed Validator (includig all code, tests, and documentation) is released
|
||||
under the following license:
|
||||
|
||||
----- begin license block -----
|
||||
|
||||
Copyright (c) 2002-2006, Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
----- end license block -----
|
9
vendor/feedvalidator/demo/README
vendored
9
vendor/feedvalidator/demo/README
vendored
|
@ -1,9 +0,0 @@
|
|||
Some tests, and some functionality, will not be enabled unless a full set
|
||||
of 32-bit character encodings are available through Python.
|
||||
|
||||
The package 'iconvcodec' provides the necessary codecs, if your underlying
|
||||
operating system supports them. Its web page is at
|
||||
<http://cjkpython.i18n.org/#iconvcodec>, and a range of packages are
|
||||
provided.
|
||||
|
||||
Python 2.3.x is required, for its Unicode support.
|
76
vendor/feedvalidator/demo/RSSValidator.wsdl
vendored
76
vendor/feedvalidator/demo/RSSValidator.wsdl
vendored
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<definitions
|
||||
targetNamespace="http://feedvalidator.org/"
|
||||
xmlns:validator="http://feedvalidator.org/"
|
||||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://schemas.xmlsoap.org/wsdl/">
|
||||
|
||||
<types>
|
||||
<xsd:schema elementFormDefault="qualified"
|
||||
targetNamespace="http://feedvalidator.org/">
|
||||
|
||||
<xsd:complexType name="Request">
|
||||
<xsd:sequence>
|
||||
<xsd:any namespace="##other"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="Message">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="level" type="xsd:string"/>
|
||||
<xsd:element name="type" type="xsd:string"/>
|
||||
<xsd:element name="line" type="xsd:string"/>
|
||||
<xsd:element name="column" type="xsd:string"/>
|
||||
<xsd:element name="msgcount" type="xsd:string"/>
|
||||
<xsd:element name="text" type="xsd:string"/>
|
||||
<xsd:any minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="Response">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="message" type="validator:Message"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="request" type="validator:Request"/>
|
||||
<xsd:element name="response" type="validator:Response"/>
|
||||
</xsd:schema>
|
||||
</types>
|
||||
|
||||
<message name="validateIn">
|
||||
<part name="request" element="validator:request" />
|
||||
</message>
|
||||
<message name="validateOut">
|
||||
<part name="response" element="validator:response" />
|
||||
</message>
|
||||
|
||||
<portType name="RSSValidatorSoap">
|
||||
<operation name="validate">
|
||||
<input message="validator:validateIn" />
|
||||
<output message="validator:validateOut" />
|
||||
</operation>
|
||||
</portType>
|
||||
|
||||
<binding name="soap" type="validator:RSSValidatorSoap">
|
||||
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
|
||||
style="document" />
|
||||
<operation name="validate">
|
||||
<soap:operation soapAction="urn:validate" style="document" />
|
||||
<input>
|
||||
<soap:body use="literal" />
|
||||
</input>
|
||||
<output>
|
||||
<soap:body use="literal" />
|
||||
</output>
|
||||
</operation>
|
||||
</binding>
|
||||
|
||||
<service name="RSSValidator">
|
||||
<port name="RSSValidatorSoap" binding="validator:soap">
|
||||
<soap:address location="http://feedvalidator.org/" />
|
||||
</port>
|
||||
</service>
|
||||
</definitions>
|
113
vendor/feedvalidator/demo/about.html
vendored
113
vendor/feedvalidator/demo/about.html
vendored
|
@ -1,113 +0,0 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>About the Feed Validator</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<style type="text/css" media="screen">@import "css/common.css";
|
||||
@import "css/documentation.css";</style>
|
||||
<script type="text/javascript"><!-- --></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="logo">
|
||||
<h1><a href="/"><span id="feed"><span id="f">F</span><span id="e1">E</span><span id="e2">E</span></span><span id="d">D</span> Validator</a></h1>
|
||||
<p>About</p>
|
||||
<a class="skip" href="#startnavigation">Jump to navigation</a>
|
||||
</div> <!--logo-->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<p>On this page:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="#what">What is this?</a></li>
|
||||
<li><a href="#why">Why a validator?</a></li>
|
||||
<li><a href="#how">What does it validate?</a></li>
|
||||
<li><a href="#who">Who wrote it?</a></li>
|
||||
<li><a href="#where">Can I run it locally?</a></li>
|
||||
<li><a href="#when">Can I tell you something?</a></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="what">What is this?</h2>
|
||||
|
||||
<p>This is a validator for syndicated feeds. It works with RSS 0.90, 0.91, 0.92, 0.93, 0.94, 1.0, 1.1, and 2.0. It also validates Atom feeds.</p>
|
||||
|
||||
<p>To use it, simply enter the address of your feed and click Validate. If the validator finds any problems in your feed, it will give you messages for each type of problem and highlight where the problem first occurs in your feed. If you're unsure what a message means, click the "help" link next to the message for a fuller explanation.</p>
|
||||
|
||||
<h2 id="why">Why a validator?</h2>
|
||||
|
||||
<p>Despite its relatively simple nature, RSS is poorly implemented by many tools. This validator is an attempt to codify the specification (literally, to translate it into code) to make it easier to know when you're producing RSS correctly, and to help you fix it when you're not.</p>
|
||||
|
||||
<p>The validator also supports the IETF standard Atom format for syndicated feeds. Early adopters who wish to support Atom should use the validator to make sure they generate it properly from day 1.</p>
|
||||
|
||||
<p>There are validators for other web technologies, such as <a href="http://validator.w3.org/">HTML</a>, <a href="http://jigsaw.w3.org/css-validator/">CSS</a>, and <a href="http://webxact.watchfire.com/">accessibility guidelines</a>, and these have all proven quite popular. As personal news syndication is becoming more widespread, we saw a need for a comprehensive but easy-to-use validator for syndicated feeds.</p>
|
||||
|
||||
<h2 id="how">What does it validate?</h2>
|
||||
|
||||
<p>It validates RSS feeds against the rules defined in the <a href="/docs/rss2.html">RSS 2.0 specification</a>. It also validates elements of commonly used namespaces:</p>
|
||||
|
||||
<ul>
|
||||
<li>blogChannel</li>
|
||||
<li>Dublin Core</li>
|
||||
<li>itunes</li>
|
||||
<li>mod_admin</li>
|
||||
<li>mod_syndication</li>
|
||||
<li>mod_content (<code>content:encoded</code> only)</li>
|
||||
</ul>
|
||||
|
||||
<p>For Atom feeds, it validates against <a href="http://www.ietf.org/rfc/rfc4287">RFC 4287</a>, which describes version 1.0 of the Atom feed format.</p>
|
||||
|
||||
<p>The <a href="/docs/">documentation index</a> lists all the error messages that the validator produces. You can also download the entire test suite that was used to create the validator (see below).</p>
|
||||
|
||||
<h2 id="who">Who wrote it?</h2>
|
||||
|
||||
<p>The validator was conceived and designed by <a href="http://diveintomark.org/">Mark Pilgrim</a>, who also wrote most of the test cases and designed the web front end. Much of the actual back end coding was done by <a href="http://intertwingly.net/blog/">Sam Ruby</a>.</p>
|
||||
|
||||
<a name="opensource" id="opensource"></a>
|
||||
<h2 id="where">Can I run it locally?</h2>
|
||||
|
||||
<p>Yes. The validator is open source, written in Python, and distributed under the <a href="LICENSE">MIT license</a>. To run it, you will need <a href="http://python.org/">Python 2.3</a> or later, and an XML parser. Most Python distributions include a minimal XML parser which will work just fine. Mac OS X 10.2 users should install <a href="http://sourceforge.net/projects/pyxml/">PyXML</a>.</p>
|
||||
|
||||
<p>You can find more information in our convenient <a href="docs/howto/install_and_run.html">HowTo</a>.</p>
|
||||
|
||||
<h2 id="when">Can I tell you something?</h2>
|
||||
|
||||
<p>Sure! The best way to provide feedback on the validator is on the <a href="http://lists.sourceforge.net/lists/listinfo/feedvalidator-users">Sourceforge mailing list</a>.</p>
|
||||
</div><!--main-->
|
||||
|
||||
<div class="centered">
|
||||
<a name="startnavigation" id="startnavigation"></a>
|
||||
<div class="navbarWrapper">
|
||||
<div class="navbarContent">
|
||||
<img class="borderTL" src="/images/borderTL.gif" alt="" width="14" height="14" />
|
||||
<img class="borderTR" src="/images/borderTR.gif" alt="" width="14" height="14" />
|
||||
|
||||
<p>
|
||||
<a href="/">Home</a> ·
|
||||
<a href="about.html">About</a> ·
|
||||
<a href="news/">News</a> ·
|
||||
<a href="docs/">Docs</a> ·
|
||||
<a href="terms.html">Terms</a>
|
||||
</p>
|
||||
|
||||
<div class="roundedCornerSpacer"> </div>
|
||||
</div><!-- .content -->
|
||||
<div class="bottomCorners">
|
||||
<img class="borderBL" src="/images/borderBL.gif" alt="" width="14" height="14" />
|
||||
<img class="borderBR" src="/images/borderBR.gif" alt="" width="14" height="14" />
|
||||
</div><!-- .bottomCorners -->
|
||||
</div><!-- .contentWrapper -->
|
||||
</div><!-- .centered -->
|
||||
|
||||
<div class="centered">
|
||||
<address>Copyright © 2002-6
|
||||
<a href="http://www.intertwingly.net/blog/">Sam Ruby</a>,
|
||||
<a href="http://diveintomark.org/">Mark Pilgrim</a>,
|
||||
<a href="http://www.kafsemo.org/">Joseph Walton</a>, and
|
||||
<a href="http://philringnalda.com/">Phil Ringnalda</a>
|
||||
</address>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
83
vendor/feedvalidator/demo/alt-banners.html
vendored
83
vendor/feedvalidator/demo/alt-banners.html
vendored
|
@ -1,83 +0,0 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>Feed Validator: alternate banners</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<style type="text/css" media="screen">@import "css/common.css";
|
||||
@import "css/documentation.css";</style>
|
||||
<script type="text/javascript"><!-- --></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="logo">
|
||||
<h1><a href="/"><span id="feed"><span id="f">F</span><span id="e1">E</span><span id="e2">E</span></span><span id="d">D</span> Validator</a></h1>
|
||||
<p>Alternate banners</p>
|
||||
<a class="skip" href="#startnavigation">Jump to navigation</a>
|
||||
</div> <!--logo-->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h2>Alternate "Valid RSS" banners</h2>
|
||||
|
||||
<p>If the default "valid RSS" banner is not your style, you can use any of these, or anything else you design, or nothing at all. The fact that you care enough to validate your feed is the important part; how you advertise it is up to you.</p>
|
||||
|
||||
<p style="line-height:300%">
|
||||
<img alt="Brockman Bulger's entry" title="by Brockman Bulger" src="/images/valid-rss-bbulger.png" width="88" height="31" />
|
||||
<img alt="Dylan Parker's entry #2" title="by Dylan Parker" src="/images/valid-rss-dylan2.gif" width="88" height="31" />
|
||||
<img alt="Neil Lee's entry with white background" title="by Neil Lee" src="/images/valid-rss-white-neil.gif" width="88" height="31" />
|
||||
<img alt="Dougal Campbell's entry with white background" title="by Dougal Campbell" src="/images/valid-rss-white-dougal.gif" width="88" height="31" />
|
||||
<img alt="Robert Guertin's entry" title="by Robert Guertin" src="/images/valid-rss-robert.jpg" width="88" height="31" />
|
||||
<img alt="Jon Wiley's entry" title="by Jon Wiley" src="/images/valid-rss-jon-wiley.gif" width="88" height="31" />
|
||||
<img alt="Jonathon Delacour's entry" title="by Jonathon Delacour" src="/images/valid-rss-jonathan.gif" width="88" height="31" />
|
||||
<img alt="Lee O'Mara's entry" title="by Lee O'Mara" src="/images/valid-rss-lee.gif" width="88" height="31" />
|
||||
<img alt="Aaron Swartz's entry" title="by Aaron Swartz" src="/images/valid-rss-aaron.png" width="88" height="31" />
|
||||
<img alt="Dylan Parker's entry #1" title="by Dylan Parker" src="/images/valid-rss-dylan1.gif" width="88" height="31" />
|
||||
<img alt="Shelley Powers' entry" title="by Shelley Powers" src="/images/valid-rss-shelley.gif" width="88" height="31" />
|
||||
<img alt="Walt Dickinson's entry with orange background" title="by Walt Dickinson" src="/images/valid-rss-orange-walt.gif" width="88" height="31" />
|
||||
<img alt="Walt Dickinson's entry with red background" title="by Walt Dickinson" src="/images/valid-rss-red-walt.gif" width="88" height="31" />
|
||||
<img alt="Dylan Parker's entry #4" title="by Dylan Parker" src="/images/valid-rss-dylan4.gif" width="88" height="31" />
|
||||
<img alt="Walk Dickinson's entry with grey background" title="by Walt Dickinson" src="/images/valid-rss-grey-walt.gif" width="88" height="31" />
|
||||
<img alt="Neil Lee's entry with maroon background" title="by Neil Lee" src="/images/valid-rss-neil.gif" width="88" height="31" />
|
||||
<img alt="Dylan Parker's entry #3" title="by Dylan Parker" src="/images/valid-rss-dylan3.gif" width="88" height="31" />
|
||||
<img alt="Martin Murtonen's entry" title="by Martin Murtonen" src="/images/valid-rss-martin.gif" />
|
||||
<img alt="Dougal Campbell's entry with black background" title="by Dougal Campbell" src="/images/valid-rss-black-dougal.gif" width="88" height="31" />
|
||||
<img alt="Nicholas Avenell's entry" title="by Nicholas Avenell" src="/images/valid-rss-nicholas.png" width="88" height="31" />
|
||||
<img alt="Aaron Swartz's entry, based on a design by antipixel.com" title="by Aaron Swartz (in the style of antipixel.com)" src="/images/valid-rss-antipixel.png" width="80" height="15" />
|
||||
<img alt="Jack Greenwood's entry" title="by Jack Greenwood" src="/images/kiss-my-rss.gif" width="88" height="31" />
|
||||
</p>
|
||||
|
||||
<p>Designers who wish to have their "valid RSS" banner listed here should email it to <a href="mailto:feed-validator@diveintomark.org">feed-validator@diveintomark.org</a>.</p>
|
||||
|
||||
</div><!--main-->
|
||||
|
||||
<div class="centered">
|
||||
<a name="startnavigation" id="startnavigation"></a>
|
||||
<div class="navbarWrapper">
|
||||
<div class="navbarContent">
|
||||
<img class="borderTL" src="/images/borderTL.gif" alt="" width="14" height="14" />
|
||||
<img class="borderTR" src="/images/borderTR.gif" alt="" width="14" height="14" />
|
||||
|
||||
<p>
|
||||
<a href="./">Home</a> ·
|
||||
<a href="./about.html">About</a> ·
|
||||
<a href="./news/">News</a> ·
|
||||
<a href="./docs/">Docs</a> ·
|
||||
<a href="./terms.html">Terms</a>
|
||||
</p>
|
||||
|
||||
<div class="roundedCornerSpacer"> </div>
|
||||
</div><!-- .content -->
|
||||
<div class="bottomCorners">
|
||||
<img class="borderBL" src="/images/borderBL.gif" alt="" width="14" height="14" />
|
||||
<img class="borderBR" src="/images/borderBR.gif" alt="" width="14" height="14" />
|
||||
</div><!-- .bottomCorners -->
|
||||
</div><!-- .contentWrapper -->
|
||||
</div><!-- .centered -->
|
||||
|
||||
<div class="centered">
|
||||
<address>Copyright © 2002-3 <a href="http://diveintomark.org/">Mark Pilgrim</a> and <a href="http://www.intertwingly.net/blog/">Sam Ruby</a></address>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
355
vendor/feedvalidator/demo/check.cgi
vendored
355
vendor/feedvalidator/demo/check.cgi
vendored
|
@ -1,355 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
from config import *
|
||||
|
||||
import cgi, sys, os, urlparse, sys, re, urllib
|
||||
import cgitb
|
||||
cgitb.enable()
|
||||
|
||||
import codecs
|
||||
ENCODING='UTF-8'
|
||||
sys.stdout = codecs.getwriter(ENCODING)(sys.stdout)
|
||||
|
||||
# Used for CGI parameters
|
||||
decUTF8 = codecs.getdecoder('utf-8')
|
||||
decW1252 = codecs.getdecoder('windows-1252')
|
||||
|
||||
if PYDIR not in sys.path:
|
||||
sys.path.insert(0, PYDIR)
|
||||
|
||||
if WEBDIR not in sys.path:
|
||||
sys.path.insert(0, WEBDIR)
|
||||
|
||||
if SRCDIR not in sys.path:
|
||||
sys.path.insert(0, SRCDIR)
|
||||
import feedvalidator
|
||||
from feedvalidator.logging import FEEDTYPEDISPLAY, VALIDFEEDGRAPHIC
|
||||
|
||||
from feedvalidator.logging import Info, Warning, Error, ValidationFailure
|
||||
from feedvalidator.logging import TYPE_ATOM_ENTRY, TYPE_OPENSEARCH, TYPE_XRD
|
||||
|
||||
def applyTemplate(templateFile, params={}):
|
||||
params['CSSURL'] = CSSURL
|
||||
fsock = open(os.path.join(WEBDIR, 'templates', templateFile))
|
||||
data = fsock.read() % params
|
||||
fsock.close()
|
||||
return data.encode('utf-8')
|
||||
|
||||
def sanitizeURL(url):
|
||||
# Allow feed: URIs, as described by draft-obasanjo-feed-URI-scheme-02
|
||||
if url.lower().startswith('feed:'):
|
||||
url = url[5:]
|
||||
if url.startswith('//'):
|
||||
url = 'http:' + url
|
||||
|
||||
if not url.split(':')[0].lower() in ['http','https']:
|
||||
url = 'http://%s' % url
|
||||
url = url.strip()
|
||||
|
||||
# strip user and password
|
||||
url = re.sub(r'^(\w*://)[-+.\w]*(:[-+.\w]+)?@', r'\1' ,url)
|
||||
|
||||
return url
|
||||
|
||||
def escapeURL(url):
|
||||
parts = list(urlparse.urlparse(url))
|
||||
safe = ['/', '/:@', '/', '/', '/?&=;', '/']
|
||||
for i in range(0,len(parts)):
|
||||
parts[i] = urllib.quote(urllib.unquote(parts[i]),safe[i])
|
||||
url = cgi.escape(urlparse.urlunparse(parts))
|
||||
try:
|
||||
return url.decode('idna')
|
||||
except:
|
||||
return url
|
||||
|
||||
import feedvalidator.formatter.text_html
|
||||
|
||||
def buildCodeListing(events, rawdata, url):
|
||||
# print feed
|
||||
codelines = []
|
||||
linenum = 1
|
||||
linesWithErrors = [e.params.get('line', 0) for e in events]
|
||||
for line in rawdata.split('\n'):
|
||||
line = feedvalidator.formatter.text_html.escapeAndMark(line)
|
||||
if not line: line = ' '
|
||||
linetype = linenum in linesWithErrors and "b" or "a"
|
||||
codelines.append(applyTemplate('code_listing_line.tmpl', {"line":line, "linenum":linenum, "linetype":linetype}).decode('utf-8'))
|
||||
linenum += 1
|
||||
codelisting = "".join(codelines)
|
||||
return applyTemplate('code_listing.tmpl', {"codelisting":codelisting, "url":escapeURL(url)})
|
||||
|
||||
def yieldEventList(output):
|
||||
errors, warnings = output.getErrors(), output.getWarnings()
|
||||
|
||||
yield output.header()
|
||||
for o in output.getErrors():
|
||||
yield o.encode('utf-8')
|
||||
if errors and warnings:
|
||||
yield output.footer()
|
||||
if len(warnings) == 1:
|
||||
yield applyTemplate('andwarn1.tmpl')
|
||||
else:
|
||||
yield applyTemplate('andwarn2.tmpl')
|
||||
yield output.header()
|
||||
for o in output.getWarnings():
|
||||
yield o.encode('utf-8')
|
||||
yield output.footer()
|
||||
|
||||
from feedvalidator.formatter.text_html import Formatter
|
||||
|
||||
def postvalidate(url, events, rawdata, feedType, autofind=1):
|
||||
"""returns dictionary including 'url', 'events', 'rawdata', 'output', 'specialCase', 'feedType'"""
|
||||
# filter based on compatibility level
|
||||
from feedvalidator import compatibility
|
||||
filterFunc = compatibility.AA # hardcoded for now
|
||||
events = filterFunc(events)
|
||||
|
||||
specialCase = None
|
||||
formattedOutput = Formatter(events, rawdata)
|
||||
if formattedOutput:
|
||||
# check for special cases
|
||||
specialCase = compatibility.analyze(events, rawdata)
|
||||
if (specialCase == 'html') and autofind:
|
||||
try:
|
||||
try:
|
||||
import feedfinder
|
||||
class NotARobot:
|
||||
base=url
|
||||
def get(self, url):
|
||||
if url == self.base: return rawdata
|
||||
sock=urllib.urlopen(url)
|
||||
data=sock.read()
|
||||
sock.close()
|
||||
return data
|
||||
feedfinder._gatekeeper = NotARobot()
|
||||
rssurls = feedfinder.getFeeds(url)
|
||||
except:
|
||||
rssurls = [url]
|
||||
if rssurls:
|
||||
url = rssurls[0]
|
||||
params = feedvalidator.validateURL(url, firstOccurrenceOnly=1, wantRawData=1)
|
||||
events = params['loggedEvents']
|
||||
rawdata = params['rawdata']
|
||||
feedType = params['feedType']
|
||||
return postvalidate(url, events, rawdata, feedType, autofind=0)
|
||||
except:
|
||||
pass
|
||||
|
||||
return {"url":url, "events":events, "rawdata":rawdata, "output":formattedOutput, "specialCase":specialCase, "feedType":feedType}
|
||||
|
||||
def checker_app(environ, start_response):
|
||||
|
||||
method = environ['REQUEST_METHOD'].lower()
|
||||
contentType = environ.get('CONTENT_TYPE', None)
|
||||
output_option = ''
|
||||
|
||||
if (method == 'get') or (contentType and cgi.parse_header(contentType)[0].lower() == 'application/x-www-form-urlencoded'):
|
||||
fs = cgi.FieldStorage(fp=environ.get('wsgi.input',None), environ=environ)
|
||||
url = fs.getvalue("url") or ''
|
||||
try:
|
||||
if url: url = url.decode('utf-8').encode('idna')
|
||||
except:
|
||||
pass
|
||||
manual = fs.getvalue("manual") or 0
|
||||
rawdata = fs.getvalue("rawdata") or ''
|
||||
output_option = fs.getvalue("output") or ''
|
||||
|
||||
# XXX Should use 'charset'
|
||||
try:
|
||||
rawdata = decUTF8(rawdata)[0]
|
||||
except UnicodeError:
|
||||
rawdata = decW1252(rawdata)[0]
|
||||
|
||||
rawdata = rawdata[:feedvalidator.MAXDATALENGTH].replace('\r\n', '\n').replace('\r', '\n')
|
||||
else:
|
||||
url = None
|
||||
manual = None
|
||||
rawdata = None
|
||||
|
||||
if (output_option == "soap12"):
|
||||
# SOAP
|
||||
try:
|
||||
if ((method == 'post') and (not rawdata)):
|
||||
params = feedvalidator.validateStream(sys.stdin, contentType=contentType)
|
||||
elif rawdata :
|
||||
params = feedvalidator.validateString(rawdata, firstOccurrenceOnly=1)
|
||||
elif url:
|
||||
url = sanitizeURL(url)
|
||||
params = feedvalidator.validateURL(url, firstOccurrenceOnly=1, wantRawData=1)
|
||||
|
||||
events = params['loggedEvents']
|
||||
feedType = params['feedType']
|
||||
|
||||
# filter based on compatibility level
|
||||
from feedvalidator import compatibility
|
||||
filterFunc = compatibility.AA # hardcoded for now
|
||||
events = filterFunc(events)
|
||||
|
||||
events_error = list()
|
||||
events_warn = list()
|
||||
events_info = list()
|
||||
|
||||
|
||||
# format as xml
|
||||
from feedvalidator.formatter.text_xml import Formatter as xmlformat
|
||||
output = xmlformat(events)
|
||||
|
||||
for event in events:
|
||||
if isinstance(event,Error): events_error.append(output.format(event))
|
||||
if isinstance(event,Warning): events_warn.append(output.format(event))
|
||||
if isinstance(event,Info): events_info.append(output.format(event))
|
||||
if len(events_error) > 0:
|
||||
validation_bool = "false"
|
||||
else:
|
||||
validation_bool = "true"
|
||||
|
||||
from datetime import datetime
|
||||
right_now = datetime.now()
|
||||
validationtime = str( right_now.isoformat())
|
||||
|
||||
body = applyTemplate('soap.tmpl', {
|
||||
'errorlist':"\n".join( events_error), 'errorcount': str(len(events_error)),
|
||||
'warninglist':"\n".join( events_warn), 'warningcount': str(len(events_warn)),
|
||||
'infolist':"\n".join( events_info), 'infocount': str(len(events_info)),
|
||||
'home_url': HOMEURL, 'url': url, 'date_time': validationtime, 'validation_bool': validation_bool
|
||||
})
|
||||
start_response('200 OK', [('Content-type', 'application/soap+xml; charset=' + ENCODING)])
|
||||
yield body
|
||||
|
||||
except:
|
||||
import traceback
|
||||
tb = ''.join(apply(traceback.format_exception, sys.exc_info()))
|
||||
|
||||
from feedvalidator.formatter.text_xml import xmlEncode
|
||||
start_response('500 Internal Error', [('Content-type', 'text/xml; charset=' + ENCODING)])
|
||||
|
||||
yield applyTemplate('fault.tmpl', {'code':sys.exc_info()[0],
|
||||
'string':sys.exc_info()[1], 'traceback':xmlEncode(tb)})
|
||||
|
||||
else:
|
||||
start_response('200 OK', [('Content-type', 'text/html; charset=' + ENCODING)])
|
||||
|
||||
if url or rawdata:
|
||||
# validate
|
||||
goon = 0
|
||||
if rawdata:
|
||||
# validate raw data (from text form)
|
||||
try:
|
||||
params = feedvalidator.validateString(rawdata, firstOccurrenceOnly=1)
|
||||
events = params['loggedEvents']
|
||||
feedType = params['feedType']
|
||||
goon = 1
|
||||
except ValidationFailure, vfv:
|
||||
yield applyTemplate('header.tmpl', {'title':'Feed Validator Results: %s' % escapeURL(url)})
|
||||
yield applyTemplate('manual.tmpl', {'rawdata':escapeURL(url)})
|
||||
output = Formatter([vfv.event], None)
|
||||
for item in yieldEventList(output):
|
||||
yield item
|
||||
yield applyTemplate('error.tmpl')
|
||||
except:
|
||||
yield applyTemplate('header.tmpl', {'title':'Feed Validator Results: %s' % escapeURL(url)})
|
||||
yield applyTemplate('manual.tmpl', {'rawdata':escapeURL(url)})
|
||||
yield applyTemplate('error.tmpl')
|
||||
else:
|
||||
url = sanitizeURL(url)
|
||||
try:
|
||||
params = feedvalidator.validateURL(url, firstOccurrenceOnly=1, wantRawData=1)
|
||||
events = params['loggedEvents']
|
||||
rawdata = params['rawdata']
|
||||
feedType = params['feedType']
|
||||
goon = 1
|
||||
except ValidationFailure, vfv:
|
||||
yield applyTemplate('header.tmpl', {'title':'Feed Validator Results: %s' % escapeURL(url)})
|
||||
yield applyTemplate('index.tmpl', {'value':escapeURL(url)})
|
||||
output = Formatter([vfv.event], None)
|
||||
for item in yieldEventList(output):
|
||||
yield item
|
||||
yield applyTemplate('error.tmpl')
|
||||
except:
|
||||
yield applyTemplate('header.tmpl', {'title':'Feed Validator Results: %s' % escapeURL(url)})
|
||||
yield applyTemplate('index.tmpl', {'value':escapeURL(url)})
|
||||
yield applyTemplate('error.tmpl')
|
||||
if goon:
|
||||
# post-validate (will do RSS autodiscovery if needed)
|
||||
validationData = postvalidate(url, events, rawdata, feedType)
|
||||
|
||||
# write output header
|
||||
url = validationData['url']
|
||||
feedType = validationData['feedType']
|
||||
rawdata = validationData['rawdata']
|
||||
yield applyTemplate('header.tmpl', {'title':'Feed Validator Results: %s' % escapeURL(url)})
|
||||
if manual:
|
||||
yield applyTemplate('manual.tmpl', {'rawdata':cgi.escape(rawdata)})
|
||||
else:
|
||||
yield applyTemplate('index.tmpl', {'value':escapeURL(url)})
|
||||
|
||||
output = validationData.get('output', None)
|
||||
|
||||
# print special case, if any
|
||||
specialCase = validationData.get('specialCase', None)
|
||||
if specialCase:
|
||||
yield applyTemplate('%s.tmpl' % specialCase)
|
||||
|
||||
msc = output.mostSeriousClass()
|
||||
|
||||
# Explain the overall verdict
|
||||
if msc == Error:
|
||||
from feedvalidator.logging import ObsoleteNamespace
|
||||
if len(output.getErrors())==1 and \
|
||||
isinstance(output.data[0],ObsoleteNamespace):
|
||||
yield applyTemplate('notsupported.tmpl')
|
||||
else:
|
||||
yield applyTemplate('invalid.tmpl')
|
||||
elif msc == Warning:
|
||||
yield applyTemplate('warning.tmpl')
|
||||
elif msc == Info:
|
||||
yield applyTemplate('info.tmpl')
|
||||
|
||||
# Print any issues, whether or not the overall feed is valid
|
||||
if output:
|
||||
for item in yieldEventList(output):
|
||||
yield item
|
||||
|
||||
# print code listing
|
||||
yield buildCodeListing(validationData['events'], validationData['rawdata'], url)
|
||||
|
||||
# As long as there were no errors, show that the feed is valid
|
||||
if msc != Error:
|
||||
# valid
|
||||
htmlUrl = escapeURL(urllib.quote(url))
|
||||
try:
|
||||
htmlUrl = htmlUrl.encode('idna')
|
||||
except:
|
||||
pass
|
||||
docType = 'feed'
|
||||
if feedType == TYPE_ATOM_ENTRY: docType = 'entry'
|
||||
if feedType == TYPE_XRD: docType = 'document'
|
||||
if feedType == TYPE_OPENSEARCH: docType = 'description document'
|
||||
yield applyTemplate('valid.tmpl', {"url":htmlUrl, "srcUrl":htmlUrl, "feedType":FEEDTYPEDISPLAY[feedType], "graphic":VALIDFEEDGRAPHIC[feedType], "HOMEURL":HOMEURL, "docType":docType})
|
||||
else:
|
||||
# nothing to validate, just write basic form
|
||||
yield applyTemplate('header.tmpl', {'title':'Feed Validator for Atom and RSS'})
|
||||
if manual:
|
||||
yield applyTemplate('manual.tmpl', {'rawdata':''})
|
||||
else:
|
||||
yield applyTemplate('index.tmpl', {'value':'http://'})
|
||||
yield applyTemplate('special.tmpl', {})
|
||||
|
||||
yield applyTemplate('navbar.tmpl')
|
||||
yield applyTemplate('footer.tmpl')
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)==1 or not sys.argv[1].isdigit():
|
||||
def start_response(status, headers):
|
||||
print 'Status: %s\r\n' % status,
|
||||
for header,value in headers:
|
||||
print '%s: %s\r\n' % (header, value),
|
||||
print
|
||||
for output in checker_app(os.environ, start_response):
|
||||
print output.decode('utf-8')
|
||||
else:
|
||||
# export HTTP_HOST=http://feedvalidator.org/
|
||||
# export SCRIPT_NAME=check.cgi
|
||||
# export SCRIPT_FILENAME=/home/rubys/svn/feedvalidator/check.cgi
|
||||
import fcgi
|
||||
port=int(sys.argv[1])
|
||||
fcgi.WSGIServer(checker_app, bindAddress=("127.0.0.1", port)).run()
|
22
vendor/feedvalidator/demo/config.py
vendored
22
vendor/feedvalidator/demo/config.py
vendored
|
@ -1,22 +0,0 @@
|
|||
# Default URL of the validator itself... feel free to beautify as you like
|
||||
import os
|
||||
HOMEURL = os.environ['HTTP_HOST'] + os.environ['SCRIPT_NAME']
|
||||
if not HOMEURL.startswith('http://'): HOMEURL = 'http://' + HOMEURL
|
||||
|
||||
# This is where the CGI itself is... other supporting scripts (like
|
||||
# feedfinder) may be placed here.
|
||||
WEBDIR = '/'.join(os.environ['SCRIPT_FILENAME'].split('/')[0:-1])
|
||||
|
||||
# This following value is primarily used for setting up the other values...
|
||||
HOMEDIR = WEBDIR
|
||||
|
||||
# This is where local python libraries are installed. This may be useful
|
||||
# for locating a locally installed libxml2 library, for example...
|
||||
PYDIR = HOMEDIR + r'/lib/python/'
|
||||
|
||||
# This is where the feedvalidator code lives...
|
||||
SRCDIR = WEBDIR + r'/src'
|
||||
|
||||
# The web location prefix of the docs and CSS, relative to check.cgi
|
||||
DOCSURL='docs'
|
||||
CSSURL='css'
|
170
vendor/feedvalidator/demo/css/common.css
vendored
170
vendor/feedvalidator/demo/css/common.css
vendored
|
@ -1,170 +0,0 @@
|
|||
/* ----- general ----- */
|
||||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
font-size: 100%;
|
||||
/* UNIX-friendly fonts from <http://www.realworldstyle.com/fonts.html> */
|
||||
font-family: "Lucida Grande", "Trebuchet MS", Verdana, Geneva, Lucida, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
a.skip {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
p.centered {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* ----- logo ----- */
|
||||
|
||||
#logo {
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
color: #444;
|
||||
font-size: 400%;
|
||||
font-family: LuciduxSerif, Georgia, "Book Antiqua", Palatino, serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#rss {
|
||||
letter-spacing: 0.2em;
|
||||
}
|
||||
|
||||
#f {
|
||||
background-color: transparent;
|
||||
color: #cc0000;
|
||||
}
|
||||
|
||||
#e1 {
|
||||
background-color: transparent;
|
||||
color: #009900;
|
||||
}
|
||||
|
||||
#e2 {
|
||||
background-color: transparent;
|
||||
color: #3366cc;
|
||||
}
|
||||
|
||||
#d {
|
||||
background-color: transparent;
|
||||
color: #cc6633;
|
||||
}
|
||||
|
||||
#logo p {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* ----- navbar ----- */
|
||||
|
||||
/* rounded corners from <http://www.albin.net/CSS/RoundedCorners/> */
|
||||
.navbarWrapper {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 30px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 50%;
|
||||
padding: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.navbarContent {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
border: 1px solid #000000;
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.navbarContent p {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.roundedCornerSpacer {
|
||||
margin: 0px; padding: 0px; border: 0px;
|
||||
font-size: 1px; line-height: 1px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.borderTL, .borderTR, .borderBL, .borderBR {
|
||||
width: 14px; height: 14px;
|
||||
padding: 0px; border: 0px;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.borderTL, .borderBL { float: left; clear: both; }
|
||||
.borderTR, .borderBR { float: right; clear: right; }
|
||||
.borderTL { margin: -1px 0px 0px -1px; }
|
||||
.borderTR { margin: -1px -1px 0px 0px; }
|
||||
.borderBL { margin: -14px 0px 0px 0px; }
|
||||
.borderBR { margin: -14px 0px 0px 0px; }
|
||||
|
||||
.borderTL {
|
||||
margin-left: -4px;
|
||||
ma\rgin-left: -1px;
|
||||
}
|
||||
html>body .borderTL {
|
||||
margin-left: -1px;
|
||||
}
|
||||
.borderTR {
|
||||
margin-right: -4px;
|
||||
ma\rgin-right: -1px;
|
||||
}
|
||||
html>body .borderTR {
|
||||
margin-right: -1px;
|
||||
}
|
||||
.borderBL {
|
||||
margin-left: -3px;
|
||||
ma\rgin-left: 0px;
|
||||
}
|
||||
html>body .borderBL {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.borderBR {
|
||||
margin-right: -3px;
|
||||
ma\rgin-right: 0px;
|
||||
}
|
||||
html>body .borderBR {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
/* ----- footer ----- */
|
||||
|
||||
address {
|
||||
font-size: x-small;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#poweredby {
|
||||
font-size: x-small;
|
||||
background: transparent;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: larger;
|
||||
}
|
16
vendor/feedvalidator/demo/css/documentation.css
vendored
16
vendor/feedvalidator/demo/css/documentation.css
vendored
|
@ -1,16 +0,0 @@
|
|||
#main h2 {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
#main .docbody {
|
||||
margin-left: 2em;
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
#main p.meta {
|
||||
font-size: xx-small;
|
||||
background: transparent;
|
||||
color: #999;
|
||||
margin-top: 1em;
|
||||
margin-left: 0;
|
||||
}
|
27
vendor/feedvalidator/demo/css/news.css
vendored
27
vendor/feedvalidator/demo/css/news.css
vendored
|
@ -1,27 +0,0 @@
|
|||
#main .newsbody {
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
#main h2 {
|
||||
margin-bottom: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
#main p.dateheader {
|
||||
font-size: xx-small;
|
||||
background: transparent;
|
||||
color: #333;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#main p.dateheader a {
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
color: #999;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
#main p.dateheader a:hover {
|
||||
background: transparent;
|
||||
color: #333;
|
||||
}
|
66
vendor/feedvalidator/demo/css/validator.css
vendored
66
vendor/feedvalidator/demo/css/validator.css
vendored
|
@ -1,66 +0,0 @@
|
|||
/* ----- validation form ----- */
|
||||
|
||||
form#validation {
|
||||
width: 550px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
/* ----- results ----- */
|
||||
|
||||
.message {
|
||||
background-color: yellow;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.marker {
|
||||
background-color: transparent;
|
||||
color: #cc0000;
|
||||
}
|
||||
|
||||
.badOctet {
|
||||
font-weight: bold;
|
||||
color: inherit;
|
||||
background: red;
|
||||
}
|
||||
|
||||
div.specialmessage {
|
||||
border: 1px solid black;
|
||||
background-color: #ddd;
|
||||
color: black;
|
||||
margin-left: 2em;
|
||||
margin-right: 2em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
/* ----- code listing ----- */
|
||||
|
||||
/* code listing from <http://development.incutio.com/simon/numbered-code-experiment.html> */
|
||||
ol.codeListing {
|
||||
font-family: monospace;
|
||||
color: green;
|
||||
background-color: #fff;
|
||||
list-style-type: decimal-leading-zero;
|
||||
list-style-position: inside;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
ol.codeListing li {
|
||||
background-color: #eee;
|
||||
color: black;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
ol.codeListing li code {
|
||||
background: transparent;
|
||||
color: black;
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
ol.codeListing li code.b {
|
||||
background: yellow;
|
||||
color: black;
|
||||
}
|
9
vendor/feedvalidator/demo/docs-xml/Makefile
vendored
9
vendor/feedvalidator/demo/docs-xml/Makefile
vendored
|
@ -1,9 +0,0 @@
|
|||
all: docs ../docs/index.html
|
||||
|
||||
docs: $(patsubst %.xml,../docs/%.html, error/*.xml warning/*.xml info/*.xml)
|
||||
|
||||
../docs/%.html: %.xml
|
||||
./build-html-docs.py template.html ../docs $<
|
||||
|
||||
../docs/index.html: docs-index-header.html error/*.xml warning/*.xml info/*.xml docs-index-footer.html build-docs-index.py
|
||||
./build-docs-index.py
|
|
@ -1,64 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Put a header and a footer on a list of all documented diagnostics,
|
||||
# linking to their pages.
|
||||
|
||||
# Note that this script has lots of hardcoded paths, needs to be run
|
||||
# from the docs-xml directory, and modifies the index.html in docs.
|
||||
|
||||
from os import listdir
|
||||
from os import path
|
||||
import re
|
||||
|
||||
from sys import stderr
|
||||
|
||||
basedir = '.'
|
||||
|
||||
messageRe = re.compile("<div id='message'>\n<p>(.*)</p>\n</div>")
|
||||
|
||||
def getMessage(fn):
|
||||
f = open(fn)
|
||||
txt = f.read()
|
||||
f.close()
|
||||
|
||||
m = messageRe.search(txt)
|
||||
return m.group(1)
|
||||
|
||||
of = open('../docs/index.html', 'w')
|
||||
|
||||
def printLine(hr, msg):
|
||||
of.write('<li><a href="%s">%s</a></li>' % (hr, msg))
|
||||
of.write("\n")
|
||||
|
||||
|
||||
f = open('docs-index-header.html')
|
||||
of.write(f.read())
|
||||
f.close()
|
||||
|
||||
of.write("<h2>Validator messages</h2>\n")
|
||||
|
||||
for (type, title) in [('error', 'Errors'), ('warning', 'Warnings'), ('info', 'Information')]:
|
||||
p = path.join(basedir, type)
|
||||
|
||||
allMsgs = []
|
||||
|
||||
for f in listdir(p):
|
||||
(name,ext) = path.splitext(f)
|
||||
if ext != '.xml':
|
||||
continue
|
||||
msg = getMessage(path.join(p, f))
|
||||
|
||||
allMsgs.append([name, msg])
|
||||
|
||||
allMsgs.sort()
|
||||
|
||||
of.write("\n<h3>%s</h3>\n" % title)
|
||||
of.write("<ul>\n")
|
||||
|
||||
for (f, msg) in allMsgs:
|
||||
printLine(type + '/' + f + '.html', msg)
|
||||
of.write("</ul>\n")
|
||||
|
||||
f = open('docs-index-footer.html')
|
||||
of.write(f.read())
|
||||
f.close()
|
|
@ -1,100 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Given a template (with a specific format), a target document root and a set of formatted XML
|
||||
# documents, generate HTML documentation for public web access.
|
||||
|
||||
# Extracts information from XML using regular expression and proper parsing
|
||||
|
||||
|
||||
from sys import argv, stderr, exit
|
||||
|
||||
if len(argv) < 3:
|
||||
print >>stderr,"Usage:",argv[0]," <template.html> <target-doc-directory> [source XML document ... ]"
|
||||
exit(5)
|
||||
|
||||
template = argv[1]
|
||||
targetDir = argv[2]
|
||||
|
||||
f = open(template)
|
||||
bp = f.read()
|
||||
f.close()
|
||||
|
||||
doc = bp
|
||||
|
||||
import libxml2
|
||||
import os.path
|
||||
|
||||
libxml2.substituteEntitiesDefault(True)
|
||||
|
||||
def asText(x):
|
||||
d = libxml2.parseDoc(x)
|
||||
return d.xpathCastNodeToString()
|
||||
|
||||
import re
|
||||
|
||||
wsRE = re.compile('\s+')
|
||||
|
||||
def trimWS(s):
|
||||
s = wsRE.sub(' ', s)
|
||||
if s and s[0] == ' ':
|
||||
s = s[1:]
|
||||
if s and s[-1] == ' ':
|
||||
s = s[:-1]
|
||||
|
||||
return s
|
||||
|
||||
secRe = re.compile("<div id='(\w+)'>\n(.*?\n)</div>\n", re.DOTALL)
|
||||
|
||||
import codecs
|
||||
|
||||
def writeDoc(x, h):
|
||||
f = open(x)
|
||||
t = f.read()
|
||||
f.close()
|
||||
|
||||
doc = bp
|
||||
|
||||
# Get the title
|
||||
xd = libxml2.parseFile(x)
|
||||
ctxt = xd.xpathNewContext()
|
||||
ctxt.xpathRegisterNs('html', 'http://www.w3.org/1999/xhtml')
|
||||
|
||||
title = ctxt.xpathEvalExpression('string(/fvdoc//html:div[@id="message"])')
|
||||
|
||||
title = trimWS(title)
|
||||
doc = doc.replace('<title></title>', '<title>' + title + '</title>')
|
||||
|
||||
|
||||
for (sec, txt) in secRe.findall(t):
|
||||
r = re.compile('<h2>' + sec + '</h2>\s*<div class="docbody">\s*()</div>', re.IGNORECASE)
|
||||
idx = r.search(doc).start(1)
|
||||
doc = doc[:idx] + txt + doc[idx:]
|
||||
|
||||
c = codecs.getdecoder('utf-8')
|
||||
|
||||
doc = c(doc)[0]
|
||||
|
||||
c = codecs.getencoder('iso-8859-1')
|
||||
|
||||
f = open(h, 'w')
|
||||
f.write(c(doc, 'xmlcharrefreplace')[0])
|
||||
f.close()
|
||||
|
||||
for f in argv[3:]:
|
||||
sp = os.path.abspath(f)
|
||||
|
||||
if not(os.path.isfile(sp)):
|
||||
continue
|
||||
|
||||
category = os.path.split(os.path.dirname(sp))[1]
|
||||
filename = os.path.basename(sp)
|
||||
|
||||
if not(category):
|
||||
continue
|
||||
|
||||
(name, ext) = os.path.splitext(filename)
|
||||
|
||||
if ext == '.xml':
|
||||
writeDoc(sp, os.path.join(targetDir, category, name + '.html'))
|
||||
else:
|
||||
print >>stderr,"Ignoring",f
|
|
@ -1,33 +0,0 @@
|
|||
|
||||
</div><!--main-->
|
||||
|
||||
<div class="centered">
|
||||
<a name="startnavigation" id="startnavigation"></a>
|
||||
<div class="navbarWrapper">
|
||||
<div class="navbarContent">
|
||||
<img class="borderTL" src="../images/borderTL.gif" alt="" width="14" height="14" />
|
||||
<img class="borderTR" src="../images/borderTR.gif" alt="" width="14" height="14" />
|
||||
|
||||
<p>
|
||||
<a href="../">Home</a> ·
|
||||
<a href="../about.html">About</a> ·
|
||||
<a href="../news/">News</a> ·
|
||||
<a href="../docs/">Docs</a> ·
|
||||
<a href="../terms.html">Terms</a>
|
||||
</p>
|
||||
|
||||
<div class="roundedCornerSpacer"> </div>
|
||||
</div><!-- .content -->
|
||||
<div class="bottomCorners">
|
||||
<img class="borderBL" src="../images/borderBL.gif" alt="" width="14" height="14" />
|
||||
<img class="borderBR" src="../images/borderBR.gif" alt="" width="14" height="14" />
|
||||
</div><!-- .bottomCorners -->
|
||||
</div><!-- .contentWrapper -->
|
||||
</div><!-- .centered -->
|
||||
|
||||
<div class="centered">
|
||||
<address>Copyright © 2002-3 <a href="http://diveintomark.org/">Mark Pilgrim</a> and <a href="http://www.intertwingly.net/blog/">Sam Ruby</a></address>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,39 +0,0 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>Feed Validator Documentation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<link rel="icon" href="http://www.feedvalidator.org/favicon.ico" />
|
||||
<link rel="shortcut icon" href="http://www.feedvalidator.org/favicon.ico" />
|
||||
<style type="text/css" media="screen">@import "../css/common.css";
|
||||
@import "../css/documentation.css";</style>
|
||||
<script type="text/javascript"><!-- --></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="logo">
|
||||
<h1><a href="/"><span id="feed"><span id="f">F</span><span id="e1">E</span><span id="e2">E</span></span><span id="d">D</span> Validator</a></h1>
|
||||
<p>Documentation</p>
|
||||
<a class="skip" href="#startnavigation">Jump to navigation</a>
|
||||
</div> <!--logo-->
|
||||
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h2>Tutorials</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="howto/declare_namespaces.html">How do I declare namespaces in my RSS feed?</a></li>
|
||||
<li><a href="howto/install_and_run.html">How do I install and run the Feed Validator?</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Specifications</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://www.atomenabled.org/developers/syndication/atom-format-spec.php">Atom 1.0</a></li>
|
||||
<li><a href="rss1.html">RSS 1.0 specification</a></li>
|
||||
<li><a href="rss2.html">RSS 2.0 specification</a></li>
|
||||
</ul>
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> should not have text (all data is in attributes)</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>You have an old-style <code>link</code> in your Atom feed.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>In Atom 0.3, the format of <code>link</code> changed. Instead of simply containing an address of a page or resource, it now contains three attributes that describe the type of link, and the MIME type of the linked resource, and the address of the resource.</p>
|
||||
|
||||
<p>This was the format in Atom 0.2:</p>
|
||||
|
||||
<blockquote><code><link>http://www.example.com/</link></code></blockquote>
|
||||
|
||||
<p>This is the new format in Atom 1.0 and later:</p>
|
||||
|
||||
<blockquote><code><link href="http://www.example.com/"/></code></blockquote>
|
||||
|
||||
<p>Note: this information only applies to Atom feeds (not RSS feeds).</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE fvdoc [
|
||||
<!ENTITY nbsp " ">
|
||||
]>
|
||||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Feeds must specify XML Version 1.0</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>All RSS and Atom files must conform to the <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">XML 1.0</a> specification</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Replace the version string in the XML declaration with "1.0". The result should look something like this:</p>
|
||||
<blockquote><p><code><?xml version="1.0" encoding="iso-8859-1"?></code></p></blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Feeds must not contain SYSTEM entities</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Your feed contains a <code>SYSTEM</code> entity. This is a security risk.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Remove the <code>SYSTEM</code> entity. RSS feeds must be self-contained.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,15 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Duplicate alternate links with the same type and hreflang</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>atom:feed elements MUST NOT contain more than one atom:link
|
||||
element with a rel attribute value of "alternate" that has the
|
||||
same combination of type and hreflang attribute values.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Remove one of the links.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> contains more than one <code>bar</code></p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Only one occurrence of the specified element is allowed in this context. For example, <code>channel</code> can only contain one <code>title</code> element.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Delete the redundant element.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> values must not be duplicated within a feed</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Only one occurrence of the specified value is allowed in the feed. For example, in RSS 2.0, <code>skipDay</code> elements can only contain one <code>day</code> element with a given value.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Delete the redundant element.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>skipDays can not contain more than 7 day elements</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p><a href="http://backend.userland.com/skipHoursDays#skipdays"><code>skipDays</code></a> can not contain more than 7 <code>day</code> elements.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Remove the duplicate <code>days</code> elements.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,18 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>HTTP Error</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Your feed couldn't be validated because there was a problem downloading
|
||||
it from the web server. You should try to diagnose this using a web browser,
|
||||
and make sure that the URL you supplied resolves to an accessible file.</p>
|
||||
<p>This usually means that the URL was wrong, or that permissions on
|
||||
the server don't allow us to fetch that file. The error shows the
|
||||
message that the server sent, which may help.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make sure this URL can be downloaded with a browser, then try again.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,24 +0,0 @@
|
|||
<!DOCTYPE fvdoc [
|
||||
<!ENTITY ldquo "“">
|
||||
<!ENTITY rdquo "”">
|
||||
<!ENTITY rsquo "’">
|
||||
]>
|
||||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>HTTP Protocol Error</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The HTTP response from the server was invalid. This will prevent some
|
||||
aggregators from downloading the feed at all.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>One common cause for this is WordPress’s “Last Modified” header
|
||||
(with a space, rather than a dash, separating the words).
|
||||
See
|
||||
<a href="http://wordpress.org/support/topic/13097#post-87665" title="RSS Feed Problems « WordPress Support">WordPress support</a>,
|
||||
or upgrade to
|
||||
<a href="http://wordpress.org/download/">a newer version</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,18 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>IO Error</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Your feed couldn't be validated because there was a problem downloading
|
||||
it from the web server. You should try to diagnose this using a web browser,
|
||||
and make sure that the URL you supplied resolves to an accessible file.</p>
|
||||
<p>One specific case that causes this is a server that claims the file
|
||||
is compressed, but then serves an uncompressed file. You may need to contact
|
||||
your host's administrators to resolve this problem.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make sure this URL can be downloaded with a browser, then try again.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,23 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Incorrect day of week: <code>foo</code></p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>If included, day-of-week must be the day implied by the date
|
||||
specification.</p>
|
||||
<p>As an example, the following is an incorrect date:</p>
|
||||
<blockquote><code><pubDate><b>Sat</b>, 31 Dec 1999 23:59:59 EST</pubDate></code></blockquote>
|
||||
<p>The following is a corrected example:</p>
|
||||
<blockquote><code><pubDate><b>Fri</b>, 31 Dec 1999 23:59:59 EST</pubDate></code></blockquote>
|
||||
<p>This may be indicative of a more significant software error in the
|
||||
formatting of dates that needs to be corrected.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>If it turns out that computing the correct day of week is impractical
|
||||
using the software you have available, then
|
||||
<a href="http://www.sendmail.org/rfc/0822.html#5">RFC 822</a> permits omitting
|
||||
both the day of the week and the subsequent comma from the value.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for access:restriction: <code>foo</code></p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid access:restriction.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute value to either <code>allow</code> or <code>deny</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,24 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be an email address</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>MUST conform to the "addr-spec" production in <a href="http://www.faqs.org/rfcs/rfc2822.html">RFC 2822</a></p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Convert the email address to a valid form. Examples of valid email
|
||||
addresses:</p>
|
||||
<ul>
|
||||
<li>joesmith@example.com</li>
|
||||
<li>joesmith+nospamplease@nospam.example.com</li>
|
||||
</ul>
|
||||
<p>Note: addr-spec does not include a provision for a display-name. Use
|
||||
atom:name instead. Examples of invalid email addresses:</p>
|
||||
<ul>
|
||||
<li>joesmith@example.com (Joe Smith)</li>
|
||||
<li>Joe Smith &lt;joesmith@example.com&gt;</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> attribute of <code>bar</code> must be 'true' or 'false'</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid boolean value.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute value to either <code>true</code> or <code>false</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,19 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be comma-separated integers</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The value for this element must be a list of integers, separated by commas.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Convert the value to a list of comma-separated integers. Examples
|
||||
of valid comma-separated integers:</p>
|
||||
<ul>
|
||||
<li><samp>1</samp></li>
|
||||
<li><samp>1,2,3</samp></li>
|
||||
<li><samp>3, 5, 7</samp></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,24 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must include an email address</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Email addresses must conform to <a href="http://www.faqs.org/rfcs/rfc2822.html">
|
||||
RFC 2822</a></p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Convert the email address to a valid form. Examples of valid email
|
||||
addresses:</p>
|
||||
<ul>
|
||||
<li>joesmith@example.com</li>
|
||||
<li>joesmith@example.com (Joe Smith)</li>
|
||||
<li>Joe Smith &lt;joesmith@example.com&gt;</li>
|
||||
<li>joesmith.nospamplease@nospam.example.com</li>
|
||||
</ul>
|
||||
<p>Alternately, if the intent is to credit authorship without revealing
|
||||
e-mail addresses, consider using the
|
||||
<a href="http://www.rssboard.org/rss-profile#namespace-elements-dublin-creator">dc:creator</a> element instead.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,15 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> is not a valid mode</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The <code>mode</code> attribute of a <code>content</code> element must be either <samp>"xml"</samp>, <samp>"escaped"</samp>, or <samp>"base64"</samp>.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Use one of the acceptable values, or take out the attribute (it defaults to <samp>"xml"</samp>).</p>
|
||||
|
||||
<p>Like all attributes in XML, this attribute value is case sensitive.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid Coordinate</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>A point contains a single coordinate pair. The coordinate pair contains a latitude value and a longitude value in that order. The preferred serialization of this uses a space to separate the two values.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://www.georss.org/">GeoRSS documentation</a> for further details. You might find the <a href="http://www.georss.org/gml.html#examples">examples</a> particularly helpful.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid Coordinate</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>A line contains two or more coordinate pairs. Each pair contains a latitude value and a longitude value in that order. The preferred serialization of this uses a space to separate the two values. Pairs are separated from each other by a space.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://www.georss.org/">GeoRSS documentation</a> for further details. You might find the <a href="http://www.georss.org/gml.html#examples">examples</a> particularly helpful.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid counry code: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The only acceptable values are ISO 3166 country codes..</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">ISO documentation</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,18 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid Credit Role</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Roles must be lower case. Additionally, if the <code>scheme</code> is not
|
||||
specified as anything other than <code>urn:ebu</code>, roles must be selected
|
||||
from the
|
||||
<a href="http://www.ebu.ch/en/technical/metadata/specifications/role_codes.php">European Broadcasting Union Role Codes</a></p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the role to be lower case, adjust the <code>scheme</code>, and/or
|
||||
select a role from the
|
||||
<a href="http://www.ebu.ch/en/technical/metadata/specifications/role_codes.php">European Broadcasting Union Role Codes</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>g:currency</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Values must be in ISO 4217 currency code format.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html">ISO documentation</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, or Sunday</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p><code>day</code> elements must be one of the following strings: "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", or "Sunday".</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Fix or remove any <code>day</code> elements that are invalid.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,15 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid duration: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Invalid duration.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>The tag can be formatted HH:MM:SS, H:MM:SS, MM:SS, or M:SS (H = hours, M = minutes, S = seconds)</p>
|
||||
|
||||
<p>An example of a valid Duration: <samp>7:40</samp></p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,16 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid character encoding: <i>foo</i></p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>There is a problem with the character encoding specified.
|
||||
This may be a typo, for example, <code>utf_8</code> rather
|
||||
than <code>utf-8</code>, or may be an encoding that isn't registered.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Replace the specified encoding with one of the
|
||||
<a href="http://www.iana.org/assignments/character-sets" title="CHARACTER SETS">registered character set</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><expansionState> is a comma-separated list of line numbers.</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid value for this element.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute value to a comma-separated list of line numbers.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>foo</code>: "<code>bar</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Value is a floating point number.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>foo</code>: "<code>bar</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Format is a floating point number optionally followed by a unit.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,16 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid form component name</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The name MUST begin with a letter and
|
||||
contain only these characters: the letters A to Z in either case,
|
||||
numeric digits, colons (":"), hyphens ("-"), periods (".") and
|
||||
underscores ("_").</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://www.rssboard.org/rss-draft-1#element-channel-textinput-name">documentation for the textInput name element</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,17 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be a full URI</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified value is not a full URI, or is mal-formed.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>If this is a link to a web page, make sure to include the "<code>http://</code>" at the beginning. If you've already done that, it's possible that the URI contains an invalid character. A complete list of acceptable characters can be found in <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.</p>
|
||||
|
||||
<p>If this is a mailing address, make sure to include the "<code>mailto:</code>" at the beginning.</p>
|
||||
|
||||
<p>The data in link elements <a href="../rss2.html#comments">must</a> begin win an <a href="http://www.iana.org/assignments/uri-schemes">IANA-registered</a> URI scheme</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>g:location</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Value should include street, city, state, postal code, and country, in that order.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html#location">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>g:gender</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Acceptable values are "Male", "M", "Female", or "F".</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html#gender">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be between 1 and 400</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p><code><a href="../../docs/rss2.html#ltimagegtSubelementOfLtchannelgt">Image height</a></code> must be between 1 and 400.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Resize your image manually, then specify the new height within range.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be between an integer 0 and 24</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p><a href="http://backend.userland.com/skipHoursDays#skiphours"><code>hour</code> elements</a> must be an integer between 0 and 24.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Remove any <code>hour</code> elements that are out of range.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,21 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>guid</code> must be a full URL, unless isPermaLink attribute is false</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>By default, the <code>guid</code> element specifies a permanent link for an item, the value must be a full URL (starting with "<code>"http://"</code>").</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>If you are using the <code>guid</code> element as a permanent link, make sure the value is a full URL, including the "<code>http://</code>" at the beginning.</p>
|
||||
|
||||
<p>If you are using the <code>guid</code> element simply as a unique identifier (and not a link to the item), then the value can be whatever you want, but you must include the attribute <code>isPermaLink="false"</code> in the <code>guid</code> tag.</p>
|
||||
|
||||
<p>Both of these are valid <code>guid</code>s:</p>
|
||||
|
||||
<p><samp><guid>http://www.example.com/archives/000054.html</guid></samp></p>
|
||||
|
||||
<p><samp><guid isPermaLink="false">article 54 at example.com</guid></samp></p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be a valid IRI</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The IRI contains an invalid character. A complete list of acceptable characters can be found in <a href="http://www.ietf.org/rfc/rfc3987.txt">RFC 3987</a>.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Replace the invalid characters with the proper escape sequence. For example, "{" and "}" characters should be replaced with "%7B" and "%7D" respectively.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,17 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be an ISO-8601 date</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Invalid date.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>The value specified must adhere to the
|
||||
<a href="http://www.iso.ch/iso/en/prods-services/popstds/datesandtime.html">ISO 8601</a>
|
||||
Date format. </p>
|
||||
|
||||
<p>An example of a valid ISO8601 Date: <samp>2002-10-02</samp></p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,17 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be an ISO-8601 date-time</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Invalid date-tie.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>The value specified must adhere to the
|
||||
<a href="http://www.iso.ch/iso/en/prods-services/popstds/datesandtime.html">ISO 8601</a>
|
||||
Date and time format. </p>
|
||||
|
||||
<p>An example of a valid ISO8601 Date-time: <samp>2002-10-02T10:00:00-05:00</samp></p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>foo</code>: "<code>bar</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Format is an integer followed by an optional unit.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be an integer</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>This value must be an integer greater than or equal to zero. It can not be negative, or a decimal, or a fraction, or a string, or blank.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make the specified value a non-negative integer.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> attribute of <code>bar</code> must be a positive integer</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>This attribute value must be an integer greater than zero. It can not be negative, or a decimal, or a fraction, or a string, or blank.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make the specified attribute value a positive integer.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,106 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> is not one of the predefined iTunes categories or sub-categories</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>itunes:category can only be populated using iTunes specific catgories or
|
||||
sub-categories, as listed in the
|
||||
<a href="http://www.apple.com/itunes/podcasts/techspecs.html#_Toc526931698">specification</a>.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute value to one of the following values:</p>
|
||||
<ul>
|
||||
<li>Arts</li>
|
||||
<ul>
|
||||
<li>Design</li>
|
||||
<li>Fashion & Beauty</li>
|
||||
<li>Food</li>
|
||||
<li>Literature</li>
|
||||
<li>Performing Arts</li>
|
||||
<li>Visual Arts</li>
|
||||
</ul>
|
||||
<li>Business</li>
|
||||
<ul>
|
||||
<li>Business News</li>
|
||||
<li>Careers</li>
|
||||
<li>Investing</li>
|
||||
<li>Management & Marketing</li>
|
||||
<li>Shopping</li>
|
||||
</ul>
|
||||
<li>Comedy</li>
|
||||
<li>Education</li>
|
||||
<ul>
|
||||
<li>Education Technology</li>
|
||||
<li>Higher Education</li>
|
||||
<li>K-12</li>
|
||||
<li>Language Courses</li>
|
||||
<li>Training</li>
|
||||
</ul>
|
||||
<li>Games & Hobbies</li>
|
||||
<ul>
|
||||
<li>Automotive</li>
|
||||
<li>Aviation</li>
|
||||
<li>Hobbies</li>
|
||||
<li>Other Games</li>
|
||||
<li>Video Games</li>
|
||||
</ul>
|
||||
<li>Government & Organizations</li>
|
||||
<ul>
|
||||
<li>Local</li>
|
||||
<li>National</li>
|
||||
<li>Non-Profit</li>
|
||||
<li>Regional</li>
|
||||
</ul>
|
||||
<li>Health</li>
|
||||
<ul>
|
||||
<li>Alternative Health</li>
|
||||
<li>Fitness & Nutrition</li>
|
||||
<li>Self-Help</li>
|
||||
<li>Sexuality</li>
|
||||
</ul>
|
||||
<li>Kids & Family</li>
|
||||
<li>Music</li>
|
||||
<li>News & Politics</li>
|
||||
<li>Religion & Spirituality</li>
|
||||
<ul>
|
||||
<li>Buddhism</li>
|
||||
<li>Christianity</li>
|
||||
<li>Hinduism</li>
|
||||
<li>Islam</li>
|
||||
<li>Judaism</li>
|
||||
<li>Other</li>
|
||||
<li>Spirituality</li>
|
||||
</ul>
|
||||
<li>Science & Medicine</li>
|
||||
<ul>
|
||||
<li>Medicine</li>
|
||||
<li>Natural Sciences</li>
|
||||
<li>Social Sciences</li>
|
||||
</ul>
|
||||
<li>Society & Culture</li>
|
||||
<ul>
|
||||
<li>History</li>
|
||||
<li>Personal Journals</li>
|
||||
<li>Philosophy</li>
|
||||
<li>Places & Travel</li>
|
||||
</ul>
|
||||
<li>Sports & Recreation</li>
|
||||
<ul>
|
||||
<li>Amateur</li>
|
||||
<li>College & High School</li>
|
||||
<li>Outdoor</li>
|
||||
<li>Professional</li>
|
||||
</ul>
|
||||
<li>Technology</li>
|
||||
<ul>
|
||||
<li>Gadgets</li>
|
||||
<li>Podcasting</li>
|
||||
<li>Software How-To</li>
|
||||
<li>Tech News</li>
|
||||
</ul>
|
||||
<li>TV & Film</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>g:label</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Place each label in a separate <label> and </label> tags.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html#label">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,19 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be an ISO-639 language code</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The value specified must adhere to the <a href="http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes">W3C format for language codes</a>. </p>
|
||||
|
||||
<p>An example of a valid language code: <samp>en-us</samp></p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Don't use the actual name of the language, like "English". Instead, use the 2- or 3-character language code, like "en" (ISO 639-1) or "eng" (ISO 639-2). (You can also specify a country code after it, like "en-us". This is optional, and the validator will ignore it.)</p>
|
||||
|
||||
<p>If you do include a country code, you need to separate the language code and the country code by a hyphen. "en-us" is valid; "en_us" is not.</p>
|
||||
|
||||
<p>The full set of language codes are defined by <a href="http://en.wikipedia.org/wiki/List_of_ISO_639_codes">ISO-639 language codes</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be between -90 and 90</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The value for elements expressing latitude must be a number between -90 and 90.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Use a number between -90 and 90 for the specified value.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be a valid URI</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The URI contains an invalid character. A complete list of acceptable characters can be found in <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Replace the invalid characters with the proper escape sequence. For example, "{" and "}" characters should be replaced with "%7B" and "%7D" respectively.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,24 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid local parameter name: <i>foo</i></p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified parameter name is not one of the predefined local parameter names:</p>
|
||||
<ul>
|
||||
<li>searchTerms</li>
|
||||
<li>count</li>
|
||||
<li>startIndex</li>
|
||||
<li>startPage</li>
|
||||
<li>language</li>
|
||||
<li>inputEncoding</li>
|
||||
<li>outputEncoding</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Either replace the parameter value with one listed in the
|
||||
<a href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_1.1_parameters">OpenSearch 1.1 specification</a>, or use a
|
||||
<a href="http://www.opensearch.org/Specifications/OpenSearch/1.1#Fully_qualified_parameter_names">fully qualified parameter name</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,35 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid local role: <i>foo</i></p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified role is not one of the permissable local role values:</p>
|
||||
<dl><dt><code>"request"</code></dt>
|
||||
<dd> Represents the search query that can be performed to retrieve the same set of search results.
|
||||
</dd>
|
||||
<dt><code>"example"</code></dt>
|
||||
<dd> Represents a search query that can be performed to demonstrate the search engine.
|
||||
</dd>
|
||||
<dt><code>"related"</code></dt>
|
||||
<dd> Represents a search query that can be performed to retrieve similar but different search results.
|
||||
</dd>
|
||||
<dt><code>"correction"</code></dt>
|
||||
<dd> Represents a search query that can be performed to improve the result set, such as with a spelling correction.
|
||||
</dd>
|
||||
<dt><code>"subset"</code></dt>
|
||||
<dd> Represents a search query that will narrow the current set of search results.
|
||||
</dd>
|
||||
<dt><code>"superset"</code></dt>
|
||||
|
||||
<dd> Represents a search query that will broaden the current set of search results.
|
||||
</dd></dl>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Either replace the role value with one listed in the
|
||||
<a href="http://www.opensearch.org/Specifications/OpenSearch/1.1#Local_role_values">OpenSearch 1.1 specification</a>, or use a
|
||||
<a href="http://www.opensearch.org/Specifications/OpenSearch/1.1#Local_role_values">fully qualified role.</a>.
|
||||
.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>foo</code>: "<code>bar</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>format is city and state/country, separated by a comma</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be between -180 and 180</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The value for elements expressing longitude must be a number between -180 and 180.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Use a number between -180 and 180 for the specified value.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,15 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> attribute of <code>bar</code> must be a valid MIME type</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The attribute value specified is not a value MIME type.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>This attribute must be a valid MIME content type as defined by <a href="http://www.faqs.org/rfcs/rfc2045.html">RFC 2045</a>.</p>
|
||||
|
||||
<p>This is an example of a valid MIME type: <samp>text/html</samp></p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,25 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> is not a valid MIME type</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>This attribute is not a valid MIME type.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Valid MIME types are specified in <a href="http://www.faqs.org/rfcs/rfc2046.html">RFC 2046</a>.</p>
|
||||
|
||||
<p>Examples of valid MIME types:</p>
|
||||
|
||||
<p><samp>application/xhtml+html</samp><br />
|
||||
<samp>text/html</samp><br />
|
||||
<samp>text/plain</samp></p>
|
||||
|
||||
<p>Examples of <em>invalid</em> MIME types:</p>
|
||||
|
||||
<p><samp>HTML</samp><br />
|
||||
<samp>text</samp><br />
|
||||
<samp>some stuff I threw together last night</samp></p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>g:marital_status</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Permissable values inclue "single", "divorced", "separated", "widowed", "married", and "in relationship".</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html#marital_status">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,18 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid content expression: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid media:content expression value.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute to one of the following:</p>
|
||||
<ul>
|
||||
<li>full</li>
|
||||
<li>nonstop</li>
|
||||
<li>sample</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,18 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid Media Hash</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<ul>
|
||||
<li><samp>algo</samp> must be <samp>'md5'</samp> or <samp>'sha-1'</samp></li>
|
||||
<li>value must be encoded as hex</li>
|
||||
<li>value length must be 32 for md5 or 40 for sha-1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Convert the hash to a valid value, and/or use the <samp>algo</samp>
|
||||
attribute to correctly indicate the hash algorithm used.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,20 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid content medium: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid media:content medium value.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute to one of the following:</p>
|
||||
<ul>
|
||||
<li>audio</li>
|
||||
<li>document</li>
|
||||
<li>executable</li>
|
||||
<li>image</li>
|
||||
<li>video</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,41 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid Media Rating</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<ul>
|
||||
<li><samp>scheme</samp> must be <samp>urn:simple</samp>,
|
||||
<samp>urn:mpaa</samp>, <samp>urn:v-chip</samp>, <samp>urn:icra</samp>,
|
||||
or a user defined URI. Default is <samp>urn:simple</samp></li>
|
||||
<li>for one of the predefined schemes, the value must be lowercase, and be
|
||||
one of the values listed below.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Select one of the schemes listed above, or use your own URI.</p>
|
||||
<p>For one of the predefined schemes, the values must be as follows:</p>
|
||||
<ul>
|
||||
|
||||
<li><b><samp>urn:simple</samp></b>:
|
||||
<samp>adult</samp>, <samp>nonadult</samp></li>
|
||||
|
||||
<li><b><samp>urn:mpaa</samp></b>:
|
||||
<samp>g</samp>, <samp>nc-17</samp>, <samp>pg</samp>,
|
||||
<samp>pg-13</samp>, <samp>r</samp>, <samp>x</samp></li>
|
||||
|
||||
<li><b><samp>urn:v-chip</samp></b>:
|
||||
<samp>14+</samp>, <samp>18+</samp>, <samp>c</samp>, <samp>c8</samp>,
|
||||
<samp>g</samp>, <samp>pg</samp>, <samp>tv-14</samp>, <samp>tv-g</samp>,
|
||||
<samp>tv-ma</samp>, <samp>tv-pg</samp>, <samp>tv-y</samp>, <samp>tv-y7</samp>,
|
||||
<samp>tv-y7-fv</samp></li>
|
||||
|
||||
<li><b><samp>urn:icra</samp></b>: Internet Content Rating Association labels
|
||||
consist of a <a href="http://www.icra.org/decode/">set of codes</a>
|
||||
(please select from the values defined in 2005) formatted per the following
|
||||
sample: <samp>r (cz 1 lz 1 mz 1 oz 1 vz 1)</samp></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,14 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>media:restriction</code> must be 'all' or 'none'</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid media:restriction value.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the value to either <code>all</code> or <code>none</code>.</p>
|
||||
<p>Or specify a type of either <code>country</code> or <code>uri</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>relationship</code> must be 'allow' or 'disallow'</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid media:restriction relationship value.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute value to either <code>allow</code> or <code>disallow</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>type</code> must be 'country' or 'uri'</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid media:restriction type value.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute value to either <code>country</code> or <code>uri</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,14 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>type attribute must be "plain" or "html"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The specified attribute value is not a valid value for this element.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the attribute value to either <code>plain</code> or <code>html</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>content</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The <code>content</code> of a Robots META tag can only be:
|
||||
<code>all</code>, <code>none</code>, <code>index</code>, <code>noindex</code>,
|
||||
<code>follow</code>, or <code>nofollow</code>; or non-conflicting and
|
||||
non-repeating combinations thereof, separated by commas.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://www.robotstxt.org/wc/meta-user.html">documentation for the Robots META tag</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>name</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Within a feed, the only expected value for <code>name</code> is <code>robots</code></p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://www.robotstxt.org/wc/meta-user.html">documentation for the Robots META tag</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be an NPT-time</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The value specified must adhere to the
|
||||
<a href="http://www.ietf.org/rfc/rfc2326.txt">RFC 2326</a>
|
||||
ntp-time format. </p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Convert the time into either a number of seconds, or a date of the format <samp>h:mm:ss.d</samp></p>
|
||||
<p>Examples of valid ntp-times:</p>
|
||||
<ul>
|
||||
<li><samp>now</samp></li>
|
||||
<li><samp>123.45</samp></li>
|
||||
<li><samp>123:05:35.030</samp></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,17 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> is in an invalid namespace</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The feed defines a default namespace that this validator does not recognize.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Atom does not allow arbitrary namespaces on the <code>feed</code> element. The correct namespace for Atom feeds is </p>
|
||||
|
||||
<p>http://www.w3.org/2005/Atom</p>
|
||||
|
||||
<p>For more information on Atom, see the <a href="http://intertwingly.net/wiki/pie/">Atom Project Wiki</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be a non-negative integer</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>This value must be an integer greater than or equal to zero. It can not be negative, or a decimal, or a fraction, or a string, or blank.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make the specified value a positive integer, or zero.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>The "version" attribute for the opml element must be <code>1.0</code> or <code>1.1</code>.</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The version of OPML is not supported by this validator.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Change the version attribute to either <code>1.0</code> or <code>1.1</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>g:payment_accepted</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>Acceptable values are "Cash", "Check", "Visa", "MasterCard", "AmericanExpress", "Discover" or "WireTransfer". If you accept more than one method, include multiple instances of the <payment_accepted> attribute for each acceptable method.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html#payment_accepted">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be a percentage</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>This value must be an floating point number greater than or equal to zero and less than or equal to 100. It can not be negative, or a fraction, or a string, or blank.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make the specified value a non-negative floating point number less than 100.0.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,31 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>guid</code> must be a full URL, unless isPermaLink attribute is false</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>By default, the <code>guid</code> element specifies a permanent link for an
|
||||
item, the value must be a full URL (for example, starting with
|
||||
"<code>http://</code>").</p>
|
||||
<p>URIs (such as <code>tag:</code> URIs), as opposed to URLs, only identify,
|
||||
not locate, items, and are not suitable for permalinks.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>If you are using the <code>guid</code> element as a permanent link, make sure
|
||||
the value is a full URL, that could be followed directly in a browser.</p>
|
||||
|
||||
<p>If you are using the <code>guid</code> element simply as a unique identifier
|
||||
(and not a link to the item), then the value can be whatever you want, but you
|
||||
must include the attribute <code>isPermaLink="false"</code> in the
|
||||
<code>guid</code> tag.</p>
|
||||
|
||||
<p>These are valid <code>guid</code>s:</p>
|
||||
|
||||
<ul>
|
||||
<li><samp><guid>http://www.example.com/archives/000054.html</guid></samp></li>
|
||||
<li><samp><guid isPermaLink="false">article 54 at example.com</guid></samp></li>
|
||||
<li><samp><guid isPermaLink="false">tag:blogger.com,1999:blog-555</guid></samp></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p><code>foo</code> must be a positive integer</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>This value must be an integer greater than zero. It can not be negative, or a decimal, or a fraction, or a string, or blank.</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make the specified value a positive integer.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,13 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>Invalid value for <code>g:price_type</code>: "<code>foo</code>"</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The type of pricing for the item. Acceptable values are "negotiable", or "starting".</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Consult the <a href="http://base.google.com/base/attribute_list.html#price_type">documentation for the attribute</a> for further details.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
|
@ -1,24 +0,0 @@
|
|||
<fvdoc>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<div id='message'>
|
||||
<p>RDF Parsing Error</p>
|
||||
</div>
|
||||
<div id='explanation'>
|
||||
<p>The feed uses an RDF format (RSS
|
||||
<a href="http://www.purplepages.ie/RSS/netscape/rss0.90.html" title="My Netscape Network - RSS 0.90 Specification">0.90</a>,
|
||||
<a href="http://web.resource.org/rss/1.0/" title="RDF Site Summary (RSS) 1.0">1.0</a>
|
||||
or
|
||||
<a href="http://inamidst.com/rss1.1/" title="RSS 1.1: RDF Site Summary (DRAFT)">1.1</a>),
|
||||
but is not valid RDF/XML
|
||||
(<a href="http://www.w3.org/TR/rdf-syntax-grammar/" title="RDF/XML Syntax Specification (Revised)">specification</a>).</p>
|
||||
</div>
|
||||
<div id='solution'>
|
||||
<p>Make sure your feed matches the structure given in the feed specification,
|
||||
including all <code>rdf:</code> attributes and elements. Check your feed
|
||||
against the RDF/XML spec, and make sure that it is valid
|
||||
RDF as well as well-formed XML. An RDF implementation with a tool such as
|
||||
<a href="http://librdf.org/raptor/rapper.html" title="Raptor RDF Parser Toolkit - Raptor RDF parser utility">rapper</a>
|
||||
can help to check for RDF validity.</p>
|
||||
</div>
|
||||
</div>
|
||||
</fvdoc>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue