add perl5 support to Vx6.9 for openssl-3.1.7 (#1)
Reviewed-on: http://13.234.246.121:3000/Neominds/ossl35vx69/pulls/1 Reviewed-by: Jayesh Babu <jayesh@neominds.in> Co-authored-by: siddhant <siddhant.singh@neominds.in> Co-committed-by: siddhant <siddhant.singh@neominds.in>
This commit is contained in:
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,77 @@
|
||||
"""Exception classes raised by urllib.
|
||||
|
||||
The base exception class is URLError, which inherits from OSError. It
|
||||
doesn't define any behavior of its own, but is the base class for all
|
||||
exceptions defined in this package.
|
||||
|
||||
HTTPError is an exception class that is also a valid HTTP response
|
||||
instance. It behaves this way because HTTP protocol errors are valid
|
||||
responses, with a status code, headers, and a body. In some contexts,
|
||||
an application may want to handle an exception like a regular
|
||||
response.
|
||||
"""
|
||||
|
||||
import urllib.response
|
||||
|
||||
__all__ = ['URLError', 'HTTPError', 'ContentTooShortError']
|
||||
|
||||
|
||||
class URLError(OSError):
|
||||
# URLError is a sub-type of OSError, but it doesn't share any of
|
||||
# the implementation. need to override __init__ and __str__.
|
||||
# It sets self.args for compatibility with other OSError
|
||||
# subclasses, but args doesn't have the typical format with errno in
|
||||
# slot 0 and strerror in slot 1. This may be better than nothing.
|
||||
def __init__(self, reason, filename=None):
|
||||
self.args = reason,
|
||||
self.reason = reason
|
||||
if filename is not None:
|
||||
self.filename = filename
|
||||
|
||||
def __str__(self):
|
||||
return '<urlopen error %s>' % self.reason
|
||||
|
||||
|
||||
class HTTPError(URLError, urllib.response.addinfourl):
|
||||
"""Raised when HTTP error occurs, but also acts like non-error return"""
|
||||
__super_init = urllib.response.addinfourl.__init__
|
||||
|
||||
def __init__(self, url, code, msg, hdrs, fp):
|
||||
self.code = code
|
||||
self.msg = msg
|
||||
self.hdrs = hdrs
|
||||
self.fp = fp
|
||||
self.filename = url
|
||||
# The addinfourl classes depend on fp being a valid file
|
||||
# object. In some cases, the HTTPError may not have a valid
|
||||
# file object. If this happens, the simplest workaround is to
|
||||
# not initialize the base classes.
|
||||
if fp is not None:
|
||||
self.__super_init(fp, hdrs, url, code)
|
||||
|
||||
def __str__(self):
|
||||
return 'HTTP Error %s: %s' % (self.code, self.msg)
|
||||
|
||||
def __repr__(self):
|
||||
return '<HTTPError %s: %r>' % (self.code, self.msg)
|
||||
|
||||
# since URLError specifies a .reason attribute, HTTPError should also
|
||||
# provide this attribute. See issue13211 for discussion.
|
||||
@property
|
||||
def reason(self):
|
||||
return self.msg
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
return self.hdrs
|
||||
|
||||
@headers.setter
|
||||
def headers(self, headers):
|
||||
self.hdrs = headers
|
||||
|
||||
|
||||
class ContentTooShortError(URLError):
|
||||
"""Exception raised when downloaded size does not match content-length."""
|
||||
def __init__(self, message, content):
|
||||
URLError.__init__(self, message)
|
||||
self.content = content
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
"""Response classes used by urllib.
|
||||
|
||||
The base class, addbase, defines a minimal file-like interface,
|
||||
including read() and readline(). The typical response object is an
|
||||
addinfourl instance, which defines an info() method that returns
|
||||
headers and a geturl() method that returns the url.
|
||||
"""
|
||||
|
||||
import tempfile
|
||||
|
||||
__all__ = ['addbase', 'addclosehook', 'addinfo', 'addinfourl']
|
||||
|
||||
|
||||
class addbase(tempfile._TemporaryFileWrapper):
|
||||
"""Base class for addinfo and addclosehook. Is a good idea for garbage collection."""
|
||||
|
||||
# XXX Add a method to expose the timeout on the underlying socket?
|
||||
|
||||
def __init__(self, fp):
|
||||
super(addbase, self).__init__(fp, '<urllib response>', delete=False)
|
||||
# Keep reference around as this was part of the original API.
|
||||
self.fp = fp
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s at %r whose fp = %r>' % (self.__class__.__name__,
|
||||
id(self), self.file)
|
||||
|
||||
def __enter__(self):
|
||||
if self.fp.closed:
|
||||
raise ValueError("I/O operation on closed file")
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
|
||||
class addclosehook(addbase):
|
||||
"""Class to add a close hook to an open file."""
|
||||
|
||||
def __init__(self, fp, closehook, *hookargs):
|
||||
super(addclosehook, self).__init__(fp)
|
||||
self.closehook = closehook
|
||||
self.hookargs = hookargs
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
closehook = self.closehook
|
||||
hookargs = self.hookargs
|
||||
if closehook:
|
||||
self.closehook = None
|
||||
self.hookargs = None
|
||||
closehook(*hookargs)
|
||||
finally:
|
||||
super(addclosehook, self).close()
|
||||
|
||||
|
||||
class addinfo(addbase):
|
||||
"""class to add an info() method to an open file."""
|
||||
|
||||
def __init__(self, fp, headers):
|
||||
super(addinfo, self).__init__(fp)
|
||||
self.headers = headers
|
||||
|
||||
def info(self):
|
||||
return self.headers
|
||||
|
||||
|
||||
class addinfourl(addinfo):
|
||||
"""class to add info() and geturl() methods to an open file."""
|
||||
|
||||
def __init__(self, fp, headers, url, code=None):
|
||||
super(addinfourl, self).__init__(fp, headers)
|
||||
self.url = url
|
||||
self.code = code
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
return self.code
|
||||
|
||||
def getcode(self):
|
||||
return self.code
|
||||
|
||||
def geturl(self):
|
||||
return self.url
|
||||
@@ -0,0 +1,273 @@
|
||||
""" robotparser.py
|
||||
|
||||
Copyright (C) 2000 Bastian Kleineidam
|
||||
|
||||
You can choose between two licenses when using this package:
|
||||
1) GNU GPLv2
|
||||
2) PSF license for Python 2.2
|
||||
|
||||
The robots.txt Exclusion Protocol is implemented as specified in
|
||||
http://www.robotstxt.org/norobots-rfc.txt
|
||||
"""
|
||||
|
||||
import collections
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
__all__ = ["RobotFileParser"]
|
||||
|
||||
RequestRate = collections.namedtuple("RequestRate", "requests seconds")
|
||||
|
||||
|
||||
class RobotFileParser:
|
||||
""" This class provides a set of methods to read, parse and answer
|
||||
questions about a single robots.txt file.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, url=''):
|
||||
self.entries = []
|
||||
self.sitemaps = []
|
||||
self.default_entry = None
|
||||
self.disallow_all = False
|
||||
self.allow_all = False
|
||||
self.set_url(url)
|
||||
self.last_checked = 0
|
||||
|
||||
def mtime(self):
|
||||
"""Returns the time the robots.txt file was last fetched.
|
||||
|
||||
This is useful for long-running web spiders that need to
|
||||
check for new robots.txt files periodically.
|
||||
|
||||
"""
|
||||
return self.last_checked
|
||||
|
||||
def modified(self):
|
||||
"""Sets the time the robots.txt file was last fetched to the
|
||||
current time.
|
||||
|
||||
"""
|
||||
import time
|
||||
self.last_checked = time.time()
|
||||
|
||||
def set_url(self, url):
|
||||
"""Sets the URL referring to a robots.txt file."""
|
||||
self.url = url
|
||||
self.host, self.path = urllib.parse.urlparse(url)[1:3]
|
||||
|
||||
def read(self):
|
||||
"""Reads the robots.txt URL and feeds it to the parser."""
|
||||
try:
|
||||
f = urllib.request.urlopen(self.url)
|
||||
except urllib.error.HTTPError as err:
|
||||
if err.code in (401, 403):
|
||||
self.disallow_all = True
|
||||
elif err.code >= 400 and err.code < 500:
|
||||
self.allow_all = True
|
||||
else:
|
||||
raw = f.read()
|
||||
self.parse(raw.decode("utf-8").splitlines())
|
||||
|
||||
def _add_entry(self, entry):
|
||||
if "*" in entry.useragents:
|
||||
# the default entry is considered last
|
||||
if self.default_entry is None:
|
||||
# the first default entry wins
|
||||
self.default_entry = entry
|
||||
else:
|
||||
self.entries.append(entry)
|
||||
|
||||
def parse(self, lines):
|
||||
"""Parse the input lines from a robots.txt file.
|
||||
|
||||
We allow that a user-agent: line is not preceded by
|
||||
one or more blank lines.
|
||||
"""
|
||||
# states:
|
||||
# 0: start state
|
||||
# 1: saw user-agent line
|
||||
# 2: saw an allow or disallow line
|
||||
state = 0
|
||||
entry = Entry()
|
||||
|
||||
self.modified()
|
||||
for line in lines:
|
||||
if not line:
|
||||
if state == 1:
|
||||
entry = Entry()
|
||||
state = 0
|
||||
elif state == 2:
|
||||
self._add_entry(entry)
|
||||
entry = Entry()
|
||||
state = 0
|
||||
# remove optional comment and strip line
|
||||
i = line.find('#')
|
||||
if i >= 0:
|
||||
line = line[:i]
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
line = line.split(':', 1)
|
||||
if len(line) == 2:
|
||||
line[0] = line[0].strip().lower()
|
||||
line[1] = urllib.parse.unquote(line[1].strip())
|
||||
if line[0] == "user-agent":
|
||||
if state == 2:
|
||||
self._add_entry(entry)
|
||||
entry = Entry()
|
||||
entry.useragents.append(line[1])
|
||||
state = 1
|
||||
elif line[0] == "disallow":
|
||||
if state != 0:
|
||||
entry.rulelines.append(RuleLine(line[1], False))
|
||||
state = 2
|
||||
elif line[0] == "allow":
|
||||
if state != 0:
|
||||
entry.rulelines.append(RuleLine(line[1], True))
|
||||
state = 2
|
||||
elif line[0] == "crawl-delay":
|
||||
if state != 0:
|
||||
# before trying to convert to int we need to make
|
||||
# sure that robots.txt has valid syntax otherwise
|
||||
# it will crash
|
||||
if line[1].strip().isdigit():
|
||||
entry.delay = int(line[1])
|
||||
state = 2
|
||||
elif line[0] == "request-rate":
|
||||
if state != 0:
|
||||
numbers = line[1].split('/')
|
||||
# check if all values are sane
|
||||
if (len(numbers) == 2 and numbers[0].strip().isdigit()
|
||||
and numbers[1].strip().isdigit()):
|
||||
entry.req_rate = RequestRate(int(numbers[0]), int(numbers[1]))
|
||||
state = 2
|
||||
elif line[0] == "sitemap":
|
||||
# According to http://www.sitemaps.org/protocol.html
|
||||
# "This directive is independent of the user-agent line,
|
||||
# so it doesn't matter where you place it in your file."
|
||||
# Therefore we do not change the state of the parser.
|
||||
self.sitemaps.append(line[1])
|
||||
if state == 2:
|
||||
self._add_entry(entry)
|
||||
|
||||
def can_fetch(self, useragent, url):
|
||||
"""using the parsed robots.txt decide if useragent can fetch url"""
|
||||
if self.disallow_all:
|
||||
return False
|
||||
if self.allow_all:
|
||||
return True
|
||||
# Until the robots.txt file has been read or found not
|
||||
# to exist, we must assume that no url is allowable.
|
||||
# This prevents false positives when a user erroneously
|
||||
# calls can_fetch() before calling read().
|
||||
if not self.last_checked:
|
||||
return False
|
||||
# search for given user agent matches
|
||||
# the first match counts
|
||||
parsed_url = urllib.parse.urlparse(urllib.parse.unquote(url))
|
||||
url = urllib.parse.urlunparse(('','',parsed_url.path,
|
||||
parsed_url.params,parsed_url.query, parsed_url.fragment))
|
||||
url = urllib.parse.quote(url)
|
||||
if not url:
|
||||
url = "/"
|
||||
for entry in self.entries:
|
||||
if entry.applies_to(useragent):
|
||||
return entry.allowance(url)
|
||||
# try the default entry last
|
||||
if self.default_entry:
|
||||
return self.default_entry.allowance(url)
|
||||
# agent not found ==> access granted
|
||||
return True
|
||||
|
||||
def crawl_delay(self, useragent):
|
||||
if not self.mtime():
|
||||
return None
|
||||
for entry in self.entries:
|
||||
if entry.applies_to(useragent):
|
||||
return entry.delay
|
||||
if self.default_entry:
|
||||
return self.default_entry.delay
|
||||
return None
|
||||
|
||||
def request_rate(self, useragent):
|
||||
if not self.mtime():
|
||||
return None
|
||||
for entry in self.entries:
|
||||
if entry.applies_to(useragent):
|
||||
return entry.req_rate
|
||||
if self.default_entry:
|
||||
return self.default_entry.req_rate
|
||||
return None
|
||||
|
||||
def site_maps(self):
|
||||
if not self.sitemaps:
|
||||
return None
|
||||
return self.sitemaps
|
||||
|
||||
def __str__(self):
|
||||
entries = self.entries
|
||||
if self.default_entry is not None:
|
||||
entries = entries + [self.default_entry]
|
||||
return '\n\n'.join(map(str, entries))
|
||||
|
||||
|
||||
class RuleLine:
|
||||
"""A rule line is a single "Allow:" (allowance==True) or "Disallow:"
|
||||
(allowance==False) followed by a path."""
|
||||
def __init__(self, path, allowance):
|
||||
if path == '' and not allowance:
|
||||
# an empty value means allow all
|
||||
allowance = True
|
||||
path = urllib.parse.urlunparse(urllib.parse.urlparse(path))
|
||||
self.path = urllib.parse.quote(path)
|
||||
self.allowance = allowance
|
||||
|
||||
def applies_to(self, filename):
|
||||
return self.path == "*" or filename.startswith(self.path)
|
||||
|
||||
def __str__(self):
|
||||
return ("Allow" if self.allowance else "Disallow") + ": " + self.path
|
||||
|
||||
|
||||
class Entry:
|
||||
"""An entry has one or more user-agents and zero or more rulelines"""
|
||||
def __init__(self):
|
||||
self.useragents = []
|
||||
self.rulelines = []
|
||||
self.delay = None
|
||||
self.req_rate = None
|
||||
|
||||
def __str__(self):
|
||||
ret = []
|
||||
for agent in self.useragents:
|
||||
ret.append(f"User-agent: {agent}")
|
||||
if self.delay is not None:
|
||||
ret.append(f"Crawl-delay: {self.delay}")
|
||||
if self.req_rate is not None:
|
||||
rate = self.req_rate
|
||||
ret.append(f"Request-rate: {rate.requests}/{rate.seconds}")
|
||||
ret.extend(map(str, self.rulelines))
|
||||
return '\n'.join(ret)
|
||||
|
||||
def applies_to(self, useragent):
|
||||
"""check if this entry applies to the specified agent"""
|
||||
# split the name token and make it lower case
|
||||
useragent = useragent.split("/")[0].lower()
|
||||
for agent in self.useragents:
|
||||
if agent == '*':
|
||||
# we have the catch-all agent
|
||||
return True
|
||||
agent = agent.lower()
|
||||
if agent in useragent:
|
||||
return True
|
||||
return False
|
||||
|
||||
def allowance(self, filename):
|
||||
"""Preconditions:
|
||||
- our agent applies to this entry
|
||||
- filename is URL decoded"""
|
||||
for line in self.rulelines:
|
||||
if line.applies_to(filename):
|
||||
return line.allowance
|
||||
return True
|
||||
Reference in New Issue
Block a user