Compare commits
	
		
			No commits in common. "c8" and "c9s" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										32
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1,31 @@ | ||||
| SOURCES/dnspython-1.15.0.tar.gz | ||||
| /dnspython-1.10.0.tar.gz | ||||
| /dnspython-1.10.0.tar.gz.asc | ||||
| /dnspython3-1.10.0.tar.gz | ||||
| /dnspython3-1.10.0.tar.gz.asc | ||||
| /dnspython-1.11.0.tar.gz | ||||
| /dnspython-1.11.0.tar.gz.asc | ||||
| /dnspython3-1.11.0.tar.gz | ||||
| /dnspython3-1.11.0.tar.gz.asc | ||||
| /dnspython-1.11.1.tar.gz | ||||
| /dnspython-1.11.1.tar.gz.asc | ||||
| /dnspython3-1.11.1.tar.gz | ||||
| /dnspython3-1.11.1.tar.gz.asc | ||||
| /dnspython-1.12.0.tar.gz | ||||
| /dnspython-1.12.0.tar.gz.asc | ||||
| /dnspython3-1.12.0.tar.gz | ||||
| /dnspython3-1.12.0.tar.gz.asc | ||||
| /dnspython-1.12.0GIT465785f.tar.gz | ||||
| /dnspython3-1.12.0GIT465785f.tar.gz | ||||
| /dnspython3-1.12.0GITa4774ee.tar.gz | ||||
| /dnspython-1.12.0GITa4774ee.tar.gz | ||||
| /dnspython3-1.12.0GIT99fd864.tar.gz | ||||
| /dnspython-1.12.0GIT99fd864.tar.gz | ||||
| /dnspython-1.15.0.tar.gz | ||||
| /dnspython-1.16.0.tar.gz | ||||
| /v2.0.0rc1.tar.gz | ||||
| /v2.0.0.tar.gz | ||||
| /dnspython-2.0.0.tar.gz | ||||
| /dnspython-2.1.0rc1.tar.gz | ||||
| /dnspython-2.1.0.tar.gz | ||||
| /dnspython-2.3.0.tar.gz | ||||
| /dnspython-2.6.1.tar.gz | ||||
|  | ||||
| @ -1 +0,0 @@ | ||||
| fcb8edb4b307f68a27cd356e7b44f53512b63b5e SOURCES/dnspython-1.15.0.tar.gz | ||||
							
								
								
									
										61
									
								
								1000-use-setuptools-to-build-dnspython.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								1000-use-setuptools-to-build-dnspython.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| diff -Naur dnspython-2.6.1/pyproject.toml dnspython-2.6.1-mod/pyproject.toml
 | ||||
| --- dnspython-2.6.1/pyproject.toml	2024-02-18 15:35:12.000000000 -0300
 | ||||
| +++ dnspython-2.6.1-mod/pyproject.toml	2024-04-30 16:01:08.055650907 -0300
 | ||||
| @@ -6,7 +6,7 @@
 | ||||
|  name = "dnspython" | ||||
|  description = "DNS toolkit" | ||||
|  authors = [{ name = "Bob Halley", email = "halley@dnspython.org" }] | ||||
| -license = "ISC"
 | ||||
| +license = {text = "ISC"}
 | ||||
