linkchecker/linkcheck/checker/nntpurl.py

100 lines
3.5 KiB
Python

# -*- coding: iso-8859-1 -*-
"""Handle nntp: and news: links"""
# Copyright (C) 2000-2004 Bastian Kleineidam
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import re
import time
import sys
import nntplib
import urlparse
import random
import linkcheck
import urlbase
import linkcheck.log
from linkcheck.i18n import _
random.seed()
class NntpUrl (urlbase.UrlBase):
"Url link with NNTP scheme"
def build_url (self):
# use nntp instead of news to comply with the unofficial internet
# draft of Alfred Gilman which unifies (s)news and nntp URLs
# note: we use this only internally (for parsing and caching)
if self.base_url[:4].lower() == 'news':
self.url = 'nntp'+self.base_url[4:]
else:
self.url = self.base_url
self.urlparts = urlparse.urlsplit(self.url)
linkcheck.log.debug(linkcheck.LOG_CHECK, self.urlparts)
def check_connection (self):
nntpserver = self.urlparts[1] or self.consumer.config["nntpserver"]
if not nntpserver:
self.add_warning(_("No NNTP server specified, skipping this URL"))
return
nntp = self._connectNntp(nntpserver)
group = self.urlparts[2]
while group[:1] == '/':
group = group[1:]
if '@' in group:
# request article
resp, number, mid = nntp.stat("<"+group+">")
self.add_info(_('Articel number %s found') % number)
else:
# split off trailing articel span
group = group.split('/', 1)[0]
if group:
# request group info
resp, count, first, last, name = nntp.group(group)
self.add_info(_("Group %s has %s articles, range %s to %s") %\
(name, count, first, last))
else:
# group name is the empty string
self.add_warning(_("No newsgroup specified in NNTP URL"))
def _connectNntp (self, nntpserver):
"""This is done only once per checking task. Also, the newly
introduced error codes 504 and 505 (both inclining "Too busy, retry
later", are caught."""
tries = 0
nntp = value = None
while tries < 5:
tries += 1
try:
nntp = nntplib.NNTP(nntpserver)
except nntplib.error_perm:
value = sys.exc_info()[1]
if re.compile("^50[45]").search(str(value)):
time.sleep(random.randrange(10, 30))
else:
raise
if nntp is None:
raise linkcheck.LinkCheckerError(
_("NTTP server too busy; tried more than %d times")%tries)
if value is not None:
self.add_warning(_("NNTP busy: %s")%str(value))
return nntp
def get_cache_keys (self):
return [self.url]
def can_get_content (self):
return False