From f9f83287a38e112e05cb9fe730f3e5006df2ec6d Mon Sep 17 00:00:00 2001
From: "taifu.gc"
Date: Wed, 14 Dec 2022 02:14:23 +0800
Subject: [PATCH] update to zziplib-0.13.71-9.el9.src.rpm
---
...ort-documentation-scripts-to-python3.patch | 850 ------------------
CVE-2018-16548.part1.patch | 71 --
CVE-2018-16548.part2.patch | 50 --
CVE-2018-16548.part3.patch | 22 -
CVE-2018-17828-singlez.patch | 59 --
CVE-2018-17828.patch | 341 -------
CVE-2018-7725.patch | 48 -
CVE-2018-7726.part1.patch | 31 -
CVE-2018-7726.part2.patch | 40 -
CVE-2018-7726.part3.patch | 22 -
CVE-2018-7727.patch | 138 ---
download | 1 +
match.py | 108 +++
....67-multilib-32.patch => multilib-32.patch | 28 +-
....13.67-multilib.patch => multilib-64.patch | 31 +-
options.py | 28 +
v0.13.68.tar.gz | Bin 1077386 -> 0 bytes
zziplib.spec | 205 +++--
18 files changed, 262 insertions(+), 1811 deletions(-)
delete mode 100644 0001-FIX-port-documentation-scripts-to-python3.patch
delete mode 100644 CVE-2018-16548.part1.patch
delete mode 100644 CVE-2018-16548.part2.patch
delete mode 100644 CVE-2018-16548.part3.patch
delete mode 100644 CVE-2018-17828-singlez.patch
delete mode 100644 CVE-2018-17828.patch
delete mode 100644 CVE-2018-7725.patch
delete mode 100644 CVE-2018-7726.part1.patch
delete mode 100644 CVE-2018-7726.part2.patch
delete mode 100644 CVE-2018-7726.part3.patch
delete mode 100644 CVE-2018-7727.patch
create mode 100644 download
create mode 100644 match.py
rename zziplib-0.13.67-multilib-32.patch => multilib-32.patch (47%)
rename zziplib-0.13.67-multilib.patch => multilib-64.patch (39%)
create mode 100644 options.py
delete mode 100644 v0.13.68.tar.gz
diff --git a/0001-FIX-port-documentation-scripts-to-python3.patch b/0001-FIX-port-documentation-scripts-to-python3.patch
deleted file mode 100644
index ba0cba3..0000000
--- a/0001-FIX-port-documentation-scripts-to-python3.patch
+++ /dev/null
@@ -1,850 +0,0 @@
-From f04dd2918b15853e866d3941b72005696c8c3b8f Mon Sep 17 00:00:00 2001
-From: Jakub Martisko
-Date: Tue, 3 Jul 2018 09:33:07 +0200
-Subject: [PATCH] FIX: port documentation scripts to python3
-
----
- configure | 2 +-
- configure.ac | 2 +-
- docs/cpp2markdown-1.py | 9 ++++--
- docs/cpp2markdown.py | 6 ++--
- docs/make-doc.py | 56 ++++++++++++++++++-----------------
- docs/makedocs.py | 26 ++++++++--------
- docs/zzipdoc/commentmarkup.py | 5 ++--
- docs/zzipdoc/dbk2htm.py | 5 ++--
- docs/zzipdoc/docbookdocument.py | 34 +++++++++++----------
- docs/zzipdoc/functionheader.py | 3 +-
- docs/zzipdoc/functionlisthtmlpage.py | 14 +++++----
- docs/zzipdoc/functionlistreference.py | 8 +++--
- docs/zzipdoc/functionprototype.py | 3 +-
- docs/zzipdoc/htm2dbk.py | 10 ++++---
- docs/zzipdoc/htmldocument.py | 34 +++++++++++----------
- docs/zzipdoc/match.py | 17 ++++++-----
- docs/zzipdoc/options.py | 5 ++--
- docs/zzipdoc/textfile.py | 6 ++--
- docs/zzipdoc/textfileheader.py | 6 ++--
- 18 files changed, 140 insertions(+), 109 deletions(-)
-
-diff --git a/configure b/configure
-index 72a5b6c..6ff3ee4 100755
---- a/configure
-+++ b/configure
-@@ -12270,7 +12270,7 @@ fi
- done
- test -n "$PERL" || PERL="echo no perl found for"
-
--for ac_prog in python
-+for ac_prog in python3
- do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
- set dummy $ac_prog; ac_word=$2
-diff --git a/configure.ac b/configure.ac
-index 4708f8d..68aeb73 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -87,7 +87,7 @@ AX_CREATE_PKGCONFIG_INFO(dnl
- AX_PAX_TAR_CREATE
- AX_PAX_TAR_EXTRACT
- AC_PATH_PROGS(PERL, perl5 perl, echo no perl found for)
--AC_PATH_PROGS(PYTHON, python, echo no python found for)
-+AC_PATH_PROGS(PYTHON, python3, echo no python found for)
- AC_PATH_PROGS(MKZIP, zip pkzip, :)
- AC_PATH_PROGS(XMLTO, xmlto, :)
-
-diff --git a/docs/cpp2markdown-1.py b/docs/cpp2markdown-1.py
-index 60d28c4..1deaed9 100755
---- a/docs/cpp2markdown-1.py
-+++ b/docs/cpp2markdown-1.py
-@@ -1,9 +1,12 @@
- #! /usr/bin/env python
-+from __future__ import absolute_import
-+from __future__ import print_function
- import pygments.lexers.compiled as lexer
- import optparse
- import re
- from pygments.token import Token
- import logging
-+from six.moves import range
-
- logg = logging.getLogger(__name__)
-
-@@ -39,7 +42,7 @@ class CppToMarkdown:
- check2 = re.compile(r"^\s[*]\s+\b[Cc]opyright\b")
- empty1 = re.compile(r"^\s[*]\s*$")
- state = "intro"
-- for i in xrange(1,len(lines)-1):
-+ for i in range(1,len(lines)-1):
- line = lines[i]
- if state == "intro":
- if empty1.match(line):
-@@ -108,7 +111,7 @@ class CppToMarkdown:
- def run(self, filename):
- filetext = open(filename).read()
- for line in self.process(filetext, filename):
-- print line
-+ print(line)
- def process(self, filetext, filename=""):
- section_ruler = "-----------------------------------------"
- copyright = ""
-@@ -136,7 +139,7 @@ class CppToMarkdown:
- else:
- if text:
- yield "#### NOTES"
-- print token, text.replace("\n", "\n ")
-+ print(token, text.replace("\n", "\n "))
- if copyright:
- yield section_ruler
- yield "### COPYRIGHT"
-diff --git a/docs/cpp2markdown.py b/docs/cpp2markdown.py
-index 710bbdc..b8fe11d 100644
---- a/docs/cpp2markdown.py
-+++ b/docs/cpp2markdown.py
-@@ -1,3 +1,5 @@
-+from __future__ import absolute_import
-+from __future__ import print_function
- import pygments.lexers.compiled as lexer
- import optparse
- import re
-@@ -62,7 +64,7 @@ class CppToMarkdown:
- def run(self, filename):
- filetext = open(filename).read()
- for line in self.process(filetext, filename):
-- print line
-+ print(line)
- def process(self, filetext, filename=""):
- for token, text in self.parse(filetext):
- if token == FileInclude:
-@@ -86,7 +88,7 @@ class CppToMarkdown:
- else:
- if text:
- yield "#### NOTES"
-- print token, text.replace("\n", "\n ")
-+ print(token, text.replace("\n", "\n "))
- def isexported_function(self):
- function = self.function_text.strip().replace("\n"," ")
- logg.debug("@ --------------------------------------")
-diff --git a/docs/make-doc.py b/docs/make-doc.py
-index f12553f..22775ef 100644
---- a/docs/make-doc.py
-+++ b/docs/make-doc.py
-@@ -1,5 +1,7 @@
- #! /usr/bin/python
- # -*- coding: UTF-8 -*-
-+from __future__ import absolute_import
-+from __future__ import print_function
- import sys
- import re
- import string
-@@ -23,7 +25,7 @@ def s(string, pattern, repl, count=0):
- def m(string, pattern):
- return re.match(pattern, string)
- def sorted_keys(dict):
-- keys = dict.keys()
-+ keys = list(dict.keys())
- keys.sort()
- return keys
-
-@@ -59,18 +61,18 @@ def section2html(text):
- "" : "", "
" : "
" ,
- "" : "", "" : "" }
- for str in mapping:
-- text = string.replace(text, str, mapping[str])
-+ text = text.replace(str, mapping[str])
- return text
- def html(text):
- return section2html(paramdef2html(text))
- def cdata1(text):
-- return string.replace(text, "&", "&")
-+ return text.replace("&", "&")
- def cdata31(text):
-- return string.replace(string.replace(text, "<","<"), ">",">")
-+ return text.replace(text, "<","<").replace( ">",">")
- def cdata3(text):
- return cdata31(cdata1(text))
- def cdata43(text):
-- return string.replace(text,"\"", """)
-+ return text.replace("\"", """)
- def cdata41(text):
- return cdata43(cdata31(text))
- def cdata4(text):
-@@ -126,7 +128,7 @@ def this_function_link(text, name):
- class Options:
- var = {}
- def __getattr__(self, name):
-- if not self.var.has_key(name): return None
-+ if name not in self.var: return None
- return self.var[name]
- def __setattr__(self, name, value):
- self.var[name] = value
-@@ -158,7 +160,7 @@ class File:
- self.copyright = ""
- def __getattr__(self, name):
- """ defend against program to break on uninited members """
-- if self.__dict__.has_key(name): return self.__dict__[name]
-+ if name in self.__dict__: return self.__dict__[name]
- warn("no such member: "+name); return None
- def set_author(self, text):
- if self.authors:
-@@ -215,7 +217,7 @@ def scan_options (options, list):
- #else
- try:
- input = open(name, "r")
-- except IOError, error:
-+ except IOError as error:
- warn(#...... (scan_options) ...............
- "can not open input file: "+name, error)
- continue
-@@ -294,12 +296,12 @@ class Function:
- # return ""
- def __getattr__(self, name):
- """ defend against program exit on members being not inited """
-- if self.__dict__.has_key(name): return self.__dict__[name]
-+ if name in self.__dict__: return self.__dict__[name]
- warn("no such member: "+name); return None
- def dict(self):
- return self.__dict__
- def dict_sorted_keys(self):
-- keys = self.__dict__.keys()
-+ keys = list(self.__dict__.keys())
- keys.sort()
- return keys
- def parse(self, prototype):
-@@ -376,7 +378,7 @@ def examine_head_anchors(func_list):
- function.head = s(function.head, r"(.*)also:(.*)", lambda x
- : set_seealso(function, x.group(2)) and x.group(1))
- if function.seealso and None:
-- print "function[",function.name,"].seealso=",function.seealso
-+ print("function[",function.name,"].seealso=",function.seealso)
- examine_head_anchors(function_list)
-
- # =============================================================== HTML =====
-@@ -455,7 +457,7 @@ def combined_html_pages(func_list):
- s(ensure_name(this_function_link(section2html( func.body ),
- func.name), func.name),
- r"(?sx) (?para>\s*)
", r"\1"))
-- return combined.values()
-+ return list(combined.values())
- html_pages = combined_html_pages(function_list)
-
- def html_resolve_links_on_page(text, list):
-@@ -495,7 +497,7 @@ class HtmlPage:
- return T
- def add_page_map(self, list):
- """ generate the index-block at the start of the onepage-html file """
-- keys = list.keys()
-+ keys = list(list.keys())
- keys.sort()
- for name in keys:
- self.toc += "\n"+ \
-@@ -524,11 +526,11 @@ html.add_page_list(html_pages)
- # and finally print the html-formatted output
- try:
- F = open(o.libhtmlfile, "w")
--except IOError, error:
-+except IOError as error:
- warn(# ............. open(o.libhtmlfile, "w") ..............
- "can not open html output file: "+o.libhtmlfile, error)
- else:
-- print >> F, html.page_text()
-+ print(html.page_text(), file=F)
- F.close()
- #fi
-
-@@ -987,40 +989,40 @@ doctype += '"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">'+"\n"
-
- try:
- F = open(o.docbookfile,"w")
--except IOError, error:
-+except IOError as error:
- warn("can not open docbook output file: "+o.docbookfile, error)
- else:
-- print >> F, doctype, 'Manual Pages'
-+ print(doctype, 'Manual Pages', file=F)
-
- for page in combined_pages:
-- print >> F, page.refentry_text()
-+ print(page.refentry_text(), file=F)
- #od
-
- for page in header_refpages.values():
- if not page.refentry: continue
-- print >> F, "\n",
-- print >> F, page.refentry_text()
-+ print("\n", end=' ', file=F)
-+ print(page.refentry_text(), file=F)
- #od
-
-- print >> F, "\n",'',"\n"
-+ print("\n",'',"\n", file=F)
- F.close()
- #fi
-
- # _____________________________________________________________________
- try:
- F = open( o.dumpdocfile, "w")
--except IOError, error:
-+except IOError as error:
- warn ("can not open"+o.dumpdocfile,error)
- else:
- for func in function_list:
- name = func.name
-- print >> F, ""+"\n"
-+ print(""+"\n", file=F)
- for H in sorted_keys(func.dict()):
-- print >> F, "<"+H+" name=\""+name+"\">",
-- print >> F, str(func.dict()[H]),
-- print >> F, ""+H+">"
-+ print("<"+H+" name=\""+name+"\">", end=' ', file=F)
-+ print(str(func.dict()[H]), end=' ', file=F)
-+ print(""+H+">", file=F)
- #od
-- print >> F, "\n\n";
-+ print("\n\n", file=F);
- #od
- F.close();
- #fi
-diff --git a/docs/makedocs.py b/docs/makedocs.py
-index 1bc8f88..d987292 100644
---- a/docs/makedocs.py
-+++ b/docs/makedocs.py
-@@ -1,3 +1,5 @@
-+from __future__ import absolute_import
-+from __future__ import print_function
- import sys
- from zzipdoc.match import *
- from zzipdoc.options import *
-@@ -37,7 +39,7 @@ class PerFile:
- return None
- def print_list_mainheader(self):
- for t_fileheader in self.headers:
-- print t_fileheader.get_filename(), t_fileheader.src_mainheader()
-+ print(t_fileheader.get_filename(), t_fileheader.src_mainheader())
-
- class PerFunctionEntry:
- def __init__(self, header, comment, prototype):
-@@ -66,10 +68,10 @@ class PerFunction:
- functionprototype) ]
- def print_list_titleline(self):
- for funcheader in self.headers:
-- print funcheader.get_filename(), "[=>]", funcheader.get_titleline()
-+ print(funcheader.get_filename(), "[=>]", funcheader.get_titleline())
- def print_list_name(self):
- for funcheader in self.prototypes:
-- print funcheader.get_filename(), "[>>]", funcheader.get_name()
-+ print(funcheader.get_filename(), "[>>]", funcheader.get_name())
-
- class PerFunctionFamilyEntry:
- def __init__(self, leader):
-@@ -122,12 +124,12 @@ class PerFunctionFamily:
- for name in self.retarget:
- into = self.retarget[name]
- if into not in name_list:
-- print ("function '"+name+"' retarget into '"+into+
-- "' does not exist - keep alone")
-+ print(("function '"+name+"' retarget into '"+into+
-+ "' does not exist - keep alone"))
- if into in self.retarget:
- other = self.retarget[into]
-- print ("function '"+name+"' retarget into '"+into+
-- "' which is itself a retarget into '"+other+"'")
-+ print(("function '"+name+"' retarget into '"+into+
-+ "' which is itself a retarget into '"+other+"'"))
- if into not in lead_list:
- lead_list += [ into ]
- for func in self.functions:
-@@ -141,7 +143,7 @@ class PerFunctionFamily:
- entry.add(func) # the first
- self.entries += [ entry ]
- else:
-- print "head function '"+name+" has no entry"
-+ print("head function '"+name+" has no entry")
- for func in self.functions:
- name = func.get_name()
- if name in self.retarget:
-@@ -150,14 +152,14 @@ class PerFunctionFamily:
- if entry is not None:
- entry.add(func) # will not add duplicates
- else:
-- print "into function '"+name+" has no entry"
-+ print("into function '"+name+" has no entry")
- def print_list_name(self):
- for family in self.entries:
- name = family.get_name()
-- print name, ":",
-+ print(name, ":", end=' ')
- for item in family.functions:
-- print item.get_name(), ",",
-- print ""
-+ print(item.get_name(), ",", end=' ')
-+ print("")
- class HtmlManualPageAdapter:
- def __init__(self, entry):
- """ usually takes a PerFunctionEntry """
-diff --git a/docs/zzipdoc/commentmarkup.py b/docs/zzipdoc/commentmarkup.py
-index 3f605a7..31727a3 100644
---- a/docs/zzipdoc/commentmarkup.py
-+++ b/docs/zzipdoc/commentmarkup.py
-@@ -1,4 +1,5 @@
--from match import Match
-+from __future__ import absolute_import
-+from .match import Match
-
- def markup_link_syntax(text):
- """ markup the link-syntax ` => somewhere ` in the text block """
-@@ -31,7 +32,7 @@ class CommentMarkup:
- comment = self.header.comment
- try:
- comment = self.header.get_otherlines()
-- except Exception, e:
-+ except Exception as e:
- pass
- mode = ""
- text = ""
-diff --git a/docs/zzipdoc/dbk2htm.py b/docs/zzipdoc/dbk2htm.py
-index f8593e6..2b68e95 100644
---- a/docs/zzipdoc/dbk2htm.py
-+++ b/docs/zzipdoc/dbk2htm.py
-@@ -1,4 +1,5 @@
--from match import Match
-+from __future__ import absolute_import
-+from .match import Match
- import string
-
- class dbk2htm_conversion:
-@@ -9,7 +10,7 @@ class dbk2htm_conversion:
- pass
- def section2html(self, text):
- for str in self.mapping:
-- text = string.replace(text, str, self.mapping[str])
-+ text = text.replace(str, self.mapping[str])
- return text
- def paramdef2html(self, text):
- s = Match()
-diff --git a/docs/zzipdoc/docbookdocument.py b/docs/zzipdoc/docbookdocument.py
-index c4602ad..44a0b23 100644
---- a/docs/zzipdoc/docbookdocument.py
-+++ b/docs/zzipdoc/docbookdocument.py
-@@ -1,6 +1,8 @@
- #! /usr/bin/env python
- # -*- coding: UTF-8 -*-
--from match import Match
-+from __future__ import absolute_import
-+from __future__ import print_function
-+from .match import Match
-
- class DocbookDocument:
- """ binds some xml content page with additional markup - in this
-@@ -23,14 +25,14 @@ class DocbookDocument:
- def get_title(self):
- if self.title: return title
- try: return self.text[0].get_title()
-- except Exception, e: pass
-+ except Exception as e: pass
- return self.title
- def _xml_doctype(self, rootnode):
- return ""
- def _xml_text(self, xml):
- """ accepts adapter objects with .xml_text() """
- try: return xml.xml_text()
-- except Exception, e: print "DocbookDocument/text", e; pass
-+ except Exception as e: print("DocbookDocument/text", e); pass
- return str(xml)
- def _fetch_rootnode(self, text):
- fetch = Match(r"^[^<>]*<(\w+)\b")
-@@ -47,7 +49,7 @@ class DocbookDocument:
- return filename
- def save(self, filename = None):
- filename = self._filename(filename)
-- print "writing '"+filename+"'"
-+ print("writing '"+filename+"'")
- if len(self.text) > 1:
- self.save_all(filename)
- else:
-@@ -58,12 +60,12 @@ class DocbookDocument:
- xml_text = self._xml_text(text)
- rootnode = self._fetch_rootnode(xml_text)
- doctype = self._xml_doctype(rootnode)
-- print >>fd, doctype
-- print >>fd, xml_text
-+ print(doctype, file=fd)
-+ print(xml_text, file=fd)
- fd.close()
- return True
-- except IOError, e:
-- print "could not open '"+filename+"'file", e
-+ except IOError as e:
-+ print("could not open '"+filename+"'file", e)
- return False
- def save_all(self, filename):
- assert len(self.text) > 1
-@@ -76,20 +78,20 @@ class DocbookDocument:
- else:
- rootnode = self.rootnode
- doctype = self._xml_doctype(rootnode)
-- print >>fd, doctype
-+ print(doctype, file=fd)
- title = self.get_title()
- if title and self.rootnode in self.has_title_child:
-- print >>fd, "<"+self.rootnode+'>'+title+''
-+ print("<"+self.rootnode+'>'+title+'', file=fd)
- elif title:
-- print >>fd, "<"+self.rootnode+' id="'+title+'">'
-+ print("<"+self.rootnode+' id="'+title+'">', file=fd)
- else:
-- print >>fd, "<"+self.rootnode+'>'
-+ print("<"+self.rootnode+'>', file=fd)
- for text in self.text:
- text = self._xml_text(text)
-- print >>fd, text
-- print >>fd, ""+self.rootnode+">"
-+ print(text, file=fd)
-+ print(""+self.rootnode+">", file=fd)
- fd.close()
- return True
-- except IOError, e:
-- print "could not open '"+filename+"'file", e
-+ except IOError as e:
-+ print("could not open '"+filename+"'file", e)
- return False
-diff --git a/docs/zzipdoc/functionheader.py b/docs/zzipdoc/functionheader.py
-index 81bb385..a424a6d 100644
---- a/docs/zzipdoc/functionheader.py
-+++ b/docs/zzipdoc/functionheader.py
-@@ -1,4 +1,5 @@
--from match import Match
-+from __future__ import absolute_import
-+from .match import Match
-
- class FunctionHeader:
- """ parsing the comment block that is usually presented before
-diff --git a/docs/zzipdoc/functionlisthtmlpage.py b/docs/zzipdoc/functionlisthtmlpage.py
-index 4ec9178..8009194 100644
---- a/docs/zzipdoc/functionlisthtmlpage.py
-+++ b/docs/zzipdoc/functionlisthtmlpage.py
-@@ -1,5 +1,7 @@
--from options import *
--from match import Match
-+from __future__ import absolute_import
-+from __future__ import print_function
-+from .options import *
-+from .match import Match
-
- class FunctionListHtmlPage:
- """ The main part here is to create a TOC (table of contents) at the
-@@ -35,7 +37,7 @@ class FunctionListHtmlPage:
- head_text = entry.head_xml_text()
- body_text = entry.body_xml_text(name)
- if not head_text:
-- print "no head_text for", name
-+ print("no head_text for", name)
- return
- try:
- prespec = entry.head_get_prespec()
-@@ -43,7 +45,7 @@ class FunctionListHtmlPage:
- callspec = entry.head_get_callspec()
- head_text = (""+namespec+""
- +callspec+" : "+prespec+"
")
-- except Exception, e:
-+ except Exception as e:
- pass
- try:
- extraline = ""
-@@ -56,7 +58,7 @@ class FunctionListHtmlPage:
- ''+filename+''+
- '')
- body_text = extraline + body_text
-- except Exception, e:
-+ except Exception as e:
- pass
- def link(text):
- return (text & Match("(\w*)")
-@@ -102,7 +104,7 @@ class FunctionListHtmlPage:
- text &= (Match("(?s)(\w+)")
- >> (lambda x: self.resolve_internal(x.group(1))))
- if len(self.not_found_in_anchors):
-- print "not found in anchors: ", self.not_found_in_anchors
-+ print("not found in anchors: ", self.not_found_in_anchors)
- return (text & Match("(?s)([^<>]*)")
- >> "\\1
")
- def resolve_external(self, func, sect):
-diff --git a/docs/zzipdoc/functionlistreference.py b/docs/zzipdoc/functionlistreference.py
-index c38ff0a..5993d45 100644
---- a/docs/zzipdoc/functionlistreference.py
-+++ b/docs/zzipdoc/functionlistreference.py
-@@ -1,7 +1,9 @@
- #! /usr/bin/env python
- # -*- coding: UTF-8 -*-
--from match import Match
--from htm2dbk import *
-+from __future__ import absolute_import
-+from __future__ import print_function
-+from .match import Match
-+from .htm2dbk import *
-
- class FunctionListReference:
- """ Creating a docbook-style list of parts
-@@ -19,7 +21,7 @@ class FunctionListReference:
- description = entry.body_xml_text(name)
- funcsynopsis = entry.head_xml_text()
- if not funcsynopsis:
-- print "no funcsynopsis for", name
-+ print("no funcsynopsis for", name)
- return
- if self.entry is None:
- self.entry = FunctionListRefEntry(entry, self.o)
-diff --git a/docs/zzipdoc/functionprototype.py b/docs/zzipdoc/functionprototype.py
-index fda85bb..1247f6c 100644
---- a/docs/zzipdoc/functionprototype.py
-+++ b/docs/zzipdoc/functionprototype.py
-@@ -1,4 +1,5 @@
--from match import Match
-+from __future__ import absolute_import
-+from .match import Match
-
- class FunctionPrototype:
- """ takes a single function prototype line (cut from some source file)
-diff --git a/docs/zzipdoc/htm2dbk.py b/docs/zzipdoc/htm2dbk.py
-index ec9685b..12b70dd 100644
---- a/docs/zzipdoc/htm2dbk.py
-+++ b/docs/zzipdoc/htm2dbk.py
-@@ -6,8 +6,10 @@ The mapping of markups and links is far from perfect. But all we
- want is the docbook-to-pdf converter and similar technology being
- present in the world of docbook-to-anything converters. """
-
-+from __future__ import absolute_import
-+from __future__ import print_function
- from datetime import date
--import match
-+from . import match
- import sys
-
- m = match.Match
-@@ -146,8 +148,8 @@ def htm2dbk_files(args):
- doc.filename = filename
- doc.add(f.read())
- f.close()
-- except IOError, e:
-- print >> sys.stderr, "can not open "+filename
-+ except IOError as e:
-+ print("can not open "+filename, file=sys.stderr)
- return doc.value()
-
- def html2docbook(text):
-@@ -155,4 +157,4 @@ def html2docbook(text):
- return htm2dbk_conversion().convert2(text)
-
- if __name__ == "__main__":
-- print htm2dbk_files(sys.argv[1:])
-+ print(htm2dbk_files(sys.argv[1:]))
-diff --git a/docs/zzipdoc/htmldocument.py b/docs/zzipdoc/htmldocument.py
-index 47d58dc..5e4445a 100644
---- a/docs/zzipdoc/htmldocument.py
-+++ b/docs/zzipdoc/htmldocument.py
-@@ -1,6 +1,8 @@
- #! /usr/bin/env python
- # -*- coding: UTF-8 -*-
--from match import Match
-+from __future__ import absolute_import
-+from __future__ import print_function
-+from .match import Match
-
- class HtmlDocument:
- """ binds some html content page with additional markup - in this
-@@ -29,31 +31,31 @@ class HtmlDocument:
- def get_title(self):
- if self.title: return self.title
- try: return self.text[0].get_title()
-- except Exception, e: pass
-+ except Exception as e: pass
- return self.title
- def _html_meta(self, meta):
- """ accepts adapter objects with .html_meta() """
- try: return meta.html_meta()
-- except Exception, e: pass
-+ except Exception as e: pass
- return str(meta)
- def _html_style(self, style):
- """ accepts adapter objects with .html_style() and .xml_style() """
- ee = None
- try: return style.html_style()
-- except Exception, e: ee = e; pass
-+ except Exception as e: ee = e; pass
- try: return style.xml_style()
-- except Exception, e: print "HtmlDocument/style", ee, e; pass
-+ except Exception as e: print("HtmlDocument/style", ee, e); pass
- try: return str(style)
-- except Exception, e: print "HtmlDocument/style", e; return ""
-+ except Exception as e: print("HtmlDocument/style", e); return ""
- def _html_text(self, html):
- """ accepts adapter objects with .html_text() and .xml_text() """
- ee = None
- try: return html.html_text()
-- except Exception, e: ee = e; pass
-+ except Exception as e: ee = e; pass
- try: return html.xml_text()
-- except Exception, e: print "HtmlDocument/text", ee, e; pass
-+ except Exception as e: print("HtmlDocument/text", ee, e); pass
- try: return str(html)
-- except Exception, e: print "HtmlDocument/text", e; return " "
-+ except Exception as e: print("HtmlDocument/text", e); return " "
- def navigation(self):
- if self.navi:
- return self.navi
-@@ -63,7 +65,7 @@ class HtmlDocument:
- self.navi = fd.read()
- fd.close()
- return self.navi
-- except Exception, e:
-+ except Exception as e:
- pass
- return None
- def html_header(self):
-@@ -103,15 +105,15 @@ class HtmlDocument:
- return filename
- def save(self, filename = None):
- filename = self._filename(filename)
-- print "writing '"+filename+"'"
-+ print("writing '"+filename+"'")
- try:
- fd = open(filename, "w")
-- print >>fd, self.html_header()
-+ print(self.html_header(), file=fd)
- for text in self.text:
-- print >>fd, self._html_text(text)
-- print >>fd, self.html_footer()
-+ print(self._html_text(text), file=fd)
-+ print(self.html_footer(), file=fd)
- fd.close()
- return True
-- except IOError, e:
-- print "could not open '"+filename+"'file", e
-+ except IOError as e:
-+ print("could not open '"+filename+"'file", e)
- return False
-diff --git a/docs/zzipdoc/match.py b/docs/zzipdoc/match.py
-index a089ec3..5f12478 100644
---- a/docs/zzipdoc/match.py
-+++ b/docs/zzipdoc/match.py
-@@ -3,7 +3,10 @@
- # @creator (C) 2003 Guido U. Draheim
- # @license http://creativecommons.org/licenses/by-nc-sa/2.0/de/
-
-+from __future__ import absolute_import
-+from __future__ import print_function
- import re
-+import six
-
- # ---------------------------------------------------------- Regex Match()
- # beware, stupid python interprets backslashes in replace-parts only partially!
-@@ -18,7 +21,7 @@ class MatchReplace:
- MatchReplace.__call__(self, matching, template, count, flags)
- def __call__(self, matching, template = None, count = 0, flags = None):
- """ other than __init__ the template may be left off to be unchanged"""
-- if isinstance(count, basestring): # count/flags swapped over?
-+ if isinstance(count, six.string_types): # count/flags swapped over?
- flags = count; count = 0
- if isinstance(matching, Match):
- self.matching = matching
-@@ -57,7 +60,7 @@ class Match(str):
- def __call__(self, pattern, flags = None):
- assert isinstance(pattern, str) or pattern is None
- assert isinstance(flags, str) or flags is None
-- str.__init__(self, pattern)
-+ super(Match,self).__init__()
- self.replaced = 0 # set by subn() inside MatchReplace
- self.found = None # set by search() to a MatchObject
- self.pattern = pattern
-@@ -90,14 +93,14 @@ class Match(str):
- if __name__ == "__main__":
- # matching:
- if "foo" & Match("oo"):
-- print "oo"
-+ print("oo")
- x = Match()
- if "foo" & x("(o+)"):
-- print x[1]
-+ print(x[1])
- # replacing:
- y = "fooboo" & Match("oo") >> "ee"
-- print y
-+ print(y)
- r = Match("oo") >> "ee"
-- print "fooboo" & r
-+ print("fooboo" & r)
- s = MatchReplace("oo", "ee")
-- print "fooboo" & s
-+ print("fooboo" & s)
-diff --git a/docs/zzipdoc/options.py b/docs/zzipdoc/options.py
-index c6758d5..4a93bb7 100644
---- a/docs/zzipdoc/options.py
-+++ b/docs/zzipdoc/options.py
-@@ -3,13 +3,14 @@
- # @creator (C) 2003 Guido U. Draheim
- # @license http://creativecommons.org/licenses/by-nc-sa/2.0/de/
-
--from match import Match
-+from __future__ import absolute_import
-+from .match import Match
-
- # use as o.optionname to check for commandline options.
- class Options:
- var = {}
- def __getattr__(self, name):
-- if not self.var.has_key(name): return None
-+ if name not in self.var: return None
- return self.var[name]
- def __setattr__(self, name, value):
- self.var[name] = value
-diff --git a/docs/zzipdoc/textfile.py b/docs/zzipdoc/textfile.py
-index bfaff8d..9fabeac 100644
---- a/docs/zzipdoc/textfile.py
-+++ b/docs/zzipdoc/textfile.py
-@@ -1,4 +1,6 @@
-
-+from __future__ import absolute_import
-+from six.moves import range
- def _src_to_xml(text):
- return text.replace("&", "&").replace("<", "<").replace(">", ">")
-
-@@ -17,7 +19,7 @@ class TextFile:
- self.src_text = fd.read()
- fd.close()
- return True
-- except IOError, e:
-+ except IOError as e:
- pass
- return False
- def assert_src_text(self):
-@@ -41,7 +43,7 @@ class TextFile:
- self._line(self.src_text, offset)
- def _line(self, text, offset):
- line = 1
-- for x in xrange(0,offset):
-+ for x in range(0,offset):
- if x == "\n":
- line += 1
- return line
-diff --git a/docs/zzipdoc/textfileheader.py b/docs/zzipdoc/textfileheader.py
-index ceaa28e..63be1e1 100644
---- a/docs/zzipdoc/textfileheader.py
-+++ b/docs/zzipdoc/textfileheader.py
-@@ -1,4 +1,6 @@
--from match import Match
-+from __future__ import absolute_import
-+from __future__ import print_function
-+from .match import Match
-
- class TextFileHeader:
- """ scan for a comment block at the source file start and fill the
-@@ -17,7 +19,7 @@ class TextFileHeader:
- x = Match()
- text = self.textfile.get_src_text()
- if not text:
-- print "nonexistent file:", self.textfile.get_filename()
-+ print("nonexistent file:", self.textfile.get_filename())
- return False
- if text & x(r"(?s)[/][*]+(\s(?:.(?!\*\/))*.)\*\/"
- r"(?:\s*\#(?:define|ifdef|endif)[ ]*\S*[ ]*\S*)*"
---
-2.14.4
-
diff --git a/CVE-2018-16548.part1.patch b/CVE-2018-16548.part1.patch
deleted file mode 100644
index 25c2b74..0000000
--- a/CVE-2018-16548.part1.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 9411bde3e4a70a81ff3ffd256b71927b2d90dcbb Mon Sep 17 00:00:00 2001
-From: jmoellers
-Date: Fri, 7 Sep 2018 11:32:04 +0200
-Subject: [PATCH] Avoid memory leak from __zzip_parse_root_directory().
-
----
- test/test.zip | Bin 1361 -> 1361 bytes
- zzip/zip.c | 36 ++++++++++++++++++++++++++++++++++--
- 2 files changed, 34 insertions(+), 2 deletions(-)
-
-diff --git a/zzip/zip.c b/zzip/zip.c
-index 88b833b..a685280 100644
---- a/zzip/zip.c
-+++ b/zzip/zip.c
-@@ -475,9 +475,15 @@ __zzip_parse_root_directory(int fd,
- } else
- {
- if (io->fd.seeks(fd, zz_rootseek + zz_offset, SEEK_SET) < 0)
-+ {
-+ free(hdr0);
- return ZZIP_DIR_SEEK;
-+ }
- if (io->fd.read(fd, &dirent, sizeof(dirent)) < __sizeof(dirent))
-+ {
-+ free(hdr0);
- return ZZIP_DIR_READ;
-+ }
- d = &dirent;
- }
-
-@@ -577,12 +583,38 @@ __zzip_parse_root_directory(int fd,
-
- if (hdr_return)
- *hdr_return = hdr0;
-+ else
-+ {
-+ /* If it is not assigned to *hdr_return, it will never be free()'d */
-+ free(hdr0);
-+ /* Make sure we don't free it again in case of error */
-+ hdr0 = NULL;
-+ }
- } /* else zero (sane) entries */
- # ifndef ZZIP_ALLOW_MODULO_ENTRIES
-- return (entries != zz_entries ? ZZIP_CORRUPTED : 0);
-+ if (entries != zz_entries)
-+ {
-+ /* If it was assigned to *hdr_return, undo assignment */
-+ if (p_reclen && hdr_return)
-+ *hdr_return = NULL;
-+ /* Free it, if it was not already free()'d */
-+ if (hdr0 != NULL)
-+ free(hdr0);
-+ return ZZIP_CORRUPTED;
-+ }
- # else
-- return ((entries & (unsigned)0xFFFF) != zz_entries ? ZZIP_CORRUPTED : 0);
-+ if (((entries & (unsigned)0xFFFF) != zz_entries)
-+ {
-+ /* If it was assigned to *hdr_return, undo assignment */
-+ if (p_reclen && hdr_return)
-+ *hdr_return = NULL;
-+ /* Free it, if it was not already free()'d */
-+ if (hdr0 != NULL)
-+ free(hdr0);
-+ return ZZIP_CORRUPTED;
-+ }
- # endif
-+ return 0;
- }
-
- /* ------------------------- high-level interface ------------------------- */
diff --git a/CVE-2018-16548.part2.patch b/CVE-2018-16548.part2.patch
deleted file mode 100644
index b9bea26..0000000
--- a/CVE-2018-16548.part2.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From d2e5d5c53212e54a97ad64b793a4389193fec687 Mon Sep 17 00:00:00 2001
-From: jmoellers
-Date: Fri, 7 Sep 2018 11:49:28 +0200
-Subject: [PATCH] Avoid memory leak from __zzip_parse_root_directory().
-
----
- zzip/zip.c | 25 ++-----------------------
- 1 file changed, 2 insertions(+), 23 deletions(-)
-
-diff --git a/zzip/zip.c b/zzip/zip.c
-index a685280..51a1a4d 100644
---- a/zzip/zip.c
-+++ b/zzip/zip.c
-@@ -587,34 +587,13 @@ __zzip_parse_root_directory(int fd,
- {
- /* If it is not assigned to *hdr_return, it will never be free()'d */
- free(hdr0);
-- /* Make sure we don't free it again in case of error */
-- hdr0 = NULL;
- }
- } /* else zero (sane) entries */
- # ifndef ZZIP_ALLOW_MODULO_ENTRIES
-- if (entries != zz_entries)
-- {
-- /* If it was assigned to *hdr_return, undo assignment */
-- if (p_reclen && hdr_return)
-- *hdr_return = NULL;
-- /* Free it, if it was not already free()'d */
-- if (hdr0 != NULL)
-- free(hdr0);
-- return ZZIP_CORRUPTED;
-- }
-+ return (entries != zz_entries) ? ZZIP_CORRUPTED : 0;
- # else
-- if (((entries & (unsigned)0xFFFF) != zz_entries)
-- {
-- /* If it was assigned to *hdr_return, undo assignment */
-- if (p_reclen && hdr_return)
-- *hdr_return = NULL;
-- /* Free it, if it was not already free()'d */
-- if (hdr0 != NULL)
-- free(hdr0);
-- return ZZIP_CORRUPTED;
-- }
-+ return ((entries & (unsigned)0xFFFF) != zz_entries) ? ZZIP_CORRUPTED : 0;
- # endif
-- return 0;
- }
-
- /* ------------------------- high-level interface ------------------------- */
diff --git a/CVE-2018-16548.part3.patch b/CVE-2018-16548.part3.patch
deleted file mode 100644
index f2f8214..0000000
--- a/CVE-2018-16548.part3.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From 0e1dadb05c1473b9df2d7b8f298dab801778ef99 Mon Sep 17 00:00:00 2001
-From: jmoellers
-Date: Fri, 7 Sep 2018 13:55:35 +0200
-Subject: [PATCH] One more free() to avoid memory leak.
-
----
- zzip/zip.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/zzip/zip.c b/zzip/zip.c
-index 51a1a4d..bc6c080 100644
---- a/zzip/zip.c
-+++ b/zzip/zip.c
-@@ -589,6 +589,8 @@ __zzip_parse_root_directory(int fd,
- free(hdr0);
- }
- } /* else zero (sane) entries */
-+ else
-+ free(hdr0);
- # ifndef ZZIP_ALLOW_MODULO_ENTRIES
- return (entries != zz_entries) ? ZZIP_CORRUPTED : 0;
- # else
diff --git a/CVE-2018-17828-singlez.patch b/CVE-2018-17828-singlez.patch
deleted file mode 100644
index 7343ab1..0000000
--- a/CVE-2018-17828-singlez.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-diff --git a/bins/unzip-mem.c b/bins/unzip-mem.c
-index c45cb72..ff564a5 100644
---- a/bins/unzip-mem.c
-+++ b/bins/unzip-mem.c
-@@ -88,10 +88,53 @@ static void zzip_mem_entry_pipe(ZZIP_MEM_DISK* disk,
- }
- }
-
-+
-+
-+
-+static inline void
-+remove_dotdotslash(char *path)
-+{
-+ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
-+ char *dotdotslash;
-+ int warned = 0;
-+
-+ dotdotslash = path;
-+ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
-+ {
-+ /*
-+ * Remove only if at the beginning of the pathname ("../path/name")
-+ * or when preceded by a slash ("path/../name"),
-+ * otherwise not ("path../name..")!
-+ */
-+ if (dotdotslash == path || dotdotslash[-1] == '/')
-+ {
-+ char *src, *dst;
-+ if (!warned)
-+ {
-+ /* Note: the first time through the pathname is still intact */
-+ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
-+ warned = 1;
-+ }
-+ /* We cannot use strcpy(), as there "The strings may not overlap" */
-+ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
-+ ;
-+ }
-+ else
-+ dotdotslash +=3; /* skip this instance to prevent infinite loop */
-+ }
-+}
-+
- static void zzip_mem_entry_make(ZZIP_MEM_DISK* disk,
- ZZIP_MEM_ENTRY* entry)
- {
-- FILE* file = fopen (entry->zz_name, "w");
-+ char name_stripped[PATH_MAX+1];
-+ FILE* file;
-+
-+ strncpy(name_stripped, entry->zz_name, PATH_MAX);
-+ name_stripped[PATH_MAX]='\0';
-+ remove_dotdotslash(name_stripped);
-+
-+ file = fopen (name_stripped, "wb");
- if (file) { zzip_mem_entry_pipe (disk, entry, file); fclose (file); }
- perror (entry->zz_name);
- if (status < EXIT_WARNINGS) status = EXIT_WARNINGS;
diff --git a/CVE-2018-17828.patch b/CVE-2018-17828.patch
deleted file mode 100644
index a340295..0000000
--- a/CVE-2018-17828.patch
+++ /dev/null
@@ -1,341 +0,0 @@
-From 81dfa6b3e08f6934885ba5c98939587d6850d08e Mon Sep 17 00:00:00 2001
-From: Josef Moellers
-Date: Thu, 4 Oct 2018 14:21:48 +0200
-Subject: [PATCH] Fix issue #62: Remove any "../" components from pathnames of
- extracted files. [CVE-2018-17828]
-
----
- bins/unzzipcat-big.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
- bins/unzzipcat-mem.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
- bins/unzzipcat-mix.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
- bins/unzzipcat-zip.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
- 4 files changed, 224 insertions(+), 4 deletions(-)
-
-diff --git a/bins/unzzipcat-big.c b/bins/unzzipcat-big.c
-index 982d262..88c4d65 100644
---- a/bins/unzzipcat-big.c
-+++ b/bins/unzzipcat-big.c
-@@ -53,6 +53,48 @@ static void unzzip_cat_file(FILE* disk, char* name, FILE* out)
- }
- }
-
-+/*
-+ * NAME: remove_dotdotslash
-+ * PURPOSE: To remove any "../" components from the given pathname
-+ * ARGUMENTS: path: path name with maybe "../" components
-+ * RETURNS: Nothing, "path" is modified in-place
-+ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
-+ * Also, "path" is not used after creating it.
-+ * So modifying "path" in-place is safe to do.
-+ */
-+static inline void
-+remove_dotdotslash(char *path)
-+{
-+ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
-+ char *dotdotslash;
-+ int warned = 0;
-+
-+ dotdotslash = path;
-+ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
-+ {
-+ /*
-+ * Remove only if at the beginning of the pathname ("../path/name")
-+ * or when preceded by a slash ("path/../name"),
-+ * otherwise not ("path../name..")!
-+ */
-+ if (dotdotslash == path || dotdotslash[-1] == '/')
-+ {
-+ char *src, *dst;
-+ if (!warned)
-+ {
-+ /* Note: the first time through the pathname is still intact */
-+ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
-+ warned = 1;
-+ }
-+ /* We cannot use strcpy(), as there "The strings may not overlap" */
-+ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
-+ ;
-+ }
-+ else
-+ dotdotslash +=3; /* skip this instance to prevent infinite loop */
-+ }
-+}
-+
- static void makedirs(const char* name)
- {
- char* p = strrchr(name, '/');
-@@ -70,6 +112,16 @@ static void makedirs(const char* name)
-
- static FILE* create_fopen(char* name, char* mode, int subdirs)
- {
-+ char *name_stripped;
-+ FILE *fp;
-+ int mustfree = 0;
-+
-+ if ((name_stripped = strdup(name)) != NULL)
-+ {
-+ remove_dotdotslash(name_stripped);
-+ name = name_stripped;
-+ mustfree = 1;
-+ }
- if (subdirs)
- {
- char* p = strrchr(name, '/');
-@@ -79,7 +131,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
- free (dir_name);
- }
- }
-- return fopen(name, mode);
-+ fp = fopen(name, mode);
-+ if (mustfree)
-+ free(name_stripped);
-+ return fp;
- }
-
-
-diff --git a/bins/unzzipcat-mem.c b/bins/unzzipcat-mem.c
-index 9bc966b..793bde8 100644
---- a/bins/unzzipcat-mem.c
-+++ b/bins/unzzipcat-mem.c
-@@ -58,6 +58,48 @@ static void unzzip_mem_disk_cat_file(ZZIP_MEM_DISK* disk, char* name, FILE* out)
- }
- }
-
-+/*
-+ * NAME: remove_dotdotslash
-+ * PURPOSE: To remove any "../" components from the given pathname
-+ * ARGUMENTS: path: path name with maybe "../" components
-+ * RETURNS: Nothing, "path" is modified in-place
-+ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
-+ * Also, "path" is not used after creating it.
-+ * So modifying "path" in-place is safe to do.
-+ */
-+static inline void
-+remove_dotdotslash(char *path)
-+{
-+ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
-+ char *dotdotslash;
-+ int warned = 0;
-+
-+ dotdotslash = path;
-+ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
-+ {
-+ /*
-+ * Remove only if at the beginning of the pathname ("../path/name")
-+ * or when preceded by a slash ("path/../name"),
-+ * otherwise not ("path../name..")!
-+ */
-+ if (dotdotslash == path || dotdotslash[-1] == '/')
-+ {
-+ char *src, *dst;
-+ if (!warned)
-+ {
-+ /* Note: the first time through the pathname is still intact */
-+ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
-+ warned = 1;
-+ }
-+ /* We cannot use strcpy(), as there "The strings may not overlap" */
-+ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
-+ ;
-+ }
-+ else
-+ dotdotslash +=3; /* skip this instance to prevent infinite loop */
-+ }
-+}
-+
- static void makedirs(const char* name)
- {
- char* p = strrchr(name, '/');
-@@ -75,6 +117,16 @@ static void makedirs(const char* name)
-
- static FILE* create_fopen(char* name, char* mode, int subdirs)
- {
-+ char *name_stripped;
-+ FILE *fp;
-+ int mustfree = 0;
-+
-+ if ((name_stripped = strdup(name)) != NULL)
-+ {
-+ remove_dotdotslash(name_stripped);
-+ name = name_stripped;
-+ mustfree = 1;
-+ }
- if (subdirs)
- {
- char* p = strrchr(name, '/');
-@@ -84,7 +136,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
- free (dir_name);
- }
- }
-- return fopen(name, mode);
-+ fp = fopen(name, mode);
-+ if (mustfree)
-+ free(name_stripped);
-+ return fp;
- }
-
- static int unzzip_cat (int argc, char ** argv, int extract)
-diff --git a/bins/unzzipcat-mix.c b/bins/unzzipcat-mix.c
-index 91c2f00..73b6ed6 100644
---- a/bins/unzzipcat-mix.c
-+++ b/bins/unzzipcat-mix.c
-@@ -69,6 +69,48 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
- }
- }
-
-+/*
-+ * NAME: remove_dotdotslash
-+ * PURPOSE: To remove any "../" components from the given pathname
-+ * ARGUMENTS: path: path name with maybe "../" components
-+ * RETURNS: Nothing, "path" is modified in-place
-+ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
-+ * Also, "path" is not used after creating it.
-+ * So modifying "path" in-place is safe to do.
-+ */
-+static inline void
-+remove_dotdotslash(char *path)
-+{
-+ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
-+ char *dotdotslash;
-+ int warned = 0;
-+
-+ dotdotslash = path;
-+ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
-+ {
-+ /*
-+ * Remove only if at the beginning of the pathname ("../path/name")
-+ * or when preceded by a slash ("path/../name"),
-+ * otherwise not ("path../name..")!
-+ */
-+ if (dotdotslash == path || dotdotslash[-1] == '/')
-+ {
-+ char *src, *dst;
-+ if (!warned)
-+ {
-+ /* Note: the first time through the pathname is still intact */
-+ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
-+ warned = 1;
-+ }
-+ /* We cannot use strcpy(), as there "The strings may not overlap" */
-+ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
-+ ;
-+ }
-+ else
-+ dotdotslash +=3; /* skip this instance to prevent infinite loop */
-+ }
-+}
-+
- static void makedirs(const char* name)
- {
- char* p = strrchr(name, '/');
-@@ -86,6 +128,16 @@ static void makedirs(const char* name)
-
- static FILE* create_fopen(char* name, char* mode, int subdirs)
- {
-+ char *name_stripped;
-+ FILE *fp;
-+ int mustfree = 0;
-+
-+ if ((name_stripped = strdup(name)) != NULL)
-+ {
-+ remove_dotdotslash(name_stripped);
-+ name = name_stripped;
-+ mustfree = 1;
-+ }
- if (subdirs)
- {
- char* p = strrchr(name, '/');
-@@ -95,7 +147,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
- free (dir_name);
- }
- }
-- return fopen(name, mode);
-+ fp = fopen(name, mode);
-+ if (mustfree)
-+ free(name_stripped);
-+ return fp;
- }
-
- static int unzzip_cat (int argc, char ** argv, int extract)
-diff --git a/bins/unzzipcat-zip.c b/bins/unzzipcat-zip.c
-index 2810f85..7f7f3fa 100644
---- a/bins/unzzipcat-zip.c
-+++ b/bins/unzzipcat-zip.c
-@@ -69,6 +69,48 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
- }
- }
-
-+/*
-+ * NAME: remove_dotdotslash
-+ * PURPOSE: To remove any "../" components from the given pathname
-+ * ARGUMENTS: path: path name with maybe "../" components
-+ * RETURNS: Nothing, "path" is modified in-place
-+ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
-+ * Also, "path" is not used after creating it.
-+ * So modifying "path" in-place is safe to do.
-+ */
-+static inline void
-+remove_dotdotslash(char *path)
-+{
-+ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
-+ char *dotdotslash;
-+ int warned = 0;
-+
-+ dotdotslash = path;
-+ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
-+ {
-+ /*
-+ * Remove only if at the beginning of the pathname ("../path/name")
-+ * or when preceded by a slash ("path/../name"),
-+ * otherwise not ("path../name..")!
-+ */
-+ if (dotdotslash == path || dotdotslash[-1] == '/')
-+ {
-+ char *src, *dst;
-+ if (!warned)
-+ {
-+ /* Note: the first time through the pathname is still intact */
-+ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
-+ warned = 1;
-+ }
-+ /* We cannot use strcpy(), as there "The strings may not overlap" */
-+ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
-+ ;
-+ }
-+ else
-+ dotdotslash +=3; /* skip this instance to prevent infinite loop */
-+ }
-+}
-+
- static void makedirs(const char* name)
- {
- char* p = strrchr(name, '/');
-@@ -86,6 +128,16 @@ static void makedirs(const char* name)
-
- static FILE* create_fopen(char* name, char* mode, int subdirs)
- {
-+ char *name_stripped;
-+ FILE *fp;
-+ int mustfree = 0;
-+
-+ if ((name_stripped = strdup(name)) != NULL)
-+ {
-+ remove_dotdotslash(name_stripped);
-+ name = name_stripped;
-+ mustfree = 1;
-+ }
- if (subdirs)
- {
- char* p = strrchr(name, '/');
-@@ -95,7 +147,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
- free (dir_name);
- }
- }
-- return fopen(name, mode);
-+ fp = fopen(name, mode);
-+ if (mustfree)
-+ free(name_stripped);
-+ return fp;
- }
-
- static int unzzip_cat (int argc, char ** argv, int extract)
diff --git a/CVE-2018-7725.patch b/CVE-2018-7725.patch
deleted file mode 100644
index b24c8aa..0000000
--- a/CVE-2018-7725.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 1ba660b3300d67b8ce9f6b96bbae0b36fa2d6b06 Mon Sep 17 00:00:00 2001
-From: Guido Draheim
-Date: Tue, 13 Mar 2018 01:29:44 +0100
-Subject: [PATCH] check zlib space to be within buffer #39
-
----
- zzip/memdisk.c | 9 +++++++++
- zzip/mmapped.c | 2 ++
- 2 files changed, 11 insertions(+)
-
-diff --git a/zzip/memdisk.c b/zzip/memdisk.c
-index 3de201c..8d5743d 100644
---- a/zzip/memdisk.c
-+++ b/zzip/memdisk.c
-@@ -521,11 +521,20 @@ zzip_mem_entry_fopen(ZZIP_MEM_DISK * dir, ZZIP_MEM_ENTRY * entry)
- file->zlib.avail_in = zzip_mem_entry_csize(entry);
- file->zlib.next_in = zzip_mem_entry_to_data(entry);
-
-+ debug2("compressed size %i", (int) file->zlib.avail_in);
-+ if (file->zlib.next_in + file->zlib.avail_in >= file->endbuf)
-+ goto error;
-+ if (file->zlib.next_in < file->buffer)
-+ goto error;
-+
- if (! zzip_mem_entry_data_deflated(entry) ||
- inflateInit2(&file->zlib, -MAX_WBITS) != Z_OK)
- { free (file); return 0; }
-
- return file;
-+error:
-+ errno = EBADMSG;
-+ return NULL;
- }
-
- zzip__new__ ZZIP_MEM_DISK_FILE *
-diff --git a/zzip/mmapped.c b/zzip/mmapped.c
-index 920c4df..8af18f4 100644
---- a/zzip/mmapped.c
-+++ b/zzip/mmapped.c
-@@ -654,6 +654,8 @@ zzip_disk_entry_fopen(ZZIP_DISK * disk, ZZIP_DISK_ENTRY * entry)
- DBG2("compressed size %i", (int) file->zlib.avail_in);
- if (file->zlib.next_in + file->zlib.avail_in >= disk->endbuf)
- goto error;
-+ if (file->zlib.next_in < disk->buffer)
-+ goto error;
-
- if (! zzip_file_header_data_deflated(header))
- goto error;
diff --git a/CVE-2018-7726.part1.patch b/CVE-2018-7726.part1.patch
deleted file mode 100644
index 563c0e1..0000000
--- a/CVE-2018-7726.part1.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 8f48323c181e20b7e527b8be7229d6eb1148ec5f Mon Sep 17 00:00:00 2001
-From: Guido Draheim
-Date: Tue, 13 Mar 2018 00:23:33 +0100
-Subject: [PATCH] check rootseek and rootsize to be positive #27
-
----
- zzip/zip.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/zzip/zip.c b/zzip/zip.c
-index a5db9d8..6be8d7c 100644
---- a/zzip/zip.c
-+++ b/zzip/zip.c
-@@ -318,6 +318,8 @@ __zzip_fetch_disk_trailer(int fd, zzip_off_t filesize,
- trailer->zz_rootseek = zzip_disk_trailer_rootseek(orig);
- trailer->zz_rootsize = zzip_disk_trailer_rootsize(orig);
- # endif
-+ if (trailer->zz_rootseek < 0 || trailer->zz_rootsize < 0)
-+ return(ZZIP_CORRUPTED); // forged value
-
- __fixup_rootseek(offset + tail - mapped, trailer);
- /*
-@@ -344,6 +346,8 @@ __zzip_fetch_disk_trailer(int fd, zzip_off_t filesize,
- zzip_disk64_trailer_finalentries(orig);
- trailer->zz_rootseek = zzip_disk64_trailer_rootseek(orig);
- trailer->zz_rootsize = zzip_disk64_trailer_rootsize(orig);
-+ if (trailer->zz_rootseek < 0 || trailer->zz_rootsize < 0)
-+ return(ZZIP_CORRUPTED); // forged value
- /*
- * "extract data from files archived in a single zip file."
- * So the file offsets must be within the current ZIP archive!
diff --git a/CVE-2018-7726.part2.patch b/CVE-2018-7726.part2.patch
deleted file mode 100644
index 574c1ce..0000000
--- a/CVE-2018-7726.part2.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 19c9e4dc6c5cf92a38d0d23dbccac6993f9c41be Mon Sep 17 00:00:00 2001
-From: Guido Draheim
-Date: Tue, 13 Mar 2018 01:50:36 +0100
-Subject: [PATCH] check rootseek after correction #41
-
----
- zzip/zip.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/zzip/zip.c b/zzip/zip.c
-index 6be8d7c..0d79d52 100644
---- a/zzip/zip.c
-+++ b/zzip/zip.c
-@@ -1,4 +1,3 @@
--
- /*
- * Author:
- * Guido Draheim
-@@ -422,6 +421,9 @@ __zzip_parse_root_directory(int fd,
- zzip_off64_t zz_rootseek = _disk_trailer_rootseek(trailer);
- __correct_rootseek(zz_rootseek, zz_rootsize, trailer);
-
-+ if (zz_entries < 0 || zz_rootseek < 0 || zz_rootseek < 0)
-+ return ZZIP_CORRUPTED;
-+
- hdr0 = (struct zzip_dir_hdr *) malloc(zz_rootsize);
- if (! hdr0)
- return ZZIP_DIRSIZE;
-@@ -465,8 +467,9 @@ __zzip_parse_root_directory(int fd,
- # endif
-
- if (fd_map)
-- { d = (void*)(fd_map+zz_fd_gap+zz_offset); } /* fd_map+fd_gap==u_rootseek */
-- else
-+ {
-+ d = (void*)(fd_map+zz_fd_gap+zz_offset); /* fd_map+fd_gap==u_rootseek */
-+ } else
- {
- if (io->fd.seeks(fd, zz_rootseek + zz_offset, SEEK_SET) < 0)
- return ZZIP_DIR_SEEK;
diff --git a/CVE-2018-7726.part3.patch b/CVE-2018-7726.part3.patch
deleted file mode 100644
index 471b596..0000000
--- a/CVE-2018-7726.part3.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From feae4da1a5c92100c44ebfcbaaa895959cc0829b Mon Sep 17 00:00:00 2001
-From: Guido Draheim
-Date: Thu, 15 Mar 2018 23:54:37 +0100
-Subject: [PATCH] fix for zz_rootsize #41
-
----
- zzip/zip.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/zzip/zip.c b/zzip/zip.c
-index 0d79d52..14e2e06 100644
---- a/zzip/zip.c
-+++ b/zzip/zip.c
-@@ -421,7 +421,7 @@ __zzip_parse_root_directory(int fd,
- zzip_off64_t zz_rootseek = _disk_trailer_rootseek(trailer);
- __correct_rootseek(zz_rootseek, zz_rootsize, trailer);
-
-- if (zz_entries < 0 || zz_rootseek < 0 || zz_rootseek < 0)
-+ if (zz_entries < 0 || zz_rootseek < 0 || zz_rootsize < 0)
- return ZZIP_CORRUPTED;
-
- hdr0 = (struct zzip_dir_hdr *) malloc(zz_rootsize);
diff --git a/CVE-2018-7727.patch b/CVE-2018-7727.patch
deleted file mode 100644
index bb53479..0000000
--- a/CVE-2018-7727.patch
+++ /dev/null
@@ -1,138 +0,0 @@
-From 83a2da55922f67e07f22048ac9671a44cc0d35c4 Mon Sep 17 00:00:00 2001
-From: Guido Draheim
-Date: Wed, 14 Mar 2018 07:50:44 +0100
-Subject: [PATCH] ensure disk_close to avoid mem-leak #40
-
----
- bins/unzzipcat-mem.c | 57 +++++++++++++++++++++++++++-------------------------
- bins/unzzipdir-mem.c | 10 ++++-----
- 2 files changed, 34 insertions(+), 33 deletions(-)
-
-diff --git a/bins/unzzipcat-mem.c b/bins/unzzipcat-mem.c
-index d13029c..9bc966b 100644
---- a/bins/unzzipcat-mem.c
-+++ b/bins/unzzipcat-mem.c
-@@ -89,7 +89,7 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
-
- static int unzzip_cat (int argc, char ** argv, int extract)
- {
-- int done;
-+ int done = 0;
- int argn;
- ZZIP_MEM_DISK* disk;
-
-@@ -116,47 +116,50 @@ static int unzzip_cat (int argc, char ** argv, int extract)
- FILE* out = stdout;
- if (extract) out = create_fopen(name, "w", 1);
- if (! out) {
-- if (errno != EISDIR) done = EXIT_ERRORS;
-+ if (errno != EISDIR) {
-+ DBG3("can not open output file %i %s", errno, strerror(errno));
-+ done = EXIT_ERRORS;
-+ }
- continue;
- }
- unzzip_mem_disk_cat_file (disk, name, out);
- if (extract) fclose(out);
- }
-- return done;
-- }
--
-- if (argc == 3 && !extract)
-+ }
-+ else if (argc == 3 && !extract)
- { /* list from one spec */
- ZZIP_MEM_ENTRY* entry = 0;
- while ((entry = zzip_mem_disk_findmatch(disk, argv[2], entry, 0, 0)))
- {
- unzzip_mem_entry_fprint (disk, entry, stdout);
- }
--
-- return 0;
-- }
--
-- for (argn=1; argn < argc; argn++)
-- { /* list only the matching entries - each in order of commandline */
-- ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
-- for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
-- {
-- char* name = zzip_mem_entry_to_name (entry);
-- if (! _zzip_fnmatch (argv[argn], name,
-- FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
-+ } else {
-+ for (argn=1; argn < argc; argn++)
-+ { /* list only the matching entries - each in order of commandline */
-+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
-+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
- {
-- FILE* out = stdout;
-- if (extract) out = create_fopen(name, "w", 1);
-- if (! out) {
-- if (errno != EISDIR) done = EXIT_ERRORS;
-- continue;
-- }
-- unzzip_mem_disk_cat_file (disk, name, out);
-- if (extract) fclose(out);
-- break; /* match loop */
-+ char* name = zzip_mem_entry_to_name (entry);
-+ if (! _zzip_fnmatch (argv[argn], name,
-+ FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
-+ {
-+ FILE* out = stdout;
-+ if (extract) out = create_fopen(name, "wb", 1);
-+ if (! out) {
-+ if (errno != EISDIR) {
-+ DBG3("can not open output file %i %s", errno, strerror(errno));
-+ done = EXIT_ERRORS;
-+ }
-+ continue;
-+ }
-+ unzzip_mem_disk_cat_file (disk, name, out);
-+ if (extract) fclose(out);
-+ break; /* match loop */
-+ }
- }
- }
- }
-+ zzip_mem_disk_close(disk);
- return done;
- }
-
-diff --git a/bins/unzzipdir-mem.c b/bins/unzzipdir-mem.c
-index e54cd8d..beca788 100644
---- a/bins/unzzipdir-mem.c
-+++ b/bins/unzzipdir-mem.c
-@@ -68,10 +68,8 @@ unzzip_list (int argc, char ** argv, int verbose)
- printf ("%lli/%lli %s %s\n", csize, usize, defl, name);
- }
- }
-- return 0;
- }
--
-- if (argc == 3)
-+ else if (argc == 3)
- { /* list from one spec */
- ZZIP_MEM_ENTRY* entry = 0;
- while ((entry = zzip_mem_disk_findmatch(disk, argv[2], entry, 0, 0)))
-@@ -89,9 +87,8 @@ unzzip_list (int argc, char ** argv, int verbose)
- printf ("%lli/%lli %s %s\n", csize, usize, defl, name);
- }
- }
-- return 0;
- }
--
-+ else
- { /* list only the matching entries - in order of zip directory */
- ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
- for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
-@@ -118,8 +115,9 @@ unzzip_list (int argc, char ** argv, int verbose)
- }
- }
- }
-- return 0;
- }
-+ zzip_mem_disk_close(disk);
-+ return EXIT_OK;
- }
-
- int
diff --git a/download b/download
new file mode 100644
index 0000000..f713589
--- /dev/null
+++ b/download
@@ -0,0 +1 @@
+e180a749c15b33d24c5f3a75e2076b28 v0.13.71-pruned.tar.gz
diff --git a/match.py b/match.py
new file mode 100644
index 0000000..04c1bf9
--- /dev/null
+++ b/match.py
@@ -0,0 +1,108 @@
+#! /usr/bin/env python3
+
+from __future__ import print_function
+
+import re
+
+try:
+ basestring
+except NameError:
+ basestring = str
+
+# ---------------------------------------------------------- Regex Match()
+# beware, stupid python interprets backslashes in replace-parts only partially!
+class MatchReplace:
+ """ A MatchReplace is a mix of a Python Pattern and a Replace-Template """
+ def __init__(self, matching, template, count = 0, flags = None):
+ """ setup a substition from regex 'matching' into 'template',
+ the replacement count default of 0 will replace all occurrences.
+ The first argument may be a Match object or it is a string that
+ will be turned into one by using Match(matching, flags). """
+ self.template = template
+ MatchReplace.__call__(self, matching, template, count, flags)
+ def __call__(self, matching, template = None, count = 0, flags = None):
+ """ other than __init__ the template may be left off to be unchanged"""
+ if isinstance(count, basestring): # count/flags swapped over?
+ flags = count; count = 0
+ if isinstance(matching, Match):
+ self.matching = matching
+ else:
+ self.matching = Match()(matching, flags) ## python 2.4.2 bug
+ if template is not None:
+ self.template = template
+ self.count = count
+ def __and__(self, string):
+ """ z = MatchReplace('foo', 'bar') & 'foo'; assert z = 'bar' """
+ text, self.matching.replaced = \
+ self.matching.regex.subn(self.template, string, self.count)
+ return text
+ def __rand__(self, string):
+ """ z = 'foo' & Match('foo') >> 'bar'; assert z = 'bar' """
+ text, self.matching.replaced = \
+ self.matching.regex.subn(self.template, string, self.count)
+ return text
+ def __iand__(self, string):
+ """ x = 'foo' ; x &= Match('foo') >> 'bar'; assert x == 'bar' """
+ string, self.matching.replaced = \
+ self.matching.regex.subn(self.template, string, self.count)
+ return string
+ def __rshift__(self, count):
+ " shorthand to set the replacement count: Match('foo') >> 'bar' >> 1 "
+ self.count = count ; return self
+ def __rlshift__(self, count):
+ self.count = count ; return self
+
+class Match:
+ """ A Match is actually a mix of a Python Pattern and MatchObject """
+ def __init__(self, pattern = None, flags = None):
+ """ flags is a string: 'i' for case-insensitive etc.; it is just
+ short for a regex prefix: Match('foo','i') == Match('(?i)foo') """
+ Match.__call__(self, pattern, flags)
+ def __call__(self, pattern, flags = None):
+ assert isinstance(pattern, str) or pattern is None
+ assert isinstance(flags, str) or flags is None
+ self.replaced = 0 # set by subn() inside MatchReplace
+ self.found = None # set by search() to a MatchObject
+ self.pattern = pattern
+ if pattern is not None:
+ if flags:
+ self.regex = re.compile("(?"+flags+")"+self.pattern)
+ else:
+ self.regex = re.compile(self.pattern)
+ return self
+ def __repr__(self):
+ return self.pattern
+ def __truth__(self):
+ return self.found is not None
+ def __and__(self, string):
+ self.found = self.regex.search(string)
+ return self.__truth__()
+ def __rand__(self, string):
+ self.found = self.regex.search(string)
+ return self.__truth__()
+ def __rshift__(self, template):
+ return MatchReplace(self, template)
+ def __rlshift__(self, template):
+ return MatchReplace(self, template)
+ def __getitem__(self, index):
+ return self.group(index)
+ def group(self, index):
+ assert self.found is not None
+ return self.found.group(index)
+ def finditer(self, string):
+ return self.regex.finditer(string)
+
+if __name__ == "__main__":
+ # matching:
+ if "foo" & Match("oo"):
+ print("oo")
+ x = Match()
+ if "foo" & x("(o+)"):
+ print(x[1])
+ # replacing:
+ y = "fooboo" & Match("oo") >> "ee"
+ print(y)
+ r = Match("oo") >> "ee"
+ print("fooboo" & r)
+ s = MatchReplace("oo", "ee")
+ print("fooboo" & s)
diff --git a/zziplib-0.13.67-multilib-32.patch b/multilib-32.patch
similarity index 47%
rename from zziplib-0.13.67-multilib-32.patch
rename to multilib-32.patch
index 66acd38..ae99a59 100644
--- a/zziplib-0.13.67-multilib-32.patch
+++ b/multilib-32.patch
@@ -1,6 +1,6 @@
---- ./a/zzip/_config.h 2018-10-11 12:28:07.994739469 +0200
-+++ ./b/zzip/_config.h 2018-10-11 10:30:48.000000000 +0200
-@@ -133,9 +133,11 @@
+--- ./a/zzip/_config.h 2021-07-21 14:18:09.000000000 +0200
++++ ./b/zzip/_config.h 2021-07-21 14:46:24.037432969 +0200
+@@ -138,9 +138,12 @@
/* whether the system defaults to 32bit off_t but can do 64bit when requested
*/
@@ -9,23 +9,11 @@
#define ZZIP_LARGEFILE_SENSITIVE 1
#endif
+#endif
++/* #undef LARGEFILE_SENSITIVE */
- /* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-@@ -185,7 +187,11 @@
-
- /* The number of bytes in type long */
- #ifndef ZZIP_SIZEOF_LONG
--#define ZZIP_SIZEOF_LONG 4
-+#if __WORDSIZE == 32
-+#define ZZIP_SIZEOF_LONG 4
-+#elif __WORDSIZE == 64
-+#define ZZIP_SIZEOF_LONG 8
-+#endif
- #endif
-
- /* The number of bytes in type short */
-@@ -221,9 +227,11 @@
+ /* Define to the sub-directory where libtool stores uninstalled libraries. */
+ #ifndef ZZIP_LT_OBJDIR
+@@ -227,9 +230,13 @@
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
@@ -34,6 +22,8 @@
#define ZZIP__FILE_OFFSET_BITS 64
#endif
+#endif
++/* #undef _FILE_OFFSET_BITS */
++
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
diff --git a/zziplib-0.13.67-multilib.patch b/multilib-64.patch
similarity index 39%
rename from zziplib-0.13.67-multilib.patch
rename to multilib-64.patch
index 169520b..5285e3a 100644
--- a/zziplib-0.13.67-multilib.patch
+++ b/multilib-64.patch
@@ -1,42 +1,29 @@
-diff -up ./x86_64-redhat-linux-gnu/zzip/_config.h.orig ./x86_64-redhat-linux-gnu/zzip/_config.h
---- ./x86_64-redhat-linux-gnu/zzip/_config.h.orig 2018-02-01 22:13:36.593910695 +0200
-+++ ./x86_64-redhat-linux-gnu/zzip/_config.h 2018-02-01 22:15:40.341476130 +0200
-@@ -133,7 +133,11 @@
+--- ./a/zzip/_config.h 2021-07-21 14:18:14.000000000 +0200
++++ ./b/zzip/_config.h 2021-07-21 14:46:24.037432969 +0200
+@@ -138,6 +138,11 @@
/* whether the system defaults to 32bit off_t but can do 64bit when requested
*/
--/* #undef LARGEFILE_SENSITIVE */
+#if __WORDSIZE == 32
+#ifndef ZZIP_LARGEFILE_SENSITIVE
+#define ZZIP_LARGEFILE_SENSITIVE 1
+#endif
+#endif
+ /* #undef LARGEFILE_SENSITIVE */
- /* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-@@ -183,8 +187,12 @@
-
- /* The number of bytes in type long */
- #ifndef ZZIP_SIZEOF_LONG
-+#if __WORDSIZE == 32
-+#define ZZIP_SIZEOF_LONG 4
-+#elif __WORDSIZE == 64
- #define ZZIP_SIZEOF_LONG 8
- #endif
-+#endif
-
- /* The number of bytes in type short */
- #ifndef ZZIP_SIZEOF_SHORT
-@@ -219,7 +227,11 @@
+ /* Define to the sub-directory where libtool stores uninstalled libraries. */
+@@ -225,8 +230,14 @@
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
--/* #undef _FILE_OFFSET_BITS */
+#if __WORDSIZE == 32
+#ifndef ZZIP__FILE_OFFSET_BITS
+#define ZZIP__FILE_OFFSET_BITS 64
+#endif
+#endif
+ /* #undef _FILE_OFFSET_BITS */
++
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
+
diff --git a/options.py b/options.py
new file mode 100644
index 0000000..6bbdec4
--- /dev/null
+++ b/options.py
@@ -0,0 +1,28 @@
+#! /usr/bin/env python3
+
+from zzipdoc.match import Match
+
+# use as o.optionname to check for commandline options.
+class Options:
+ var = {}
+ def __getattr__(self, name):
+ if not name in self.var: return None
+ return self.var[name]
+ def __setattr__(self, name, value):
+ self.var[name] = value
+ def scan(self, optionstring): # option-name or None
+ x = Match()
+ if optionstring & x(r"^--?(\w+)=(.*)"):
+ self.var[x[1]] = x[2] ; return x[1]
+ if optionstring & x(r"^--?no-(\w+)$"):
+ self.var[x[1]] = "" ; return x[1]
+ if optionstring & x(r"^--?(\w+)$"):
+ self.var[x[1]] = "*"; return x[1]
+ return None
+#end Options
+
+if False:
+ o = Options()
+ o.help = """
+ scans for options
+ """
diff --git a/v0.13.68.tar.gz b/v0.13.68.tar.gz
deleted file mode 100644
index 75ef9f60fca1c3718d3543b2762df36a2caed7dc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1077386
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
RGPu7lX((+N{rg#@X$(6=!F)6DCSbI~j*svxW*7
zb1kn|Ep59?1IT&dIhWZ|85yr~8`E#875rI-SV<%)DXDz=XUhaRO1;}ZXDP(G_ywpw
z$Cx&%ac*hgSL0z)NV2?6TEK0@%~yQRb