|  classifiers = [ | ||||
|      "Development Status :: 5 - Production/Stable", | ||||
|      "Intended Audience :: Developers", | ||||
| diff -Naur dnspython-2.6.1/setup.py dnspython-2.6.1-mod/setup.py
 | ||||
| --- dnspython-2.6.1/setup.py	1969-12-31 21:00:00.000000000 -0300
 | ||||
| +++ dnspython-2.6.1-mod/setup.py	2024-04-30 15:58:24.489890400 -0300
 | ||||
| @@ -0,0 +1,45 @@
 | ||||
| +#!/usr/bin/env python3
 | ||||
| +#
 | ||||
| +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
 | ||||
| +#
 | ||||
| +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
 | ||||
| +#
 | ||||
| +# Permission to use, copy, modify, and distribute this software and its
 | ||||
| +# documentation for any purpose with or without fee is hereby granted,
 | ||||
| +# provided that the above copyright notice and this permission notice
 | ||||
| +# appear in all copies.
 | ||||
| +#
 | ||||
| +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
 | ||||
| +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | ||||
| +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
 | ||||
| +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | ||||
| +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | ||||
| +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 | ||||
| +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | ||||
| +
 | ||||
| +import sys
 | ||||
| +from setuptools import setup, find_packages
 | ||||
| +
 | ||||
| +
 | ||||
| +try:
 | ||||
| +    sys.argv.remove("--cython-compile")
 | ||||
| +except ValueError:
 | ||||
| +    compile_cython = False
 | ||||
| +else:
 | ||||
| +    compile_cython = True
 | ||||
| +    from Cython.Build import cythonize
 | ||||
| +
 | ||||
| +    ext_modules = cythonize(
 | ||||
| +        ["dns/*.py", "dns/quic/*.py", "dns/rdtypes/*.py", "dns/rdtypes/*/*.py"],
 | ||||
| +        language_level="3",
 | ||||
| +    )
 | ||||
| +
 | ||||
| +kwargs = {
 | ||||
| +    "name": "dnspython",
 | ||||
| +    "version": "@VERSION@",
 | ||||
| +    "packages": find_packages(exclude=["tests"]),
 | ||||
| +    "ext_modules": ext_modules if compile_cython else None,
 | ||||
| +    "zip_safe": False if compile_cython else None,
 | ||||
| +}
 | ||||
| +
 | ||||
| +setup(**kwargs)
 | ||||
							
								
								
									
										178
									
								
								1001-disable-tests-due-to-etc-resolv-conf.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								1001-disable-tests-due-to-etc-resolv-conf.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,178 @@ | ||||
| diff -Naur dnspython-2.6.1-orig/tests/test_async.py dnspython-2.6.1-mod/tests/test_async.py
 | ||||
| --- dnspython-2.6.1-orig/tests/test_async.py	2024-08-12 11:30:25.845242476 -0300
 | ||||
| +++ dnspython-2.6.1-mod/tests/test_async.py	2024-08-12 17:57:20.266767286 -0300
 | ||||
| @@ -173,7 +173,7 @@
 | ||||
|          self.assertEqual(t, ("::", 53)) | ||||
|   | ||||
|   | ||||
| -@unittest.skipIf(not tests.util.is_internet_reachable(), "Internet not reachable")
 | ||||
| +@unittest.skip(reason="Build is failing to open /etc/resolv.conf.")
 | ||||
|  class AsyncTests(unittest.TestCase): | ||||
|      def setUp(self): | ||||
|          self.backend = dns.asyncbackend.set_default_backend("asyncio") | ||||
| @@ -597,7 +597,7 @@
 | ||||
|          self.async_run(run) | ||||
|   | ||||
|   | ||||
| -@unittest.skipIf(not tests.util.is_internet_reachable(), "Internet not reachable")
 | ||||
| +@unittest.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class AsyncioOnlyTests(unittest.TestCase): | ||||
|      def setUp(self): | ||||
|          self.backend = dns.asyncbackend.set_default_backend("asyncio") | ||||
| diff -Naur dnspython-2.6.1-orig/tests/test_resolver_override.py dnspython-2.6.1-mod/tests/test_resolver_override.py
 | ||||
| --- dnspython-2.6.1-orig/tests/test_resolver_override.py	2024-08-12 11:30:25.846242494 -0300
 | ||||
| +++ dnspython-2.6.1-mod/tests/test_resolver_override.py	2024-08-12 17:46:49.849623485 -0300
 | ||||
| @@ -11,7 +11,7 @@
 | ||||
|  import tests.util | ||||
|   | ||||
|   | ||||
| -@unittest.skipIf(not tests.util.is_internet_reachable(), "Internet not reachable")
 | ||||
| +@unittest.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class OverrideSystemResolverTestCase(unittest.TestCase): | ||||
|      def setUp(self): | ||||
|          self.res = dns.resolver.Resolver(configure=False) | ||||
| @@ -211,6 +211,7 @@
 | ||||
|          raise dns.exception.Timeout | ||||
|   | ||||
|   | ||||
| +@unittest.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class OverrideSystemResolverUsingFakeResolverTestCase(unittest.TestCase): | ||||
|      def setUp(self): | ||||
|          self.res = FakeResolver() | ||||
| @@ -240,7 +241,7 @@
 | ||||
|              socket.gethostbyaddr("bogus") | ||||
|   | ||||
|   | ||||
| -@unittest.skipIf(not tests.util.is_internet_reachable(), "Internet not reachable")
 | ||||
| +@unittest.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class OverrideSystemResolverUsingDefaultResolverTestCase(unittest.TestCase): | ||||
|      def setUp(self): | ||||
|          self.res = FakeResolver() | ||||
| diff -Naur dnspython-2.6.1-orig/tests/test_resolver.py dnspython-2.6.1-mod/tests/test_resolver.py
 | ||||
| --- dnspython-2.6.1-orig/tests/test_resolver.py	2024-08-12 11:30:25.846242494 -0300
 | ||||
| +++ dnspython-2.6.1-mod/tests/test_resolver.py	2024-08-12 17:53:19.968646375 -0300
 | ||||
| @@ -222,6 +222,7 @@
 | ||||
|              time.sleep(offset) | ||||
|   | ||||
|   | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf.")
 | ||||
|  class BaseResolverTests(unittest.TestCase): | ||||
|      def testRead(self): | ||||
|          f = StringIO(resolv_conf) | ||||
| @@ -628,7 +629,7 @@
 | ||||
|  keyname = dns.name.from_text("keyname") | ||||
|   | ||||
|   | ||||
| -@unittest.skipIf(not tests.util.is_internet_reachable(), "Internet not reachable")
 | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf.")
 | ||||
|  class LiveResolverTests(unittest.TestCase): | ||||
|      def testZoneForName1(self): | ||||
|          name = dns.name.from_text("www.dnspython.org.") | ||||
| @@ -830,6 +831,7 @@
 | ||||
|          unittest.TestCase.tearDown(self) | ||||
|   | ||||
|   | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class SelectResolverTestCase( | ||||
|      PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase | ||||
|  ): | ||||
| @@ -839,6 +841,7 @@
 | ||||
|   | ||||
|  if hasattr(selectors, "PollSelector"): | ||||
|   | ||||
| +    @pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|      class PollResolverTestCase( | ||||
|          PollingMonkeyPatchMixin, LiveResolverTests, unittest.TestCase | ||||
|      ): | ||||
| @@ -846,6 +849,7 @@
 | ||||
|              return selectors.PollSelector | ||||
|   | ||||
|   | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class NXDOMAINExceptionTestCase(unittest.TestCase): | ||||
|      # pylint: disable=broad-except | ||||
|   | ||||
| @@ -978,6 +982,7 @@
 | ||||
|          self.assertEqual(e2.canonical_name, dns.name.from_text(cname2)) | ||||
|   | ||||
|   | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf.")
 | ||||
|  class ResolverMiscTestCase(unittest.TestCase): | ||||
|      if sys.platform != "win32": | ||||
|   | ||||
| @@ -1007,6 +1012,7 @@
 | ||||
|              self.assertEqual(n, dns.win32util._config_domain(".home")) | ||||
|   | ||||
|   | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class ResolverNameserverValidTypeTestCase(unittest.TestCase): | ||||
|      def test_set_nameservers_to_list(self): | ||||
|          resolver = dns.resolver.Resolver(configure=False) | ||||
| @@ -1033,6 +1039,7 @@
 | ||||
|                  resolver.nameservers = invalid_nameserver | ||||
|   | ||||
|   | ||||
| +@unittest.skipIf(not tests.util.is_internet_reachable(), "Internet not reachable")
 | ||||
|  class NaptrNanoNameserver(Server): | ||||
|      def handle(self, request): | ||||
|          response = dns.message.make_response(request.message) | ||||
| @@ -1058,10 +1065,7 @@
 | ||||
|          return response | ||||
|   | ||||
|   | ||||
| -@unittest.skipIf(
 | ||||
| -    not (tests.util.is_internet_reachable() and _nanonameserver_available),
 | ||||
| -    "Internet and NanoAuth required",
 | ||||
| -)
 | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class NanoTests(unittest.TestCase): | ||||
|      def testE164Query(self): | ||||
|          with NaptrNanoNameserver() as na: | ||||
| @@ -1125,10 +1129,7 @@
 | ||||
|          return response | ||||
|   | ||||
|   | ||||
| -@unittest.skipIf(
 | ||||
| -    not (tests.util.is_internet_reachable() and _nanonameserver_available),
 | ||||
| -    "Internet and NanoAuth required",
 | ||||
| -)
 | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  class ZoneForNameTests(unittest.TestCase): | ||||
|      def testNoRootSOA(self): | ||||
|          with AlwaysType3NXDOMAINNanoNameserver() as na: | ||||
| @@ -1177,10 +1178,7 @@
 | ||||
|  # (right now it's still fast enough we don't really need it) | ||||
|   | ||||
|   | ||||
| -@pytest.mark.skipif(
 | ||||
| -    not (tests.util.is_internet_reachable() and _nanonameserver_available),
 | ||||
| -    reason="Internet and NanoAuth required",
 | ||||
| -)
 | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  def testResolverTimeout(): | ||||
|      with DroppingNanoNameserver() as na: | ||||
|          res = dns.resolver.Resolver(configure=False) | ||||
| @@ -1204,10 +1202,7 @@
 | ||||
|                  assert isinstance(error[3], dns.exception.Timeout)  # exception | ||||
|   | ||||
|   | ||||
| -@pytest.mark.skipif(
 | ||||
| -    not (tests.util.is_internet_reachable() and _nanonameserver_available),
 | ||||
| -    reason="Internet and NanoAuth required",
 | ||||
| -)
 | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  def testResolverNoNameservers(): | ||||
|      with FormErrNanoNameserver() as na: | ||||
|          res = dns.resolver.Resolver(configure=False) | ||||
| @@ -1235,10 +1230,7 @@
 | ||||
|          return response | ||||
|   | ||||
|   | ||||
| -@pytest.mark.skipif(
 | ||||
| -    not (tests.util.is_internet_reachable() and _nanonameserver_available),
 | ||||
| -    reason="Internet and NanoAuth required",
 | ||||
| -)
 | ||||
| +@pytest.mark.skip(reason="Build is failing to open /etc/resolv.conf")
 | ||||
|  def testZoneForNameLifetimeTimeout(): | ||||
|      with SlowAlwaysType3NXDOMAINNanoNameserver() as na: | ||||
|          res = dns.resolver.Resolver(configure=False) | ||||
| @ -1,99 +0,0 @@ | ||||
| From a77e0c662c6d5b8224ac1e283aee8353bcd1536e Mon Sep 17 00:00:00 2001 | ||||
| From: Lumir Balhar <lbalhar@redhat.com> | ||||
| Date: Mon, 22 Apr 2024 16:49:15 +0200 | ||||
| Subject: [PATCH] CVE-2023-29483 | ||||
| 
 | ||||
| ---
 | ||||
|  dns/query.py | 60 +++++++++++++++++++++++++++++++++++----------------- | ||||
|  1 file changed, 41 insertions(+), 19 deletions(-) | ||||
| 
 | ||||
| diff --git a/dns/query.py b/dns/query.py
 | ||||
| index 19b9fbb..2dba3cc 100644
 | ||||
| --- a/dns/query.py
 | ||||
| +++ b/dns/query.py
 | ||||
| @@ -170,6 +170,22 @@ def _addresses_equal(af, a1, a2):
 | ||||
|      return n1 == n2 and a1[1:] == a2[1:] | ||||
|   | ||||
|   | ||||
| +def _matches_destination(af, from_address, destination, ignore_unexpected):
 | ||||
| +    # Check that from_address is appropriate for a response to a query
 | ||||
| +    # sent to destination.
 | ||||
| +    if not destination:
 | ||||
| +        return True
 | ||||
| +    if _addresses_equal(af, from_address, destination) or (
 | ||||
| +        dns.inet.is_multicast(destination[0]) and from_address[1:] == destination[1:]
 | ||||
| +    ):
 | ||||
| +        return True
 | ||||
| +    elif ignore_unexpected:
 | ||||
| +        return False
 | ||||
| +    raise UnexpectedSource(
 | ||||
| +        f"got a response from {from_address} instead of " f"{destination}"
 | ||||
| +    )
 | ||||
| +
 | ||||
| +
 | ||||
|  def _destination_and_source(af, where, port, source, source_port): | ||||
|      # Apply defaults and compute destination and source tuples | ||||
|      # suitable for use in connect(), sendto(), or bind(). | ||||
| @@ -194,7 +210,7 @@ def _destination_and_source(af, where, port, source, source_port):
 | ||||
|   | ||||
|   | ||||
|  def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0, | ||||
| -        ignore_unexpected=False, one_rr_per_rrset=False):
 | ||||
| +        ignore_unexpected=False, one_rr_per_rrset=False, ignore_errors=False):
 | ||||
|      """Return the response obtained after sending a query via UDP. | ||||
|   | ||||
|      @param q: the query | ||||
| @@ -239,26 +255,32 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
 | ||||
|          while 1: | ||||
|              _wait_for_readable(s, expiration) | ||||
|              (wire, from_address) = s.recvfrom(65535) | ||||
| -            if _addresses_equal(af, from_address, destination) or \
 | ||||
| -                    (dns.inet.is_multicast(where) and
 | ||||
| -                     from_address[1:] == destination[1:]):
 | ||||
| -                break
 | ||||
| -            if not ignore_unexpected:
 | ||||
| -                raise UnexpectedSource('got a response from '
 | ||||
| -                                       '%s instead of %s' % (from_address,
 | ||||
| -                                                             destination))
 | ||||
| -    finally:
 | ||||
| -        if begin_time is None:
 | ||||
| -            response_time = 0
 | ||||
| -        else:
 | ||||
| +            if not _matches_destination(
 | ||||
| +                s.family, from_address, destination, ignore_unexpected
 | ||||
| +            ):
 | ||||
| +                continue
 | ||||
| +
 | ||||
|              response_time = time.time() - begin_time | ||||
| +
 | ||||
| +            try:
 | ||||
| +                r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
 | ||||
| +                                  one_rr_per_rrset=one_rr_per_rrset)
 | ||||
| +                r.time = response_time
 | ||||
| +            except Exception:
 | ||||
| +                if ignore_errors:
 | ||||
| +                    continue
 | ||||
| +                else:
 | ||||
| +                    raise
 | ||||
| +
 | ||||
| +            if q.is_response(r):
 | ||||
| +                return r
 | ||||
| +            else:
 | ||||
| +                if ignore_errors:
 | ||||
| +                    continue
 | ||||
| +                else:
 | ||||
| +                    raise BadResponse
 | ||||
| +    finally:
 | ||||
|          s.close() | ||||
| -    r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
 | ||||
| -                              one_rr_per_rrset=one_rr_per_rrset)
 | ||||
| -    r.time = response_time
 | ||||
| -    if not q.is_response(r):
 | ||||
| -        raise BadResponse
 | ||||
| -    return r
 | ||||
|   | ||||
|   | ||||
|  def _net_read(sock, count, expiration): | ||||
| -- 
 | ||||
| 2.44.0 | ||||
| 
 | ||||
| @ -1,161 +0,0 @@ | ||||
| From c28f0584ba37cd6b0e9919dcbec652a34a420843 Mon Sep 17 00:00:00 2001 | ||||
| From: Lumir Balhar <lbalhar@redhat.com> | ||||
| Date: Wed, 28 Aug 2019 14:10:36 +0200 | ||||
| Subject: [PATCH] Backported original patch from: | ||||
|  https://github.com/rthalley/dnspython/commit/c76aa6ac9969447220c8e807aa1e5640a6c12924 | ||||
| 
 | ||||
| Unicode label escapify was not escapifying special characters. [Issue #339] | ||||
| ---
 | ||||
|  dns/name.py        | 57 +++++++++++++++++++++++----------------------- | ||||
|  tests/test_name.py |  5 ++++ | ||||
|  2 files changed, 34 insertions(+), 28 deletions(-) | ||||
| 
 | ||||
| diff --git a/dns/name.py b/dns/name.py
 | ||||
| index 97e216c..4a064d6 100644
 | ||||
| --- a/dns/name.py
 | ||||
| +++ b/dns/name.py
 | ||||
| @@ -116,20 +116,28 @@ class IDNACodec(object):
 | ||||
|      def __init__(self): | ||||
|          pass | ||||
|   | ||||
| +    def is_idna(self, label):
 | ||||
| +        return label.lower().startswith(b'xn--')
 | ||||
| +
 | ||||
| +    def is_all_ascii(self, label):
 | ||||
| +        for c in label:
 | ||||
| +            if ord(c) > 0x7f:
 | ||||
| +                return False
 | ||||
| +        return True
 | ||||
| +
 | ||||
|      def encode(self, label): | ||||
|          raise NotImplementedError | ||||
|   | ||||
|      def decode(self, label): | ||||
| -        # We do not apply any IDNA policy on decode; we just
 | ||||
| -        downcased = label.lower()
 | ||||
| -        if downcased.startswith(b'xn--'):
 | ||||
| +        # We do not apply any IDNA policy on decode.
 | ||||
| +        if self.is_idna(label):
 | ||||
|              try: | ||||
| -                label = downcased[4:].decode('punycode')
 | ||||
| +                label = label[4:].decode('punycode')
 | ||||
|              except Exception as e: | ||||
|                  raise IDNAException(idna_exception=e) | ||||
|          else: | ||||
|              label = maybe_decode(label) | ||||
| -        return _escapify(label, True)
 | ||||
| +        return _escapify(label)
 | ||||
|   | ||||
|  class IDNA2003Codec(IDNACodec): | ||||
|   | ||||
| @@ -159,7 +167,7 @@ class IDNA2003Codec(IDNACodec):
 | ||||
|          if label == b'': | ||||
|              return u'' | ||||
|          try: | ||||
| -            return _escapify(encodings.idna.ToUnicode(label), True)
 | ||||
| +            return _escapify(encodings.idna.ToUnicode(label))
 | ||||
|          except Exception as e: | ||||
|              raise IDNAException(idna_exception=e) | ||||
|   | ||||
| @@ -197,12 +205,6 @@ class IDNA2008Codec(IDNACodec):
 | ||||
|          self.allow_pure_ascii = allow_pure_ascii | ||||
|          self.strict_decode = strict_decode | ||||
|   | ||||
| -    def is_all_ascii(self, label):
 | ||||
| -        for c in label:
 | ||||
| -            if ord(c) > 0x7f:
 | ||||
| -                return False
 | ||||
| -        return True
 | ||||
| -
 | ||||
|      def encode(self, label): | ||||
|          if label == '': | ||||
|              return b'' | ||||
| @@ -227,11 +229,12 @@ class IDNA2008Codec(IDNACodec):
 | ||||
|          try: | ||||
|              if self.uts_46: | ||||
|                  label = idna.uts46_remap(label, False, False) | ||||
| -            return _escapify(idna.ulabel(label), True)
 | ||||
| +            return _escapify(idna.ulabel(label))
 | ||||
|          except idna.IDNAError as e: | ||||
|              raise IDNAException(idna_exception=e) | ||||
|   | ||||
|  _escaped = bytearray(b'"().;\\@$') | ||||
| +_escaped_text = '"().;\\@$'
 | ||||
|   | ||||
|  IDNA_2003_Practical = IDNA2003Codec(False) | ||||
|  IDNA_2003_Strict = IDNA2003Codec(True) | ||||
| @@ -242,13 +245,13 @@ IDNA_2008_Strict = IDNA2008Codec(False, False, False, True)
 | ||||
|  IDNA_2008_Transitional = IDNA2008Codec(True, True, False, False) | ||||
|  IDNA_2008 = IDNA_2008_Practical | ||||
|   | ||||
| -def _escapify(label, unicode_mode=False):
 | ||||
| +def _escapify(label):
 | ||||
|      """Escape the characters in label which need it. | ||||
| -    @param unicode_mode: escapify only special and whitespace (<= 0x20)
 | ||||
| -    characters
 | ||||
|      @returns: the escaped string | ||||
|      @rtype: string""" | ||||
| -    if not unicode_mode:
 | ||||
| +    if isinstance(label, bytes):
 | ||||
| +        # Ordinary DNS label mode.  Escape special characters and values
 | ||||
| +        # < 0x20 or > 0x7f.
 | ||||
|          text = '' | ||||
|          if isinstance(label, text_type): | ||||
|              label = label.encode() | ||||
| @@ -259,19 +262,17 @@ def _escapify(label, unicode_mode=False):
 | ||||
|                  text += chr(c) | ||||
|              else: | ||||
|                  text += '\\%03d' % c | ||||
| -        return text.encode()
 | ||||
| +        return text
 | ||||
|   | ||||
| +    # Unicode label mode.  Escape only special characters and values < 0x20
 | ||||
|      text = u'' | ||||
| -    if isinstance(label, binary_type):
 | ||||
| -        label = label.decode()
 | ||||
|      for c in label: | ||||
| -        if c > u'\x20' and c < u'\x7f':
 | ||||
| -            text += c
 | ||||
| +        if c in _escaped_text:
 | ||||
| +            text += '\\' + c
 | ||||
| +        elif c <= '\x20':
 | ||||
| +            text += '\\%03d' % ord(c)
 | ||||
|          else: | ||||
| -            if c >= u'\x7f':
 | ||||
| -                text += c
 | ||||
| -            else:
 | ||||
| -                text += u'\\%03d' % ord(c)
 | ||||
| +            text += c
 | ||||
|      return text | ||||
|   | ||||
|  def _validate_labels(labels): | ||||
| @@ -519,8 +520,8 @@ class Name(object):
 | ||||
|              l = self.labels[:-1] | ||||
|          else: | ||||
|              l = self.labels | ||||
| -        s = b'.'.join(map(_escapify, l))
 | ||||
| -        return maybe_decode(s)
 | ||||
| +        s = '.'.join(map(_escapify, l))
 | ||||
| +        return s
 | ||||
|   | ||||
|      def to_unicode(self, omit_final_dot=False, idna_codec=None): | ||||
|          """Convert name to Unicode text format. | ||||
| diff --git a/tests/test_name.py b/tests/test_name.py
 | ||||
| index f2a8773..fa1d3eb 100644
 | ||||
| --- a/tests/test_name.py
 | ||||
| +++ b/tests/test_name.py
 | ||||
| @@ -255,6 +255,11 @@ class NameTestCase(unittest.TestCase):
 | ||||
|          t = dns.name.root.to_unicode() | ||||
|          self.assertEqual(t, '.') | ||||
|   | ||||
| +    def testToText12(self):
 | ||||
| +            n = dns.name.from_text(r'a\.b.c')
 | ||||
| +            t = n.to_unicode()
 | ||||
| +            self.assertEqual(t, r'a\.b.c.')
 | ||||
| +
 | ||||
|      def testSlice1(self): | ||||
|          n = dns.name.from_text(r'a.b.c.', origin=None) | ||||
|          s = n[:] | ||||
| -- 
 | ||||
| 2.21.0 | ||||
| 
 | ||||
| @ -1,14 +0,0 @@ | ||||
| diff --git a/dns/query.py b/dns/query.py
 | ||||
| index bfecd43..19b9fbb 100644
 | ||||
| --- a/dns/query.py
 | ||||
| +++ b/dns/query.py
 | ||||
| @@ -467,7 +467,8 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
 | ||||
|      first = True | ||||
|      while not done: | ||||
|          mexpiration = _compute_expiration(timeout) | ||||
| -        if mexpiration is None or mexpiration > expiration:
 | ||||
| +        if mexpiration is None or \
 | ||||
| +           (expiration is not None and mexpiration > expiration):
 | ||||
|              mexpiration = expiration | ||||
|          if use_udp: | ||||
|              _wait_for_readable(s, expiration) | ||||
| @ -1,12 +0,0 @@ | ||||
| diff -ruN /home/avram/Desktop/dnspython-1.15.0.orig/tests/test_zone.py /home/avram/Desktop/dnspython-1.15.0/tests/test_zone.py
 | ||||
| --- a/tests/test_zone.py	2016-09-20 12:24:02.000000000 -0400
 | ||||
| +++ b/tests/test_zone.py	2016-10-04 07:59:39.717946790 -0400
 | ||||
| @@ -177,7 +177,7 @@
 | ||||
|      def testToFileFilename(self): | ||||
|          z = dns.zone.from_file(here('example'), 'example') | ||||
|          try: | ||||
| -            z.to_file('example3-filename.out')
 | ||||
| +            z.to_file(here('example3-filename.out'))
 | ||||
|              ok = filecmp.cmp(here('example3-filename.out'), | ||||
|                               here('example3.good')) | ||||
|          finally: | ||||
							
								
								
									
										7
									
								
								gating.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								gating.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| # recipients: abokovoy, frenaud, kaleem, ftrivino, rjeffman | ||||
| --- !Policy | ||||
| product_versions: | ||||
|   - rhel-9 | ||||
| decision_context: osci_compose_gate | ||||
| rules: | ||||
|   - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1.functional} | ||||
| @ -1,33 +1,44 @@ | ||||
| %global pypi_name dnspython | ||||
| %global py_package_name dns | ||||
| %global rctag %{nil} | ||||
| 
 | ||||
| %if 0%{?rhel} | ||||
| %bcond_with trio | ||||
| %bcond_with doh | ||||
| %else | ||||
| %bcond_without trio | ||||
| %bcond_without doh | ||||
| %endif | ||||
| 
 | ||||
| Name:           python-dns | ||||
| Version:        1.15.0 | ||||
| Release:        12%{?dist} | ||||
| Version:        2.6.1 | ||||
| Release:        3%{?dist} | ||||
| Summary:        DNS toolkit for Python | ||||
| 
 | ||||
| License:        MIT | ||||
| URL:            http://www.dnspython.org/ | ||||
| 
 | ||||
| Source0: http://www.dnspython.org/kits/%{version}/dnspython-%{version}.tar.gz | ||||
| # The entire package is licensed with both licenses, see LICENSE file | ||||
| License:        ISC | ||||
| URL:            https://www.dnspython.org | ||||
| 
 | ||||
| Source0:        https://github.com/rthalley/%{pypi_name}/archive/v%{version}%{rctag}/%{pypi_name}-%{version}%{rctag}.tar.gz | ||||
| Patch1000:      1000-use-setuptools-to-build-dnspython.patch | ||||
| Patch1001:      1001-disable-tests-due-to-etc-resolv-conf.patch | ||||
| BuildArch:      noarch | ||||
| Patch0:         test_fails_on_missing_file.patch | ||||
| # Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1731081 | ||||
| # Upstream issue: https://github.com/rthalley/dnspython/issues/339 | ||||
| Patch1:         fix_unicode_label_escaping.patch | ||||
| 
 | ||||
| # Fixes https://bugzilla.redhat.com/show_bug.cgi?id=2075187 | ||||
| # Backported from upstream: https://github.com/rthalley/dnspython/commit/9fbf9b223dc26262b1cf23f623f89283ee9c8375 | ||||
| Patch2:         float_none_comparison_fix.patch | ||||
| 
 | ||||
| # Fix for CVE-2023-29483 | ||||
| # Upstream fix: | ||||
| #   https://github.com/rthalley/dnspython/commit/f66e25b5f549acf66d1fb6ead13eb3cff7d09af3 | ||||
| # Backported to completely different codebase hence not very similar to upstream fix. | ||||
| Patch3:         CVE-2023-29483.patch | ||||
| 
 | ||||
| BuildRequires:  python3-devel | ||||
| BuildRequires:  python3-setuptools | ||||
| BuildRequires:  python3-cryptography | ||||
| %if %{with trio} | ||||
| BuildRequires:  python3-trio | ||||
| BuildRequires:  python3-sniffio | ||||
| %endif | ||||
| %if %{with doh} | ||||
| BuildRequires:  python3-requests | ||||
| BuildRequires:  python3-requests-toolbelt | ||||
| %endif | ||||
| BuildRequires:  python3-idna | ||||
| BuildRequires:  python3-pytest | ||||
| 
 | ||||
| %description | ||||
| %global _description %{expand: | ||||
| dnspython is a DNS toolkit for Python. It supports almost all record | ||||
| types. It can be used for queries, zone transfers, and dynamic | ||||
| updates. It supports TSIG authenticated messages and EDNS0. | ||||
| @ -36,73 +47,178 @@ dnspython provides both high and low level access to DNS. The high | ||||
| level classes perform queries for data of a given name, type, and | ||||
| class, and return an answer set. The low level classes allow direct | ||||
| manipulation of DNS zones, messages, names, and records. | ||||
| } | ||||
| 
 | ||||
| %description %_description | ||||
| %package -n python3-%{py_package_name} | ||||
| Summary:        %{summary} | ||||
| 
 | ||||
| %package     -n python3-dns | ||||
| Summary:        DNS toolkit for Python 3 | ||||
| %{?python_provide:%python_provide python3-dns} | ||||
| 
 | ||||
| %description -n python3-dns | ||||
| dnspython3 is a DNS toolkit for Python 3. It supports almost all | ||||
| record types. It can be used for queries, zone transfers, and dynamic | ||||
| updates. It supports TSIG authenticated messages and EDNS0. | ||||
| 
 | ||||
| dnspython3 provides both high and low level access to DNS. The high | ||||
| level classes perform queries for data of a given name, type, and | ||||
| class, and return an answer set. The low level classes allow direct | ||||
| manipulation of DNS zones, messages, names, and records. | ||||
| %{?python_provide:%python_provide python3-%{py_package_name}} | ||||
| 
 | ||||
| %description -n python3-%{py_package_name} %_description | ||||
| 
 | ||||
| %prep | ||||
| %autosetup -p1 -n dnspython-%{version} | ||||
| %autosetup -p1 -n %{pypi_name}-%{version}%{rctag} | ||||
| 
 | ||||
| # Fix package version. | ||||
| sed -i -e "s/@VERSION@/%{version}/" setup.py | ||||
| 
 | ||||
| # strip exec permissions so that we don't pick up dependencies from docs | ||||
| find examples -type f | xargs chmod a-x | ||||
| 
 | ||||
| 
 | ||||
| %build | ||||
| %py3_build | ||||
| 
 | ||||
| 
 | ||||
| %install | ||||
| %py3_install | ||||
| 
 | ||||
| 
 | ||||
| %check | ||||
| %{__python3} setup.py test | ||||
| export OPENSSL_ENABLE_SHA1_SIGNATURES=yes | ||||
| pytest | ||||
| 
 | ||||
| 
 | ||||
| %files -n python3-dns | ||||
| # Add README.* when it is included with the source (commit a906279) | ||||
| %doc ChangeLog examples | ||||
| %files -n python3-%{py_package_name} | ||||
| %license LICENSE | ||||
| %{python3_sitelib}/*egg-info | ||||
| %{python3_sitelib}/dns | ||||
| %doc README.md examples | ||||
| %pycached %exclude %{python3_sitelib}/dns/_trio_backend.py | ||||
| %{python3_sitelib}/%{py_package_name} | ||||
| %{python3_sitelib}/%{pypi_name}-*.egg-info | ||||
| 
 | ||||
| %python_extras_subpkg -n python3-dns -i %{python3_sitelib}/dns/__init__.py dnssec idna | ||||
| 
 | ||||
| %if %{with doh} | ||||
| %python_extras_subpkg -n python3-dns -i %{python3_sitelib}/dns/__init__.py doh | ||||
| %endif | ||||
| 
 | ||||
| %if %{with trio} | ||||
| %python_extras_subpkg -n python3-dns -i %{python3_sitelib}/dns/__init__.py trio | ||||
| %pycached %{python3_sitelib}/dns/_trio_backend.py | ||||
| %endif | ||||
| 
 | ||||
| %changelog | ||||
| * Mon Apr 22 2024 Lumír Balhar <lbalhar@redhat.com> - 1.15.0-12 | ||||
| - Security fix for CVE-2023-29483 | ||||
| Resolves: RHEL-32630 | ||||
| * Tue Aug 20 2024 Rafael Jeffman <rjeffman@redhat.com> - 2.6.1-3 | ||||
| - Ensure dns.rdtypes subpackages are available | ||||
|   Related: RHEL-32663 | ||||
| 
 | ||||
| * Thu Apr 21 2022 Charalampos Stratakis <cstratak@redhat.com> - 1.15.0-11 | ||||
| - Fix comparison between float and None types | ||||
| Resolves: rhbz#2075187 | ||||
| * Mon Aug 19 2024 Rafael Jeffman <rjeffman@redhat.com> - 2.6.1-2 | ||||
| - Add missing files due to build change from hatchling to setuptools | ||||
|   Related: RHEL-32663 | ||||
| 
 | ||||
| * Thu Oct 24 2019 Lumír Balhar <lbalhar@redhat.com> - 1.15.0-10 | ||||
| - Release bump for gating | ||||
| Related: rhbz#1731081 | ||||
| * Fri Aug 16 2024 Rafael Jeffman <rjeffman@redhat.com> - 2.6.1-1 | ||||
| - Rebase to 2.6.1 | ||||
|   Resolves: RHEL-32628, RHEL-32663 | ||||
| 
 | ||||
| * Wed Aug 28 2019 Lumír Balhar <lbalhar@redhat.com> - 1.15.0-9 | ||||
| - Fix unicode label escaping | ||||
| Resolves: rhbz#1731081 | ||||
| * Mon Jun 26 2023 Rafael Jeffman <rjeffman@redhat.com> - 2.3.0-2 | ||||
| - Fix build for legacy setup.py | ||||
|   Related: rhbz#2177854 | ||||
| 
 | ||||
| * Mon Aug 27 2018 Miro Hrončok <mhroncok@redhat.com> - 1.15.0-8 | ||||
| - Drop python2 subpackage (#1567168) | ||||
| * Wed May 17 2023 Rafael Jeffman <rjeffman@redhat.com> - 2.3.0-1 | ||||
| - Rebase to version 2.3.0 | ||||
|   Resolves: rhbz#2177854 | ||||
| 
 | ||||
| * Mon Jun 25 2018 Petr Viktorin <pviktori@redhat.com> - 1.15.0-7 | ||||
| - Allow Python 2 for build | ||||
|   see https://hurl.corp.redhat.com/rhel8-py2 | ||||
| * Sat Jan 07 2023 Rafael Jeffman <rjeffman@redhat.com> - 2.2.1-2 | ||||
| - Remove pycache from patch 0003. | ||||
|   Related: rhbz#2107651 | ||||
| 
 | ||||
| * Fri Jan 06 2023 Rafael Jeffman <rjeffman@redhat.com> - 2.2.1-1 | ||||
| - Rebase to version 2.2.1 | ||||
|   Resolves: rhbz#2088661 | ||||
| - Disable DNSSEC tests using SHA1 due to crypto policies | ||||
|   Resolves: rhbz#2107651 | ||||
| 
 | ||||
| * Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 2.1.0-6 | ||||
| - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags | ||||
|   Related: rhbz#1991688 | ||||
| 
 | ||||
| * Thu Apr 22 2021 Rafael Jeffman <rjeffman@redhat.com> - 2.1.0-5 | ||||
| - Skip tests that require external network connection. | ||||
| 
 | ||||
| * Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 2.1.0-4 | ||||
| - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 | ||||
| 
 | ||||
| * Tue Mar 09 2021 Christian Heimes <cheimes@redhat.com> - 2.1.0-3 | ||||
| - Add bconds for extras require trio, curio, and doh | ||||
| - Move trio and curio backend modules into extras subpackages | ||||
| - Enable python3-dns+curio meta package | ||||
| - Skip failing test testCanonicalNameDangling | ||||
| 
 | ||||
| * Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.0-2 | ||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild | ||||
| 
 | ||||
| * Fri Jan 08 2021 Lumír Balhar <lbalhar@redhat.com> - 2.1.0-1 | ||||
| - Update to 2.1.0 final (#1913860) | ||||
| 
 | ||||
| * Fri Nov 27 2020 Lumír Balhar <lbalhar@redhat.com> - 2.1.0-0.2.rc1 | ||||
| - Fix upstream issue in resolve chaining | ||||
| 
 | ||||
| * Wed Nov 18 2020 Lumír Balhar <lbalhar@redhat.com> - 2.1.0-0.1.rc1 | ||||
| - Update to 2.1.0-0.1.rc1 (#1893295) | ||||
| 
 | ||||
| * Thu Jul 30 2020 Lumír Balhar <lbalhar@redhat.com> - 2.0.0-1 | ||||
| - Update to 2.0.0 (#1849341) | ||||
| - python2-dns moved to its own SRPM | ||||
| 
 | ||||
| * Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.16.0-13 | ||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild | ||||
| 
 | ||||
| * Sun May 24 2020 Miro Hrončok <mhroncok@redhat.com> - 1.16.0-12 | ||||
| - Rebuilt for Python 3.9 | ||||
| 
 | ||||
| * Tue Apr 28 2020 Lumír Balhar <lbalhar@redhat.com> - 1.16.0-11 | ||||
| - Switch crypto backend to python-cryptography | ||||
| Related to: rhbz#1819086 | ||||
| 
 | ||||
| * Fri Apr 17 2020 Lumír Balhar <lbalhar@redhat.com> - 1.16.0-10 | ||||
| - Bring python2 subpackage back | ||||
| - Fix weak dependencies | ||||
| 
 | ||||
| * Wed Apr 15 2020 Paul Wouters <pwouters@redhat.com> - 1.16.0-9 | ||||
| - Remove python2 and "other_python3" support | ||||
| - Resolves: rhbz#1802998 Make pycryptodomex and ecdsa weak dependencies of python-dns | ||||
| - Resolves: rhbz#1801247 python-certbot-dns-rfc2136 fails to build with Python 3.9: base64.decodestring() was removed | ||||
| 
 | ||||
| * Mon Feb 03 2020 Miro Hrončok <mhroncok@redhat.com> - 1.16.0-8 | ||||
| - Drop build dependency on python2-typing | ||||
| 
 | ||||
| * Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.16.0-7 | ||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild | ||||
| 
 | ||||
| * Tue Jan 21 2020 Avram Lubkin <aviso@fedoraproject.org> - 1.16.0-6 | ||||
| - Enable unicode patch (rhbz#1731100) | ||||
| - Fix collections.abc import for Python 3.9 (rhbz#1792919) | ||||
| 
 | ||||
| * Tue Nov 05 2019 Paul Howarth <paul@city-fan.org> - 1.16.0-5 | ||||
| - Use pycryptodomex instead of pycrypto | ||||
| - Also use python-ecdsa (except with Python 2) | ||||
| 
 | ||||
| * Thu Oct 03 2019 Miro Hrončok <mhroncok@redhat.com> - 1.16.0-4 | ||||
| - Rebuilt for Python 3.8.0rc1 (#1748018) | ||||
| 
 | ||||
| * Tue Aug 20 2019 Miro Hrončok <mhroncok@redhat.com> - 1.16.0-3 | ||||
| - Reintroduce dropped python2-dns, it is still needed | ||||
| 
 | ||||
| * Mon Aug 19 2019 Miro Hrončok <mhroncok@redhat.com> - 1.16.0-2 | ||||
| - Rebuilt for Python 3.8 | ||||
| 
 | ||||
| * Sat Jul 27 2019 Avram Lubkin <aviso@fedoraproject.org> - 1.16.0-1 | ||||
| - Latest Release | ||||
| - Cleanup spec | ||||
| - Patch to fix unicode escapes | ||||
| - Drop el6 from master (el6 requires patch for 1.16.0) | ||||
| 
 | ||||
| * Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.15.0-11 | ||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild | ||||
| 
 | ||||
| * Sat Feb 02 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.15.0-10 | ||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild | ||||
| 
 | ||||
| * Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.15.0-9 | ||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild | ||||
| 
 | ||||
| * Thu Jul 12 2018 Paul Wouters <pwouters@redhat.com> - 1.15.0-8 | ||||
| - Resolves: rhbz#1600418 - NVR of python-dns is lower in rawhide than in f28 | ||||
| 
 | ||||
| * Tue Jun 19 2018 Miro Hrončok <mhroncok@redhat.com> - 1.15.0-7 | ||||
| - Rebuilt for Python 3.7 | ||||
| 
 | ||||
| * Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.15.0-6 | ||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild | ||||
| @ -461,4 +577,3 @@ Resolves: rhbz#1731081 | ||||
| 
 | ||||
| * Fri May 26 2006 Jeffrey C. Ollie <jeff@ocjtech.us> - 1.3.5-1 | ||||
| - First version for Fedora Extras | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user