Commit d146cb1e authored by Jérome Perrin's avatar Jérome Perrin

ERP5: Zope4 on python2

using ERP5: nexedi/erp5!1545

See merge request nexedi/slapos!1122
parents a2418691 42385a73
Pipeline #26955 passed with stage
in 0 seconds
......@@ -15,10 +15,10 @@ parts = ZODB/scripts
# [ZODB]
# major = <ZODB-version-major>
#
# By default ZODB4 is used.
# By default ZODB5 is used.
[ZODB]
recipe = slapos.recipe.build
major = 4
major = 5
init =
# link/depend ZODB -> ZODB<X>
zodb_x = 'ZODB'+options['major']
......@@ -59,7 +59,7 @@ egg-versions =
<= _ZODB
egg-versions =
ZODB = 5.8.0
transaction = 2.4.0
transaction = 3.0.1
# ZODB4-wc2 is ZODB4 version with patches for wendelin.core 2 to work correctly.
......@@ -94,9 +94,9 @@ setup-eggs = ${python-cffi:egg}
# eggs that are common to ZODB4 and ZODB5.
[versions]
BTrees = 4.5.1
persistent = 4.6.4
zodbpickle = 2.0.0
BTrees = 4.11.3
persistent = 4.9.3
zodbpickle = 2.6.0
# Provide ZODB3 for those eggs that still care about ZODB3 compatibility -
# for example wendelin.core. ZODB3 3.11 is just a dependency egg on _latest_
......
diff -uNr Acquisition-2.13.12.orig/src/Acquisition/_Acquisition.c Acquisition-2.13.12/src/Acquisition/_Acquisition.c
--- Acquisition-2.13.12.orig/src/Acquisition/_Acquisition.c 2017-12-01 12:01:34.000000000 +0100
+++ Acquisition-2.13.12/src/Acquisition/_Acquisition.c 2018-04-09 17:10:15.394836944 +0200
@@ -449,6 +449,64 @@
diff -Naur Acquisition-4.7.orig/src/Acquisition/_Acquisition.c Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/_Acquisition.c
--- Acquisition-4.7.orig/src/Acquisition/_Acquisition.c 2021-03-17 16:22:28.266539592 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/_Acquisition.c 2021-03-17 16:28:59.609842948 +0100
@@ -543,6 +543,64 @@
}
static PyObject *
......@@ -66,47 +66,47 @@ diff -uNr Acquisition-2.13.12.orig/src/Acquisition/_Acquisition.c Acquisition-2.
Wrapper_acquire(Wrapper *self, PyObject *oname,
PyObject *filter, PyObject *extra, PyObject *orig,
int explicit, int containment);
@@ -589,8 +647,8 @@
Py_XDECREF(r); Py_XDECREF(v); Py_XDECREF(tb);
r=NULL;
@@ -677,8 +735,8 @@
return NULL;
}
- /* normal attribute lookup */
- else if ((r=PyObject_GetAttr(self->obj,oname)))
- else if ((r = PyObject_GetAttr(self->obj, oname))) {
+ /* Give _aq_dynamic a chance, then normal attribute lookup */
+ else if ((r=Wrapper_GetAttr(OBJECT(self),oname,orig)))
{
if (r==Acquired)
{
@@ -714,7 +772,7 @@
Py_XDECREF(r); Py_XDECREF(v); Py_XDECREF(tb);
r=NULL;
- if ((r=PyObject_GetAttr(self->container,oname))) {
+ if ((r=Wrapper_GetAttr(self->container,oname,orig))) {
+ else if ((r = Wrapper_GetAttr(OBJECT(self), oname, orig))) {
if (r == Acquired) {
Py_DECREF(r);
return Wrapper_acquire(
@@ -806,7 +864,7 @@
return NULL;
}
@@ -751,7 +809,7 @@
- if ((r = PyObject_GetAttr(self->container, oname)) == NULL) {
+ if ((r = Wrapper_GetAttr(self->container, oname, orig)) == NULL) {
/* May be AttributeError or some other kind of error */
return NULL;
}
@@ -830,7 +888,7 @@
static PyObject *
Wrapper_getattro(Wrapper *self, PyObject *oname)
{
if (self->obj || self->container)
- return Wrapper_findattr(self, oname, NULL, NULL, NULL, 1, 1, 0, 0);
+ return Wrapper_findattr(self, oname, NULL, NULL, OBJECT(self), 1, 1, 0, 0);
}
/* Maybe we are getting initialized? */
return Py_FindAttr(OBJECT(self),oname);
@@ -776,7 +834,7 @@
result = Py_FindAttr(OBJECT(self),oname);
else if (self->obj || self->container)
static PyObject *
@@ -846,7 +904,7 @@
if (STR_EQ(PyBytes_AS_STRING(tmp), "acquire")) {
result = Py_FindAttr(OBJECT(self), oname);
} else {
- result = Wrapper_findattr(self, oname, NULL, NULL, NULL, 1, 0, 0, 0);
+ result = Wrapper_findattr(self, oname, NULL, NULL, OBJECT(self), 1, 0, 0, 0);
}
/* Maybe we are getting initialized? */
else result = Py_FindAttr(OBJECT(self),oname);
diff -uNr Acquisition-2.13.12.orig/src/Acquisition/test_dynamic_acquisition.py Acquisition-2.13.12/src/Acquisition/test_dynamic_acquisition.py
--- Acquisition-2.13.12.orig/src/Acquisition/test_dynamic_acquisition.py 1970-01-01 01:00:00.000000000 +0100
+++ Acquisition-2.13.12/src/Acquisition/test_dynamic_acquisition.py 2018-04-09 17:07:34.863985305 +0200
Py_DECREF(tmp);
diff -Naur Acquisition-4.7.orig/src/Acquisition/test_dynamic_acquisition.py Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/test_dynamic_acquisition.py
--- Acquisition-4.7.orig/src/Acquisition/test_dynamic_acquisition.py 1970-01-01 01:00:00.000000000 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/test_dynamic_acquisition.py 2021-03-17 16:30:07.082413986 +0100
@@ -0,0 +1,160 @@
+##############################################################################
+#
......@@ -268,25 +268,30 @@ diff -uNr Acquisition-2.13.12.orig/src/Acquisition/test_dynamic_acquisition.py A
+ >>> assert not b.a.aq_inContextOf('somestring')
+'''
+
diff -uNr Acquisition-2.13.12.orig/src/Acquisition/tests.py Acquisition-2.13.12/src/Acquisition/tests.py
--- Acquisition-2.13.12.orig/src/Acquisition/tests.py 2017-12-01 12:01:34.000000000 +0100
+++ Acquisition-2.13.12/src/Acquisition/tests.py 2018-04-09 17:07:34.867985476 +0200
@@ -2588,6 +2588,7 @@
def test_suite():
return unittest.TestSuite((
diff -Naur Acquisition-4.7.orig/src/Acquisition/tests.py Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/tests.py
--- Acquisition-4.7.orig/src/Acquisition/tests.py 2021-03-17 16:22:28.266539592 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition/tests.py 2021-03-17 16:31:31.971132854 +0100
@@ -3366,6 +3366,7 @@
suites = [
DocTestSuite(),
+ DocTestSuite('Acquisition.test_dynamic_acquisition'),
DocFileSuite('README.txt', package='Acquisition'),
unittest.makeSuite(TestParent),
unittest.makeSuite(TestAcquire),
diff -uNr Acquisition-2.13.12.orig/src/Acquisition.egg-info/SOURCES.txt Acquisition-2.13.12/src/Acquisition.egg-info/SOURCES.txt
--- Acquisition-2.13.12.orig/src/Acquisition.egg-info/SOURCES.txt 2017-12-01 12:08:29.000000000 +0100
+++ Acquisition-2.13.12/src/Acquisition.egg-info/SOURCES.txt 2018-04-09 17:07:34.867985476 +0200
@@ -10,6 +10,7 @@
src/Acquisition/_Acquisition.c
unittest.defaultTestLoader.loadTestsFromName(__name__),
]
diff -Naur Acquisition-4.7.orig/src/Acquisition.egg-info/SOURCES.txt Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition.egg-info/SOURCES.txt
--- Acquisition-4.7.orig/src/Acquisition.egg-info/SOURCES.txt 2021-03-17 16:22:28.262539558 +0100
+++ Acquisition-4.7-py2.7-linux-x86_64.egg/src/Acquisition.egg-info/SOURCES.txt 2021-03-17 16:32:31.619638229 +0100
@@ -15,9 +15,10 @@
src/Acquisition/__init__.py
src/Acquisition/interfaces.py
+src/Acquisition/test_dynamic_acquisition.py
src/Acquisition/tests.py
+src/Acquisition/test_dynamic_acquisition.py
src/Acquisition.egg-info/PKG-INFO
src/Acquisition.egg-info/SOURCES.txt
src/Acquisition.egg-info/dependency_links.txt
src/Acquisition.egg-info/not-zip-safe
src/Acquisition.egg-info/requires.txt
-src/Acquisition.egg-info/top_level.txt
\ Pas de fin de ligne à la fin du fichier
+src/Acquisition.egg-info/top_level.txt
diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/DCWorkflow.py Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/DCWorkflow.py
--- Products.DCWorkflow-2.2.4/Products/DCWorkflow/DCWorkflow.py 2011-11-01 18:55:01.000000000 +0100
+++ Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/DCWorkflow.py 2013-10-31 16:42:05.021141352 +0100
@@ -40,6 +40,7 @@
from Products.DCWorkflow.permissions import ManagePortal
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/DCWorkflow.py Products.DCWorkflow-2.4.1/Products/DCWorkflow/DCWorkflow.py
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/DCWorkflow.py 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/DCWorkflow.py 2021-03-18 15:43:47.791236880 +0100
@@ -38,6 +38,7 @@
from Products.DCWorkflow.interfaces import IDCWorkflowDefinition
from Products.DCWorkflow.Transitions import TRIGGER_AUTOMATIC
from Products.DCWorkflow.Transitions import TRIGGER_USER_ACTION
+from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
from Products.DCWorkflow.utils import Message as _
from Products.DCWorkflow.utils import modifyRolesForGroup
from Products.DCWorkflow.utils import modifyRolesForPermission
@@ -281,6 +282,52 @@
raise Unauthorized(action)
@@ -279,6 +280,52 @@
self._changeStateOf(ob, tdef, kw)
+ security.declarePrivate('isWorkflowMethodSupported')
@security.private
+ def isWorkflowMethodSupported(self, ob, method_id):
+ '''
+ Returns a true value if the given workflow method
......@@ -30,7 +29,7 @@ diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/DCWorkflow.py Products.D
+ return 1
+ return 0
+
+ security.declarePrivate('wrapWorkflowMethod')
+ @security.private
+ def wrapWorkflowMethod(self, ob, method_id, func, args, kw):
+ '''
+ Allows the user to request a workflow action. This method
......@@ -38,12 +37,12 @@ diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/DCWorkflow.py Products.D
+ '''
+ sdef = self._getWorkflowStateOf(ob)
+ if sdef is None:
+ raise WorkflowException, 'Object is in an undefined state'
+ raise WorkflowException('Object is in an undefined state')
+ if method_id not in sdef.transitions:
+ raise Unauthorized(method_id)
+ tdef = self.transitions.get(method_id, None)
+ if tdef is None or tdef.trigger_type != TRIGGER_WORKFLOW_METHOD:
+ raise WorkflowException, (
+ raise WorkflowException(
+ 'Transition %s is not triggered by a workflow method'
+ % method_id)
+ if not self._checkTransitionGuard(tdef, ob):
......@@ -54,17 +53,18 @@ diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/DCWorkflow.py Products.D
+ except ObjectDeleted:
+ # Re-raise with a different result.
+ raise ObjectDeleted(res)
+ except ObjectMoved, ex:
+ except ObjectMoved as ex:
+ # Re-raise with a different result.
+ raise ObjectMoved(ex.getNewObject(), res)
+ return res
+
security.declarePrivate('isInfoSupported')
+ @security.private
def isInfoSupported(self, ob, name):
'''
diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/dtml/transition_properties.dtml Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/dtml/transition_properties.dtml
--- Products.DCWorkflow-2.2.4/Products/DCWorkflow/dtml/transition_properties.dtml 2011-11-01 18:55:01.000000000 +0100
+++ Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/dtml/transition_properties.dtml 2013-10-31 16:42:05.021141352 +0100
Returns a true value if the given info name is supported.
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transition_properties.dtml Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transition_properties.dtml
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transition_properties.dtml 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transition_properties.dtml 2021-03-18 15:37:55.144028451 +0100
@@ -56,6 +56,16 @@
</tr>
......@@ -82,9 +82,9 @@ diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/dtml/transition_properti
<th align="left">Script (before)</th>
<td>
<select name="script_name">
diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/dtml/transitions.dtml Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/dtml/transitions.dtml
--- Products.DCWorkflow-2.2.4/Products/DCWorkflow/dtml/transitions.dtml 2011-11-01 18:55:01.000000000 +0100
+++ Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/dtml/transitions.dtml 2013-10-31 16:42:05.021141352 +0100
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transitions.dtml Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transitions.dtml
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/dtml/transitions.dtml 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/dtml/transitions.dtml 2021-03-18 15:37:55.144028451 +0100
@@ -17,7 +17,8 @@
<td>
Destination state: <code><dtml-if new_state_id>&dtml-new_state_id;<dtml-else>(Remain in state)</dtml-if></code> <br />
......@@ -95,21 +95,21 @@ diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/dtml/transitions.dtml Pr
<br />
<dtml-if script_name>
Script (before): &dtml-script_name;
diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/exportimport.py Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/exportimport.py
--- Products.DCWorkflow-2.2.4/Products/DCWorkflow/exportimport.py 2011-11-01 18:55:01.000000000 +0100
+++ Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/exportimport.py 2013-10-31 16:42:09.221141578 +0100
@@ -34,7 +34,7 @@
from Products.GenericSetup.interfaces import ISetupEnviron
from Products.GenericSetup.utils import BodyAdapterBase
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/exportimport.py Products.DCWorkflow-2.4.1/Products/DCWorkflow/exportimport.py
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/exportimport.py 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/exportimport.py 2021-03-18 15:44:34.903667147 +0100
@@ -40,7 +40,7 @@
from Products.DCWorkflow.utils import _xmldir
-TRIGGER_TYPES = ( 'AUTOMATIC', 'USER' )
+TRIGGER_TYPES = ( 'AUTOMATIC', 'USER', 'METHOD' )
-TRIGGER_TYPES = ('AUTOMATIC', 'USER')
+TRIGGER_TYPES = ('AUTOMATIC', 'USER', 'METHOD' )
_FILENAME = 'workflows.xml'
diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/Transitions.py Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/Transitions.py
--- Products.DCWorkflow-2.2.4/Products/DCWorkflow/Transitions.py 2011-11-01 18:55:01.000000000 +0100
+++ Products.DCWorkflow-2.2.4nxd001/Products/DCWorkflow/Transitions.py 2013-10-31 16:42:12.389141749 +0100
diff -Naur Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/Transitions.py Products.DCWorkflow-2.4.1/Products/DCWorkflow/Transitions.py
--- Products.DCWorkflow-2.4.1.orig/Products/DCWorkflow/Transitions.py 2020-03-09 22:05:43.000000000 +0100
+++ Products.DCWorkflow-2.4.1/Products/DCWorkflow/Transitions.py 2021-03-18 15:37:55.148028486 +0100
@@ -31,6 +31,7 @@
TRIGGER_AUTOMATIC = 0
......@@ -117,4 +117,4 @@ diff -uNr Products.DCWorkflow-2.2.4/Products/DCWorkflow/Transitions.py Products.
+TRIGGER_WORKFLOW_METHOD = 2
class TransitionDefinition (SimpleItem):
class TransitionDefinition(SimpleItem):
From: Bert JW Regeer <bertjw@regeer.org>
Date: Sat, 12 Mar 2022 18:30:30 -0700
Subject: Add new regular expressions for Chunked Encoding
This also moves some regular expressions for QUOTED_PAIR/QUOTED_STRING
into this module from utilities so that they may be reused.
Part of CVE-2022-24761
---
src/waitress/rfc7230.py | 27 ++++++++++++++++++++++++++-
src/waitress/utilities.py | 28 +++-------------------------
2 files changed, 29 insertions(+), 26 deletions(-)
diff --git a/src/waitress/rfc7230.py b/src/waitress/rfc7230.py
index cd33c90..0b76a38 100644
--- a/src/waitress/rfc7230.py
+++ b/src/waitress/rfc7230.py
@@ -7,6 +7,9 @@ import re
from .compat import tobytes
+HEXDIG = "[0-9a-fA-F]"
+DIGIT = "[0-9]"
+
WS = "[ \t]"
OWS = WS + "{0,}?"
RWS = WS + "{1,}?"
@@ -27,6 +30,12 @@ TOKEN = TCHAR + "{1,}"
# ; visible (printing) characters
VCHAR = r"\x21-\x7e"
+# The '\\' between \x5b and \x5d is needed to escape \x5d (']')
+QDTEXT = "[\t \x21\x23-\x5b\\\x5d-\x7e" + OBS_TEXT + "]"
+
+QUOTED_PAIR = r"\\" + "([\t " + VCHAR + OBS_TEXT + "])"
+QUOTED_STRING = '"(?:(?:' + QDTEXT + ")|(?:" + QUOTED_PAIR + '))*"'
+
# header-field = field-name ":" OWS field-value OWS
# field-name = token
# field-value = *( field-content / obs-fold )
@@ -45,8 +54,24 @@ FIELD_CONTENT = FIELD_VCHAR + "+(?:[ \t]+" + FIELD_VCHAR + "+)*"
# Which allows the field value here to just see if there is even a value in the first place
FIELD_VALUE = "(?:" + FIELD_CONTENT + ")?"
-HEADER_FIELD = re.compile(
+# chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+# chunk-ext-name = token
+# chunk-ext-val = token / quoted-string
+
+CHUNK_EXT_NAME = TOKEN
+CHUNK_EXT_VAL = "(?:" + TOKEN + ")|(?:" + QUOTED_STRING + ")"
+CHUNK_EXT = (
+ "(?:;(?P<extension>" + CHUNK_EXT_NAME + ")(?:=(?P<value>" + CHUNK_EXT_VAL + "))?)*"
+)
+
+# Pre-compiled regular expressions for use elsewhere
+ONLY_HEXDIG_RE = re.compile(("^" + HEXDIG + "+$").encode("latin-1"))
+ONLY_DIGIT_RE = re.compile(("^" + DIGIT + "+$").encode("latin-1"))
+HEADER_FIELD_RE = re.compile(
tobytes(
"^(?P<name>" + TOKEN + "):" + OWS + "(?P<value>" + FIELD_VALUE + ")" + OWS + "$"
)
)
+QUOTED_PAIR_RE = re.compile(QUOTED_PAIR)
+QUOTED_STRING_RE = re.compile(QUOTED_STRING)
+CHUNK_EXT_RE = re.compile(("^" + CHUNK_EXT + "$").encode("latin-1"))
diff --git a/src/waitress/utilities.py b/src/waitress/utilities.py
index 556bed2..fa59657 100644
--- a/src/waitress/utilities.py
+++ b/src/waitress/utilities.py
@@ -22,7 +22,7 @@ import re
import stat
import time
-from .rfc7230 import OBS_TEXT, VCHAR
+from .rfc7230 import QUOTED_PAIR_RE, QUOTED_STRING_RE
logger = logging.getLogger("waitress")
queue_logger = logging.getLogger("waitress.queue")
@@ -216,32 +216,10 @@ def parse_http_date(d):
return retval
-# RFC 5234 Appendix B.1 "Core Rules":
-# VCHAR = %x21-7E
-# ; visible (printing) characters
-vchar_re = VCHAR
-
-# RFC 7230 Section 3.2.6 "Field Value Components":
-# quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
-# qdtext = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
-# obs-text = %x80-FF
-# quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
-obs_text_re = OBS_TEXT
-
-# The '\\' between \x5b and \x5d is needed to escape \x5d (']')
-qdtext_re = "[\t \x21\x23-\x5b\\\x5d-\x7e" + obs_text_re + "]"
-
-quoted_pair_re = r"\\" + "([\t " + vchar_re + obs_text_re + "])"
-quoted_string_re = '"(?:(?:' + qdtext_re + ")|(?:" + quoted_pair_re + '))*"'
-
-quoted_string = re.compile(quoted_string_re)
-quoted_pair = re.compile(quoted_pair_re)
-
-
def undquote(value):
if value.startswith('"') and value.endswith('"'):
# So it claims to be DQUOTE'ed, let's validate that
- matches = quoted_string.match(value)
+ matches = QUOTED_STRING_RE.match(value)
if matches and matches.end() == len(value):
# Remove the DQUOTE's from the value
@@ -249,7 +227,7 @@ def undquote(value):
# Remove all backslashes that are followed by a valid vchar or
# obs-text
- value = quoted_pair.sub(r"\1", value)
+ value = QUOTED_PAIR_RE.sub(r"\1", value)
return value
elif not value.startswith('"') and not value.endswith('"'):
From: Bert JW Regeer <bertjw@regeer.org>
Date: Sat, 12 Mar 2022 18:32:24 -0700
Subject: Be more strict in parsing Content-Length
Validate that we are only parsing digits and nothing else. RFC7230 is
explicit in that the Content-Length can only exist of 1*DIGIT and may
not include any additional sign information.
The Python int() function parses `+10` as `10` which means we were more
lenient than the standard intended.
Part of CVE-2022-24761
---
src/waitress/parser.py | 12 ++++++------
tests/test_parser.py | 24 ++++++++++++++++++++++++
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/src/waitress/parser.py b/src/waitress/parser.py
index 765fe59..acaf494 100644
--- a/src/waitress/parser.py
+++ b/src/waitress/parser.py
@@ -22,6 +22,7 @@ from io import BytesIO
from waitress.buffers import OverflowableBuffer
from waitress.compat import tostr, unquote_bytes_to_wsgi, urlparse
from waitress.receiver import ChunkedReceiver, FixedStreamReceiver
+from waitress.rfc7230 import HEADER_FIELD_RE, ONLY_DIGIT_RE
from waitress.utilities import (
BadRequest,
RequestEntityTooLarge,
@@ -29,8 +30,6 @@ from waitress.utilities import (
ServerNotImplemented,
find_double_newline,
)
-from .rfc7230 import HEADER_FIELD
-
class ParsingError(Exception):
pass
@@ -209,7 +208,7 @@ class HTTPRequestParser(object):
headers = self.headers
for line in lines:
- header = HEADER_FIELD.match(line)
+ header = HEADER_FIELD_RE.match(line)
if not header:
raise ParsingError("Invalid header")
@@ -299,11 +298,12 @@ class HTTPRequestParser(object):
self.connection_close = True
if not self.chunked:
- try:
- cl = int(headers.get("CONTENT_LENGTH", 0))
- except ValueError:
+ cl = headers.get("CONTENT_LENGTH", "0")
+
+ if not ONLY_DIGIT_RE.match(cl.encode("latin-1")):
raise ParsingError("Content-Length is invalid")
+ cl = int(cl)
self.content_length = cl
if cl > 0:
buf = OverflowableBuffer(self.adj.inbuf_overflow)
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 91837c7..eabf353 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -194,6 +194,30 @@ class TestHTTPRequestParser(unittest.TestCase):
else: # pragma: nocover
self.assertTrue(False)
+ def test_parse_header_bad_content_length_plus(self):
+ from waitress.parser import ParsingError
+
+ data = b"GET /foobar HTTP/8.4\r\ncontent-length: +10\r\n"
+
+ try:
+ self.parser.parse_header(data)
+ except ParsingError as e:
+ self.assertIn("Content-Length is invalid", e.args[0])
+ else: # pragma: nocover
+ self.assertTrue(False)
+
+ def test_parse_header_bad_content_length_minus(self):
+ from waitress.parser import ParsingError
+
+ data = b"GET /foobar HTTP/8.4\r\ncontent-length: -10\r\n"
+
+ try:
+ self.parser.parse_header(data)
+ except ParsingError as e:
+ self.assertIn("Content-Length is invalid", e.args[0])
+ else: # pragma: nocover
+ self.assertTrue(False)
+
def test_parse_header_multiple_content_length(self):
from waitress.parser import ParsingError
From: Bert JW Regeer <bertjw@regeer.org>
Date: Sat, 12 Mar 2022 18:35:01 -0700
Subject: Update tests to remove invalid chunked encoding chunk-size
RFC7230 states the following:
chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
chunk-size = 1*HEXDIG
Where chunk-ext is:
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
Only if there is a chunk-ext should there be a `;` after the 1*HEXDIG.
And a chunk-ext that is empty is invalid.
Part of CVE-2022-24761
---
tests/test_functional.py | 6 +++---
tests/test_parser.py | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tests/test_functional.py b/tests/test_functional.py
index e894497..7a54b22 100644
--- a/tests/test_functional.py
+++ b/tests/test_functional.py
@@ -302,7 +302,7 @@ class EchoTests(object):
self.assertFalse("transfer-encoding" in headers)
def test_chunking_request_with_content(self):
- control_line = b"20;\r\n" # 20 hex = 32 dec
+ control_line = b"20\r\n" # 20 hex = 32 dec
s = b"This string has 32 characters.\r\n"
expected = s * 12
header = tobytes("GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n")
@@ -321,7 +321,7 @@ class EchoTests(object):
self.assertFalse("transfer-encoding" in headers)
def test_broken_chunked_encoding(self):
- control_line = "20;\r\n" # 20 hex = 32 dec
+ control_line = "20\r\n" # 20 hex = 32 dec
s = "This string has 32 characters.\r\n"
to_send = "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
to_send += control_line + s + "\r\n"
@@ -346,7 +346,7 @@ class EchoTests(object):
self.assertRaises(ConnectionClosed, read_http, fp)
def test_broken_chunked_encoding_missing_chunk_end(self):
- control_line = "20;\r\n" # 20 hex = 32 dec
+ control_line = "20\r\n" # 20 hex = 32 dec
s = "This string has 32 characters.\r\n"
to_send = "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
to_send += control_line + s
diff --git a/tests/test_parser.py b/tests/test_parser.py
index eabf353..420f280 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -152,7 +152,7 @@ class TestHTTPRequestParser(unittest.TestCase):
b"Transfer-Encoding: chunked\r\n"
b"X-Foo: 1\r\n"
b"\r\n"
- b"1d;\r\n"
+ b"1d\r\n"
b"This string has 29 characters\r\n"
b"0\r\n\r\n"
)
From: Bert JW Regeer <bertjw@regeer.org>
Date: Sat, 12 Mar 2022 18:42:51 -0700
Subject: Error when receiving back Chunk Extension
Waitress discards chunked extensions and does no further processing on
them, however it failed to validate that the chunked encoding extension
did not contain invalid data.
We now validate that if there are any chunked extensions that they are
well-formed, if they are not and contain invalid characters, then
Waitress will now correctly return a Bad Request and stop any further
processing of the request.
Part of CVE-2022-24761
---
src/waitress/receiver.py | 11 ++++++++++-
tests/test_functional.py | 22 ++++++++++++++++++++++
tests/test_receiver.py | 37 +++++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/src/waitress/receiver.py b/src/waitress/receiver.py
index 5d1568d..106dbc7 100644
--- a/src/waitress/receiver.py
+++ b/src/waitress/receiver.py
@@ -14,6 +14,7 @@
"""Data Chunk Receiver
"""
+from waitress.rfc7230 import CHUNK_EXT_RE, ONLY_HEXDIG_RE
from waitress.utilities import BadRequest, find_double_newline
@@ -110,6 +111,7 @@ class ChunkedReceiver(object):
s = b""
else:
self.chunk_end = b""
+
if pos == 0:
# Chop off the terminating CR LF from the chunk
s = s[2:]
@@ -140,7 +142,14 @@ class ChunkedReceiver(object):
semi = line.find(b";")
if semi >= 0:
- # discard extension info.
+ extinfo = line[semi:]
+ valid_ext_info = CHUNK_EXT_RE.match(extinfo)
+
+ if not valid_ext_info:
+ self.error = BadRequest("Invalid chunk extension")
+ self.all_chunks_received = True
+
+ break
line = line[:semi]
try:
sz = int(line.strip(), 16) # hexadecimal
diff --git a/tests/test_functional.py b/tests/test_functional.py
index 7a54b22..853942c 100644
--- a/tests/test_functional.py
+++ b/tests/test_functional.py
@@ -345,6 +345,28 @@ class EchoTests(object):
self.send_check_error(to_send)
self.assertRaises(ConnectionClosed, read_http, fp)
+ def test_broken_chunked_encoding_invalid_extension(self):
+ control_line = b"20;invalid=\r\n" # 20 hex = 32 dec
+ s = b"This string has 32 characters.\r\n"
+ to_send = b"GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
+ to_send += control_line + s + b"\r\n"
+ self.connect()
+ self.sock.send(to_send)
+ with self.sock.makefile("rb", 0) as fp:
+ line, headers, response_body = read_http(fp)
+ self.assertline(line, "400", "Bad Request", "HTTP/1.1")
+ cl = int(headers["content-length"])
+ self.assertEqual(cl, len(response_body))
+ self.assertIn(b"Invalid chunk extension", response_body)
+ self.assertEqual(
+ sorted(headers.keys()),
+ ["connection", "content-length", "content-type", "date", "server"],
+ )
+ self.assertEqual(headers["content-type"], "text/plain")
+ # connection has been closed
+ self.send_check_error(to_send)
+ self.assertRaises(ConnectionClosed, read_http, fp)
+
def test_broken_chunked_encoding_missing_chunk_end(self):
control_line = "20\r\n" # 20 hex = 32 dec
s = "This string has 32 characters.\r\n"
diff --git a/tests/test_receiver.py b/tests/test_receiver.py
index b4910bb..a6261ea 100644
--- a/tests/test_receiver.py
+++ b/tests/test_receiver.py
@@ -1,5 +1,7 @@
import unittest
+import pytest
+
class TestFixedStreamReceiver(unittest.TestCase):
def _makeOne(self, cl, buf):
@@ -226,6 +228,41 @@ class TestChunkedReceiver(unittest.TestCase):
self.assertEqual(inst.error, None)
+class TestChunkedReceiverParametrized:
+ def _makeOne(self, buf):
+ from waitress.receiver import ChunkedReceiver
+
+ return ChunkedReceiver(buf)
+
+ @pytest.mark.parametrize(
+ "invalid_extension", [b"\n", b"invalid=", b"\r", b"invalid = true"]
+ )
+ def test_received_invalid_extensions(self, invalid_extension):
+ from waitress.utilities import BadRequest
+
+ buf = DummyBuffer()
+ inst = self._makeOne(buf)
+ data = b"4;" + invalid_extension + b"\r\ntest\r\n"
+ result = inst.received(data)
+ assert result == len(data)
+ assert inst.error.__class__ == BadRequest
+ assert inst.error.body == "Invalid chunk extension"
+
+ @pytest.mark.parametrize(
+ "valid_extension", [b"test", b"valid=true", b"valid=true;other=true"]
+ )
+ def test_received_valid_extensions(self, valid_extension):
+ # While waitress may ignore extensions in Chunked Encoding, we do want
+ # to make sure that we don't fail when we do encounter one that is
+ # valid
+ buf = DummyBuffer()
+ inst = self._makeOne(buf)
+ data = b"4;" + valid_extension + b"\r\ntest\r\n"
+ result = inst.received(data)
+ assert result == len(data)
+ assert inst.error == None
+
+
class DummyBuffer(object):
def __init__(self, data=None):
if data is None:
From: Bert JW Regeer <bertjw@regeer.org>
Date: Sat, 12 Mar 2022 18:48:26 -0700
Subject: Validate chunk size in Chunked Encoding are HEXDIG
RFC7230 states that a chunk-size should be 1*HEXDIG, this is now
validated before passing the resulting string to int() which would also
parse other formats for hex, such as: `0x01` as `1` and `+0x01` as `1`.
This would lead to a potential for a frontend proxy server and waitress
to disagree on where a chunk started and ended, thereby potentially
leading to request smuggling.
With the increased validation if the size is not just hex digits,
Waitress now returns a Bad Request and stops processing the request.
Part of CVE-2022-24761
---
src/waitress/receiver.py | 19 ++++++++++++++-----
tests/test_functional.py | 22 ++++++++++++++++++++++
tests/test_receiver.py | 12 ++++++++++++
3 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/src/waitress/receiver.py b/src/waitress/receiver.py
index 106dbc7..9e4bffe 100644
--- a/src/waitress/receiver.py
+++ b/src/waitress/receiver.py
@@ -150,12 +150,21 @@ class ChunkedReceiver(object):
self.all_chunks_received = True
break
+
line = line[:semi]
- try:
- sz = int(line.strip(), 16) # hexadecimal
- except ValueError: # garbage in input
- self.error = BadRequest("garbage in chunked encoding input")
- sz = 0
+
+ # Remove any whitespace
+ line = line.strip()
+
+ if not ONLY_HEXDIG_RE.match(line):
+ self.error = BadRequest("Invalid chunk size")
+ self.all_chunks_received = True
+
+ break
+
+ # Can not fail due to matching against the regular
+ # expression above
+ sz = int(line.strip(), 16) # hexadecimal
if sz > 0:
# Start a new chunk.
diff --git a/tests/test_functional.py b/tests/test_functional.py
index 853942c..448e0c0 100644
--- a/tests/test_functional.py
+++ b/tests/test_functional.py
@@ -345,6 +345,28 @@ class EchoTests(object):
self.send_check_error(to_send)
self.assertRaises(ConnectionClosed, read_http, fp)
+ def test_broken_chunked_encoding_invalid_hex(self):
+ control_line = b"0x20\r\n" # 20 hex = 32 dec
+ s = b"This string has 32 characters.\r\n"
+ to_send = b"GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
+ to_send += control_line + s + b"\r\n"
+ self.connect()
+ self.sock.send(to_send)
+ with self.sock.makefile("rb", 0) as fp:
+ line, headers, response_body = read_http(fp)
+ self.assertline(line, "400", "Bad Request", "HTTP/1.1")
+ cl = int(headers["content-length"])
+ self.assertEqual(cl, len(response_body))
+ self.assertIn(b"Invalid chunk size", response_body)
+ self.assertEqual(
+ sorted(headers.keys()),
+ ["connection", "content-length", "content-type", "date", "server"],
+ )
+ self.assertEqual(headers["content-type"], "text/plain")
+ # connection has been closed
+ self.send_check_error(to_send)
+ self.assertRaises(ConnectionClosed, read_http, fp)
+
def test_broken_chunked_encoding_invalid_extension(self):
control_line = b"20;invalid=\r\n" # 20 hex = 32 dec
s = b"This string has 32 characters.\r\n"
diff --git a/tests/test_receiver.py b/tests/test_receiver.py
index a6261ea..17328d4 100644
--- a/tests/test_receiver.py
+++ b/tests/test_receiver.py
@@ -262,6 +262,18 @@ class TestChunkedReceiverParametrized:
assert result == len(data)
assert inst.error == None
+ @pytest.mark.parametrize("invalid_size", [b"0x04", b"+0x04", b"x04", b"+04"])
+ def test_received_invalid_size(self, invalid_size):
+ from waitress.utilities import BadRequest
+
+ buf = DummyBuffer()
+ inst = self._makeOne(buf)
+ data = invalid_size + b"\r\ntest\r\n"
+ result = inst.received(data)
+ assert result == len(data)
+ assert inst.error.__class__ == BadRequest
+ assert inst.error.body == "Invalid chunk size"
+
class DummyBuffer(object):
def __init__(self, data=None):
From: Bert JW Regeer <bertjw@regeer.org>
Date: Sat, 12 Mar 2022 19:16:23 -0700
Subject: Remove extraneous calls to .strip() in Chunked Encoding
To be valid chunked encoding we should not be removing any whitespace as
the standard does not allow for optional whitespace.
If whitespace is encountered in the wrong place, it should lead to a 400
Bad Request instead.
Part of CVE-2022-24761
---
src/waitress/receiver.py | 6 +-----
tests/test_receiver.py | 4 +++-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/waitress/receiver.py b/src/waitress/receiver.py
index 9e4bffe..806ff87 100644
--- a/src/waitress/receiver.py
+++ b/src/waitress/receiver.py
@@ -135,7 +135,6 @@ class ChunkedReceiver(object):
line = s[:pos]
s = s[pos + 2 :]
self.control_line = b""
- line = line.strip()
if line:
# Begin a new chunk.
@@ -153,9 +152,6 @@ class ChunkedReceiver(object):
line = line[:semi]
- # Remove any whitespace
- line = line.strip()
-
if not ONLY_HEXDIG_RE.match(line):
self.error = BadRequest("Invalid chunk size")
self.all_chunks_received = True
@@ -164,7 +160,7 @@ class ChunkedReceiver(object):
# Can not fail due to matching against the regular
# expression above
- sz = int(line.strip(), 16) # hexadecimal
+ sz = int(line, 16) # hexadecimal
if sz > 0:
# Start a new chunk.
diff --git a/tests/test_receiver.py b/tests/test_receiver.py
index 17328d4..014f785 100644
--- a/tests/test_receiver.py
+++ b/tests/test_receiver.py
@@ -262,7 +262,9 @@ class TestChunkedReceiverParametrized:
assert result == len(data)
assert inst.error == None
- @pytest.mark.parametrize("invalid_size", [b"0x04", b"+0x04", b"x04", b"+04"])
+ @pytest.mark.parametrize(
+ "invalid_size", [b"0x04", b"+0x04", b"x04", b"+04", b" 04", b" 0x04"]
+ )
def test_received_invalid_size(self, invalid_size):
from waitress.utilities import BadRequest
[buildout]
extends =
../golang/buildout.cfg
../../stack/slapos.cfg
parts =
slapos-cookbook
......
[buildout]
extends =
buildout.hash.cfg
../../stack/slapos.cfg
../openssl/buildout.cfg
../jupyter/buildout.cfg
../../stack/monitor/buildout.cfg
......
......@@ -186,11 +186,6 @@
},
"type": "object"
},
"wsgi": {
"description": "If set to true, Zope is run as a WSGI application, instead of using the Medusa HTTP server.",
"type": "boolean",
"default": true
},
"zope-partition-dict": {
"description": "Zope layout definition",
"default": {
......
......@@ -124,16 +124,6 @@ class TestDefaultParameters(ERP5InstanceTestCase, TestPublishedURLIsReachableMix
__test_matrix__ = matrix((default,))
class TestMedusa(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 Medusa server
"""
__partition_reference__ = 'medusa'
@classmethod
def getInstanceParameterDict(cls):
return {'_': json.dumps({'wsgi': False})}
class TestJupyter(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 Jupyter notebook
"""
......@@ -366,16 +356,18 @@ class TestZopeNodeParameterOverride(ERP5InstanceTestCase, TestPublishedURLIsReac
zodb["mount-point"] = "/"
zodb["pool-size"] = 4
zodb["pool-timeout"] = "10m"
zodb["%import"] = "ZEO"
storage["storage"] = "root"
storage["server"] = zeo_addr
storage["server-sync"] = "true"
with open(f'{partition}/etc/zope-{zope}.conf') as f:
conf = list(map(str.strip, f.readlines()))
i = conf.index("<zodb_db root>") + 1
conf = iter(conf[i:conf.index("</zodb_db>", i)])
for line in conf:
if line == '<zeoclient>':
if line == '<clientstorage>':
for line in conf:
if line == '</zeoclient>':
if line == '</clientstorage>':
break
checkParameter(line, storage)
for k, v in storage.items():
......@@ -525,8 +517,6 @@ class ZopeSkinsMixin:
class ZopeTestMixin(ZopeSkinsMixin, CrontabMixin):
"""Mixin class for zope features.
"""
wsgi = NotImplemented # type: bool
__partition_reference__ = 'z'
@classmethod
......@@ -545,8 +535,7 @@ class ZopeTestMixin(ZopeSkinsMixin, CrontabMixin):
"port-base": 2210,
},
},
"wsgi": cls.wsgi,
})
}),
}
@classmethod
......@@ -884,20 +873,9 @@ class ZopeTestMixin(ZopeSkinsMixin, CrontabMixin):
'zope-2-event.log',
])
class TestZopeMedusa(ZopeTestMixin, ERP5InstanceTestCase):
wsgi = False
class TestZopeWSGI(ZopeTestMixin, ERP5InstanceTestCase):
wsgi = True
@unittest.expectedFailure
def test_long_request_log_rotation(self):
super().test_long_request_log_rotation()
@unittest.expectedFailure
def test_basic_authentication_user_in_access_log(self):
super().test_basic_authentication_user_in_access_log()
pass
class TestZopePublisherTimeout(ZopeSkinsMixin, ERP5InstanceTestCase):
......
......@@ -34,7 +34,6 @@ interpreter = ${:_buildout_section_name_}
[versions]
# To match ERP5
zope.event = 3.5.2
zope.exceptions = 3.6.2
zope.testing = 3.9.7
zope.exceptions = 4.6
zope.testing = 4.10
##
......@@ -7,13 +7,6 @@ parts +=
vifib-fix-products-paths
# SlapOS Master needs to use Wendelin.core 2.
# Wendelin.core 2 works with either ZODB4-wc2, or ZODB5, but not with ZODB4.
# ERP5 does not currently work with ZODB5.
# -> this leaves ZODB4-wc2 as the only choice.
[ZODB]
major = 4-wc2
[erp5-defaults]
wcfs-enable-default = true
......
......@@ -112,15 +112,6 @@ class TestDefaultParameters(
__partition_reference__ = 'defp'
class TestMedusa(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 Medusa server
"""
__partition_reference__ = 'medusa'
@classmethod
def getInstanceParameterDict(cls):
return {'_': json.dumps({'wsgi': False})}
class TestJupyter(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 Jupyter notebook
"""
......@@ -288,16 +279,18 @@ class TestZopeNodeParameterOverride(ERP5InstanceTestCase, TestPublishedURLIsReac
zodb["mount-point"] = "/"
zodb["pool-size"] = 4
zodb["pool-timeout"] = "10m"
zodb["%import"] = "ZEO"
storage["storage"] = "root"
storage["server"] = zeo_addr
storage["server-sync"] = "true"
with open(f'{partition}/etc/zope-{zope}.conf') as f:
conf = list(map(str.strip, f.readlines()))
i = conf.index("<zodb_db root>") + 1
conf = iter(conf[i:conf.index("</zodb_db>", i)])
for line in conf:
if line == '<zeoclient>':
if line == '<clientstorage>':
for line in conf:
if line == '</zeoclient>':
if line == '</clientstorage>':
break
checkParameter(line, storage)
for k, v in storage.items():
......@@ -369,7 +362,6 @@ class TestDeploymentScriptInstantiation(ERP5InstanceTestCase):
"timezone": "UTC",
"site-id": "erp5",
"bt5": "erp5_full_text_myisam_catalog slapos_configurator",
"wsgi": False,
"test-runner": {"enabled": False}, # won't work anyway here
"zope-partition-dict": {
"admin": {
......
[buildout]
extends =
# Exact version of Zope
ztk-versions.cfg
# versions pins from zope, vendored with:
# curl https://zopefoundation.github.io/Zope/releases/4.8.7/versions-prod.cfg > zope-versions.cfg
# When updating, keep in mind that some versions are defined in other places,
# for example component/ZEO , component/ZODB and stack/slapos
zope-versions.cfg
../slapos.cfg
buildout.hash.cfg
../../component/fonts/buildout.cfg
../../component/git/buildout.cfg
......@@ -506,30 +509,18 @@ eggs +=
ipywidgets
requests
[zope-product-with-eggtestinfo]
[egg-with-zope-proxy]
recipe = zc.recipe.egg:custom
setup-eggs =
eggtestinfo
zope.proxy
egg = ${:_buildout_section_name_}
[Products.CMFUid]
<= zope-product-with-eggtestinfo
[Products.CMFActionIcons]
<= zope-product-with-eggtestinfo
[Products.CMFCalendar]
<= zope-product-with-eggtestinfo
[Products.CMFCore]
<= zope-product-with-eggtestinfo
[Products.CMFDefault]
<= zope-product-with-eggtestinfo
[Products.CMFTopic]
<= zope-product-with-eggtestinfo
[Products.DCWorkflow]
<= zope-product-with-eggtestinfo
Products.DCWorkflow-patches = ${:_profile_base_location_}/../../component/egg-patch/Products.DCWorkflow/workflow_method.patch#975b49e96bae33ac8563454fe5fa9899
Products.DCWorkflow-patch-options = -p1
[Products.GenericSetup]
<= zope-product-with-eggtestinfo
[zope.security]
<= egg-with-zope-proxy
[zope.container]
<= egg-with-zope-proxy
setup-eggs +=
${persistent:egg}
[eggs]
<= neoppod
......@@ -614,6 +605,8 @@ eggs = ${neoppod:eggs}
xlrd
# Zope
${zope.security:egg}
${zope.container:egg}
Zope2
${tempstorage:egg}
# Zope acquisition patch
......@@ -623,27 +616,11 @@ eggs = ${neoppod:eggs}
# Other Zope 2 packages
Products.PluggableAuthService
Products.PluginRegistry
# CMF 2.2
${Products.CMFActionIcons:egg}
${Products.CMFCalendar:egg}
${Products.CMFCore:egg}
${Products.CMFDefault:egg}
${Products.CMFTopic:egg}
${Products.CMFUid:egg}
${Products.DCWorkflow:egg}
${Products.GenericSetup:egg}
five.localsitemanager
Products.DCWorkflow
# Other products
Products.MimetypesRegistry
Products.TIDStorage
Products.LongRequestLogger
# BBB: Temporarily keep zope.app.testing awaiting we use newer version of CMF
# (for tests like testCookieCrumbler).
zope.app.testing
# Currently forked in our repository
# Products.PortalTransforms
......@@ -677,6 +654,21 @@ eggs = ${neoppod:eggs}
strict-rfc3339
jsonschema[format]
# Used by zope4
docutils
zLOG
Products.ZSQLMethods
ZServer
Products.ExternalMethod
Products.SiteErrorLog
tempstorage
Products.DCWorkflow
Products.Sessions
Products.ZODBMountPoint
Record
haufe.requestmonitoring
Zope
entry-points =
runwsgi=Products.ERP5.bin.zopewsgi:runwsgi
scripts =
......@@ -695,13 +687,23 @@ extra-paths =
# patches for eggs
patch-binary = ${patch:location}/bin/patch
Acquisition-patches = ${:_profile_base_location_}/../../component/egg-patch/Acquisition/aq_dynamic-4.7.patch#85b0090e216cead0fc86c5c274450d96
Acquisition-patch-options = -p1
Products.DCWorkflow-patches = ${:_profile_base_location_}/../../component/egg-patch/Products.DCWorkflow/workflow_method-2.4.1.patch#ec7bb56a9f1d37fcbf960cd1e96e6e6d
Products.DCWorkflow-patch-options = -p1
PyPDF2-patches = ${:_profile_base_location_}/../../component/egg-patch/PyPDF2/0001-Custom-implementation-of-warnings.formatwarning-remo.patch#d25bb0f5dde7f3337a0a50c2f986f5c8
PyPDF2-patch-options = -p1
Acquisition-patches = ${:_profile_base_location_}/../../component/egg-patch/Acquisition/aq_dynamic-2.13.12.patch#1d9a56e9af4371f5b6951ebf217a15d7
Acquisition-patch-options = -p1
python-magic-patches = ${:_profile_base_location_}/../../component/egg-patch/python_magic/magic.patch#de0839bffac17801e39b60873a6c2068
python-magic-patch-options = -p1
# backported security patches for waitress-1.4.4 from Debian 1.4.4-1.1+deb11u1 package.
waitress-patches =
${:_profile_base_location_}/../../component/egg-patch/waitress/CVE-2022-24761-1.patch#a0508880f24662e48a20ce3bcbf440c2
${:_profile_base_location_}/../../component/egg-patch/waitress/CVE-2022-24761-2.patch#1ff77cede06d5bc39a9891d3647708a2
${:_profile_base_location_}/../../component/egg-patch/waitress/CVE-2022-24761-3.patch#8bab78102e0c2966f6bcafde7819ea8e
${:_profile_base_location_}/../../component/egg-patch/waitress/CVE-2022-24761-4.patch#d752ca3ac251ebfaf36c667b28744c20
${:_profile_base_location_}/../../component/egg-patch/waitress/CVE-2022-24761-5.patch#ad2765822397cd1e28e02a68a52d7768
${:_profile_base_location_}/../../component/egg-patch/waitress/CVE-2022-24761-6.patch#85fc9c4105eabee3ff71c800b2ddf63b
waitress-patch-options = -p1
# neoppod installs bin/coverage so we inject erp5 plugin here so that coverage script can use it in report
[neoppod]
......@@ -733,143 +735,137 @@ depends =
# neoppod, mysqlclient, slapos.recipe.template
# patched eggs
Acquisition = 2.13.12+SlapOSPatched001
Products.DCWorkflow = 2.2.4+SlapOSPatched001
Acquisition = 4.7+SlapOSPatched001
Products.DCWorkflow = 2.4.1+SlapOSPatched001
ocropy = 1.0+SlapOSPatched001
pysvn = 1.9.15+SlapOSPatched001
python-ldap = 2.4.32+SlapOSPatched001
python-magic = 0.4.12+SlapOSPatched001
PyPDF2 = 1.26.0+SlapOSPatched001
waitress = 1.4.4+SlapOSPatched006
## https://lab.nexedi.com/nexedi/slapos/merge_requests/648
pylint = 1.4.4+SlapOSPatched002
# astroid 1.4.1 breaks testDynamicClassGeneration
astroid = 1.3.8+SlapOSPatched001
# use newer version than specified in ZTK
PasteDeploy = 1.5.2
argparse = 1.4.0
zope.dottedname = 4.1.0
# modified version that works fine for buildout installation
SOAPpy = 0.12.0nxd001
# CMF 2.3 is not yet supported.
Products.CMFCalendar = 2.2.3
Products.CMFCore = 2.2.10
Products.CMFDefault = 2.2.4
Products.CMFTopic = 2.2.1
Products.CMFUid = 2.2.1
# newer version requires zope.traversing>=4.0.0a2.
zope.app.appsetup = 3.16.0
# newer version requires zope.i18n>=4.0.0a3
zope.app.publication = 3.14.0
# newer version requires zope.testbrowser>=4
zope.app.testing = 3.8.1
# Pinned versions
alabaster = 0.7.12
APacheDEX = 1.8
Pillow = 6.2.2
Products.CMFActionIcons = 2.1.3
Products.GenericSetup = 1.8.6
Products.LongRequestLogger = 2.1.0
# Products.MimetypesRegistry 2.1 requires AccessControl>=3.0.0Acquisition.
Products.MimetypesRegistry = 2.0.10
Products.PluggableAuthService = 1.10.0
Products.PluginRegistry = 1.4
Products.TIDStorage = 5.5.0
pyPdf = 1.13
PyStemmer = 1.3.0
Pympler = 0.4.3
StructuredText = 2.11.1
WSGIUtils = 0.7
Beaker = 1.11.0
beautifulsoup4 = 4.8.2
cloudpickle = 0.5.3
cookies = 2.2.1
dask = 0.18.1
deepdiff = 3.3.0
docutils = 0.17.1
erp5-coverage-plugin = 0.0.1
erp5diff = 0.8.1.8
facebook-sdk = 2.0.0
five.formlib = 1.0.4
five.localsitemanager = 2.0.5
fpconst = 0.7.2
future = 0.18.2
google-api-python-client = 1.6.1
graphviz = 0.5.2
haufe.requestmonitoring = 0.6.0
html5lib = 1.1
httplib2 = 0.10.3
huBarcode = 1.0.0
interval = 1.0.0
ipdb = 0.10.2
jdcal = 1.3
jedi = 0.15.1
jsonpickle = 0.9.6
jsonpointer = 2.2
logilab-common = 1.3.0
Mako = 1.1.4
mechanize = 0.4.8
mpmath = 0.19
munnel = 0.3
networkx = 2.1
nt-svcutils = 2.13.0
numpy = 1.13.1
oauth2client = 4.0.0
oauthlib = 3.1.0
objgraph = 3.1.0
oic = 0.15.1
olefile = 0.44
openpyxl = 2.4.8
pandas = 0.19.2
parso = 0.5.1
Pillow = 6.2.2
polib = 1.0.8
pprofile = 2.0.4
Products.CMFCore = 2.7.0
Products.ExternalMethod = 4.7
Products.GenericSetup = 2.3.0
Products.MailHost = 4.13
Products.MimetypesRegistry = 2.1.8
Products.PluggableAuthService = 2.8.1
Products.PluginRegistry = 1.6
Products.PythonScripts = 4.15
Products.Sessions = 4.15
Products.SiteErrorLog = 5.7
Products.StandardCacheManagers = 4.2
Products.TIDStorage = 5.5.0
Products.ZODBMountPoint = 1.3
Products.ZSQLMethods = 3.16
pyasn1-modules = 0.0.8
pycountry = 17.1.8
pycrypto = 2.6.1
pycryptodomex = 3.10.1
pyflakes = 1.5.0
pyjwkest = 1.4.2
Pympler = 0.4.3
pyPdf = 1.13
PyStemmer = 1.3.0
pytesseract = 0.2.2
python-gettext = 4.1
python-libmilter = 1.0.3
python-memcached = 1.58
pytracemalloc = 1.2
PyWavelets = 0.5.2
qrcode = 5.3
responses = 0.10.6
rfc3987 = 1.3.8
rsa = 3.4.2
scikit-image = 0.14.0
scipy = 0.19.0
soupsieve = 1.9.5
spyne = 2.12.14
strict-rfc3339 = 0.7
StructuredText = 2.11.1
suds = 0.4
facebook-sdk = 2.0.0
toolz = 0.9.0
typing = 3.10.0.0
unidiff = 0.5.5
urlnorm = 1.1.4
uuid = 1.30
validictory = 1.1.0
webcolors = 1.10
webencodings = 0.5.1
WebOb = 1.8.5
WebTest = 2.0.33
WSGIProxy2 = 0.4.6
WSGIUtils = 0.7
xfw = 0.10
xupdate-processor = 0.5
scikit-image = 0.14.0
PyWavelets = 0.5.2
networkx = 2.1
pytesseract = 0.2.2
yapf = 0.28.0
z3c.etestbrowser = 3.0.1
zbarlight = 2.3
cloudpickle = 0.5.3
dask = 0.18.1
toolz = 0.9.0
zope.globalrequest = 1.5
waitress = 1.4.4
Products.ZSQLMethods = 2.13.5
fpconst = 0.7.2
graphviz = 0.5.2
olefile = 0.44
python-libmilter = 1.0.3
zLOG = 3.1
zope.app.appsetup = 4.2.0
zope.app.debug = 3.4.1
zope.app.dependable = 3.5.1
zope.app.form = 4.0.2
mpmath = 0.19
openpyxl = 2.4.8
jdcal = 1.3
deepdiff = 3.3.0
unidiff = 0.5.5
jsonpickle = 0.9.6
responses = 0.10.6
cookies = 2.2.1
jedi = 0.15.1
parso = 0.5.1
yapf = 0.28.0
z3c.etestbrowser = 3.0.1
zope.app.form = 5.1.0
zope.app.publication = 4.5
zope.app.testing = 4.0.0
zope.authentication = 5.0
zope.error = 4.6
zope.minmax = 2.3
zope.password = 4.4
zope.session = 4.5
zope.testbrowser = 5.5.1
WSGIProxy2 = 0.4.6
WebTest = 2.0.33
beautifulsoup4 = 4.8.2
WebOb = 1.8.5
soupsieve = 1.9.5
eggtestinfo = 0.3
oic = 0.15.1
Beaker = 1.11.0
Mako = 1.1.4
pyjwkest = 1.4.2
alabaster = 0.7.12
future = 0.18.2
pycryptodomex = 3.10.1
strict-rfc3339 = 0.7
webcolors = 1.10
rfc3987 = 1.3.8
jsonpointer = 2.2
pandas = 0.19.2
numpy = 1.13.1
scipy = 0.19.0
ZConfig = 2.9.3
......@@ -34,11 +34,11 @@ md5sum = 45cc45510b59ceb730b6e38448b5c0c3
[template-zope-conf]
filename = zope.conf.in
md5sum = ce8d03a1b4c1a9e5085ec54ea2744007
md5sum = 07c9d4ced9945fe3ad80e75b493af29e
[site-zcml]
filename = site.zcml
md5sum = 43556e5bca8336dd543ae8068512aa6d
md5sum = f45dc4568b63de39f49b8fecca5deef1
[template-my-cnf]
filename = my.cnf.in
......@@ -78,7 +78,7 @@ md5sum = 30a1e738a8211887e75a5e75820e5872
[template-zeo]
filename = instance-zeo.cfg.in
md5sum = 0ba5735ab87ee53e2c203b1563b55ff0
md5sum = d86d6808b745ee66be3a914487b25744
[template-zodb-base]
filename = instance-zodb-base.cfg.in
......@@ -86,7 +86,7 @@ md5sum = 0ac4b74436f554cd677f19275d18d880
[template-zope]
filename = instance-zope.cfg.in
md5sum = 0451190711157fc204418662126d5cf8
md5sum = 558ffbc6d51bb0ce9fc25d1062edcd2a
[template-balancer]
filename = instance-balancer.cfg.in
......
......@@ -28,7 +28,7 @@ ip = {{ ipv4 }}
{% set current_port = next(ports) -%}
{% set known_tid_storage_identifier_host = (ipv4, current_port), -%}
{% for name, zodb in zodb -%}
{% do storage_dict.__setitem__(name, {'server': ipv4 ~ ':' ~ current_port, 'storage': name}) %}
{% do storage_dict.__setitem__(name, {'server': ipv4 ~ ':' ~ current_port, 'storage': name, 'server-sync': 'true'}) %}
{% set path = zodb.get('path', '%(zodb)s/%(name)s.fs') % {'zodb': default_zodb_path, 'name': name} -%}
{% do storage_list.append((name, path)) -%}
{% set backup_directory = zodb.get('backup', '%(backup)s/%(name)s') % {'backup': default_backup_path, 'name': name} -%}
......
{% from "instance_zodb_base" import zodb_dict with context %}
{% set wsgi = slapparameter_dict['wsgi'] -%}
{% set webdav = slapparameter_dict['webdav'] -%}
{% set thread_amount = slapparameter_dict['thread-amount'] %}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
{% set ports = itertools.count(slapparameter_dict['port-base']) -%}
{% set site_id = slapparameter_dict['site-id'] -%}
......@@ -107,7 +107,6 @@ instance-etc-package-include = ${:instance}/etc/package-include
instance-extensions = ${:instance}/Extensions
instance-import = ${:instance}/import
instance-lib = ${:instance}/lib
instance-products = ${:instance}/Products
instance-propertysheet = ${:instance}/PropertySheet
instance-tests = ${:instance}/tests
log = ${:var}/log
......@@ -243,19 +242,6 @@ pem = {{dumps(storage_dict.pop(k))}}
{% endfor -%}
{# endhack -#}
[runzope-base]
<= run-common
instance-home = ${directory:instance}
{% if wsgi -%}
wrapped-command-line = '{{ bin_directory }}/runwsgi' {% if webdav %}-w{% endif %} {{ ipv4 }}:${:port} {% if timerserver_interval %}--timerserver-interval={{ timerserver_interval }}{% endif %} '${:configuration-file}'
{% else -%}
wrapped-command-line = '{{ bin_directory }}/runzope' -C '${:configuration-file}'
{%- endif %}
{%- set private_dev_shm = slapparameter_dict['private-dev-shm'] %}
{%- if private_dev_shm %}
private-tmpfs = {{ private_dev_shm }} /dev/shm
{%- endif %}
[{{ section('zcml') }}]
recipe = slapos.cookbook:copyfilelist
target-directory = ${directory:instance-etc}
......@@ -288,19 +274,12 @@ developer-list = {{ dumps(slapparameter_dict['developer-list']) }}
publisher-timeout = {{ dumps(slapparameter_dict['publisher-timeout']) }}
activity-timeout = {{ dumps(slapparameter_dict['activity-timeout']) }}
instance = ${directory:instance}
instance-products = ${directory:instance-products}
deadlock-path = /manage_debug_threads
deadlock-debugger-password = {{ dumps(slapparameter_dict['deadlock-debugger-password']) }}
{% if slapparameter_dict.get('tidstorage-ip') -%}
tidstorage-ip = {{ dumps(slapparameter_dict['tidstorage-ip']) }}
tidstorage-port = {{ dumps(slapparameter_dict['tidstorage-port']) }}
{% endif -%}
{% set thread_amount = slapparameter_dict['thread-amount'] -%}
{% set large_file_threshold = slapparameter_dict['large-file-threshold'] -%}
thread-amount = {{ thread_amount }}
webdav = {{ dumps(webdav) }}
wsgi = {{ dumps(wsgi) }}
timerserver-interval = {{ dumps(timerserver_interval) }}
[zope-conf-base]
< = jinja2-template-base
......@@ -325,7 +304,6 @@ import-list =
[{{ conf_parameter_name }}]
< = zope-conf-parameter-base
pid-file = ${directory:run}/{{ name }}.pid
lock-file = ${directory:run}/{{ name }}.lock
port = {{ port }}
event-log = ${directory:log}/{{ name }}-event.log
z2-log = ${directory:log}/{{ name }}-Z2.log
......@@ -343,7 +321,6 @@ node-id = {{ dumps(node_id_base ~ (node_id_index_format % index)) }}
{% endfor -%}
import-list = {{ dumps(list(import_set)) }}
zodb-dict = {{ dumps(zodb_dict) }}
large-file-threshold = {{ large_file_threshold }}
{% if longrequest_logger_interval > 0 -%}
longrequest-logger-file = {{ longrequest_logger_base_path ~ name ~ ".log" }}
longrequest-logger-timeout = {{ longrequest_logger_timeout }}
......@@ -361,17 +338,32 @@ context =
import re re
[{{ section(name) }}]
< = runzope-base
wrapper-path = ${directory:service-on-watch}/{{ name }}
configuration-file = {{ '${' ~ conf_name ~ ':output}' }}
{%- if wsgi %}
port = {{ port }}
<= run-common
wrapped-command-line =
'{{ bin_directory }}/runwsgi'
--event-log-file={{ '${' ~ conf_parameter_name ~ ':event-log}' }}
--access-log-file={{ '${' ~ conf_parameter_name ~ ':z2-log}' }}
{% if longrequest_logger_interval > 0 %} --long-request-log-file={{ '${' ~ conf_parameter_name ~ ':longrequest-logger-file}' }} {% endif %}
{% if webdav %}-w{% endif %}
{{ ipv4 }}:${:port}
{% if timerserver_interval %}--timerserver-interval={{ timerserver_interval }}{% endif %}
'${:configuration-file}'
--threads={{ thread_amount }}
--large-file-threshold={{ slapparameter_dict['large-file-threshold'] }}
{%- set private_dev_shm = slapparameter_dict['private-dev-shm'] %}
{%- if private_dev_shm %}
private-tmpfs = {{ private_dev_shm }} /dev/shm
{%- endif %}
wrapper-path = ${directory:service-on-watch}/{{ name }}
hash-files =
${:configuration-file}
hash-existing-files =
${buildout:directory}/software_release/buildout.cfg
configuration-file = {{ '${' ~ conf_name ~ ':output}' }}
instance-home = ${directory:instance}
port = {{ port }}
[{{ section("promise-" ~ name) }}]
{% if six.PY3 -%}
# Disable the promise in Python 3. ERP5 is not compatible with Python 3 yet, so
......@@ -417,7 +409,7 @@ config-maximum-delay = {{ slapparameter_dict["zope-longrequest-logger-maximum-de
< = logrotate-entry-base
name = {{ name }}
log = {{ '${' ~ conf_parameter_name ~ ':event-log}' }} {{ '${' ~ conf_parameter_name ~ ':z2-log}' }} {{ '${' ~ conf_parameter_name ~ ':longrequest-logger-file}' }} {{ ' '.join(log_list) }}
post = test ! -s {{ '${' ~ conf_parameter_name ~ ':pid-file}' }} || {{ bin_directory }}/slapos-kill --pidfile {{ '${' ~ conf_parameter_name ~ ':pid-file}' }} -s USR2
copytruncate = true
{% endmacro -%}
{% for i in instance_index_list -%}
......@@ -492,9 +484,6 @@ environment-extra =
SQLBENCH_PATH={{ parameter_dict['sqlbench_path'] }}
TEST_CA_PATH=${directory:ca-dir}
ERP5_TEST_RUNNER_CONFIGURATION=${test-runner-configuration:output}
{%- if wsgi %}
erp5_wsgi=1
{%- endif %}
instance-home = ${directory:unit-test-path}
wrapper-path = ${directory:bin}/${:command-name}.real
command-line =
......
......@@ -23,4 +23,6 @@
<securityPolicy
component="AccessControl.security.SecurityPolicy" />
<include package="haufe.requestmonitoring" file="monitor.zcml"/>
</configure>
[buildout]
# Version pins for required and commonly used dependencies.
[versions]
Zope2 = 2.13.30
AccessControl = 2.13.16
Acquisition = 2.13.12
DateTime = 2.12.8
DocumentTemplate = 2.13.6
ExtensionClass = 2.13.2
Jinja2 = 2.8.1
MarkupSafe = 1.1.1
Missing = 2.13.1
MultiMapping = 2.13.0
Paste = 1.7.5.1
PasteDeploy = 1.3.4
PasteScript = 1.7.5
Persistence = 2.13.2
Products.BTreeFolder2 = 2.13.5
Products.ExternalMethod = 2.13.1
Products.MIMETools = 2.13.0
Products.MailHost = 2.13.4
Products.OFSP = 2.13.2
Products.PythonScripts = 2.13.2
Products.Sessions = 3.0
Products.StandardCacheManagers = 2.13.1
Products.TemporaryFolder = 3.0
Products.ZCTextIndex = 2.13.5
Products.ZCatalog = 2.13.30
Record = 2.13.0
RestrictedPython = 3.6.0
Sphinx = 1.0.8
ZConfig = 2.9.3
ZODB3 = 3.10.7
ZServer = 3.0
ZopeUndo = 2.12.0
appdirs = 1.4.3
configparser = 4.0.2
contextlib2 = 0.6.0.post1
distlib = 0.3.0
docutils = 0.12
filelock = 3.0.12
importlib-metadata = 1.3.0
importlib-resources = 1.0.2
initgroups = 2.13.0
mechanize = 0.2.5
more-itertools = 5.0.0
mr.developer = 1.34
packaging = 20.1
pathlib2 = 2.3.5
pluggy = 0.13.1
py = 1.8.1
pyparsing = 2.4.6
pytz = 2017.2
repoze.retry = 1.2
repoze.tm2 = 1.0
repoze.who = 2.0
scandir = 1.10.0
six = 1.14.0
tempstorage = 2.12.2
toml = 0.10.0
tox = 3.14.4
transaction = 1.1.1
typing = 3.7.4.1
virtualenv = 20.0.4
z3c.checkversions = 1.1
zExceptions = 2.13.0
zLOG = 2.11.2
zc.buildout = 2.3.1
zc.lockfile = 1.0.2
zc.recipe.egg = 2.0.5
zc.recipe.testrunner = 1.2.1
zdaemon = 2.0.7
zipp = 0.6.0
zope.annotation = 3.5.0
zope.broken = 3.6.0
zope.browser = 1.3
zope.browsermenu = 3.9.1
zope.browserpage = 3.12.2
zope.browserresource = 3.10.3
zope.component = 3.9.5
zope.configuration = 3.7.4
zope.container = 3.11.2
zope.contentprovider = 3.7.2
zope.contenttype = 3.5.5
zope.deferredimport = 3.5.3
zope.dottedname = 3.4.6
zope.event = 3.5.2
zope.exceptions = 3.6.2
zope.filerepresentation = 3.6.1
zope.i18n = 3.7.4
zope.i18nmessageid = 3.5.3
zope.interface = 3.6.8
zope.lifecycleevent = 3.6.2
zope.location = 3.9.1
zope.pagetemplate = 3.5.2
zope.processlifetime = 1.0
zope.proxy = 3.6.1
zope.ptresource = 3.9.0
zope.publisher = 3.12.6
zope.schema = 3.7.1
zope.security = 3.7.4
zope.sendmail = 3.7.5
zope.sequencesort = 3.4.0
zope.site = 3.9.2
zope.size = 3.4.1
zope.structuredtext = 3.5.1
zope.tal = 3.5.2
zope.tales = 3.5.3
zope.testbrowser = 3.11.1
zope.testing = 3.9.7
zope.traversing = 3.13.2
zope.viewlet = 3.7.2
Zope = 4.8.7
Zope2 = 4.0
# AccessControl 5+ no longer supports Zope 4.
AccessControl = 4.3
Acquisition = 4.13
AuthEncoding = 4.3
BTrees = 4.11.3
Chameleon = 3.10.2
DateTime = 4.9
DocumentTemplate = 4.1
ExtensionClass = 4.9
Missing = 4.2
MultiMapping = 4.1
Paste = 3.5.2
PasteDeploy = 3.0.1
Persistence = 3.6
Products.BTreeFolder2 = 4.4
# ZCatalog 6+ no longer supports Zope 4.
Products.ZCatalog = 5.4
Record = 3.6
# RestrictedPython >= 6 no longer supports Zope 4
RestrictedPython = 5.2
WSGIProxy2 = 0.5.1
WebOb = 1.8.7
WebTest = 3.0.0
ZConfig = 3.6.1
ZEO = 5.3.0
ZODB = 5.8.0
five.globalrequest = 99.1
five.localsitemanager = 3.4
funcsigs = 1.0.2
future = 0.18.2
ipaddress = 1.0.23
mock = 4.0.3
multipart = 0.2.4
pbr = 5.11.0
persistent = 4.9.3
pytz = 2022.7
roman = 3.3
shutilwhich = 1.1.0
six = 1.16.0
transaction = 3.0.1
waitress = 2.1.2
z3c.pt = 3.3.1
zExceptions = 4.3
zc.lockfile = 2.0
zdaemon = 4.4
zodbpickle = 2.6
zope.annotation = 4.8
zope.browser = 2.4
zope.browsermenu = 4.4
zope.browserpage = 4.4.0
zope.browserresource = 4.4
zope.cachedescriptors = 4.4
zope.component = 5.0.1
zope.componentvocabulary = 2.3.0
zope.configuration = 4.4.1
zope.container = 4.10
zope.contentprovider = 4.2.1
zope.contenttype = 4.6
zope.datetime = 4.3.0
zope.deferredimport = 4.4
zope.deprecation = 4.4.0
zope.dottedname = 5.0
zope.event = 4.6
zope.exceptions = 4.6
zope.filerepresentation = 5.0.0
zope.formlib = 5.0.1
zope.globalrequest = 1.6
zope.hookable = 5.4
zope.i18n = 4.9.0
zope.i18nmessageid = 5.1.1
zope.interface = 5.5.2
zope.lifecycleevent = 4.4
zope.location = 4.3
zope.pagetemplate = 4.6.0
zope.processlifetime = 2.4
zope.proxy = 4.6.1
zope.ptresource = 4.3.0
zope.publisher = 6.1.0
zope.ramcache = 2.4
zope.schema = 6.2.1
zope.security = 5.8
zope.sendmail = 5.3
zope.sequencesort = 4.2
zope.site = 4.6.1
zope.size = 4.4
zope.structuredtext = 4.4
zope.tal = 4.5
zope.tales = 5.2
zope.testbrowser = 5.6.1
zope.testing = 4.10
zope.testrunner = 5.6
zope.traversing = 4.4.1
zope.viewlet = 4.3
[versions:python27]
# Chameleon 3.10 doesn't work on Python 2.7
Chameleon = 3.9.1
# DocumentTemplate 4+ requires Python 3.5 or higher
DocumentTemplate = 3.4
# PasteDeploy >3 requires Python 3.7
PasteDeploy = 2.1.1
# WSGIProxy 0.5 and up requires Python 3.7 and up
WSGIProxy2 = 0.4.6
# WebTest 3.0 and up requires Python 3.6 and up
WebTest = 2.0.35
# ZServer is only available for Python 2
ZServer = 4.0.2
# mock 4.0 and up requires Python 3.6 or higher
mock = 3.0.5
# multipart 0.2 and up requires Python 3
multipart = 0.1.1
# waitress 2 requires Python 3.6 or higher
waitress = 1.4.4
# zope.dottedname >= 5 requires Python 3.6 or higher
zope.dottedname = 4.3
[versions:python35]
# DocumentTemplate 4+ cannot be installed on Zope 4 for Python 3.5
DocumentTemplate = 3.4
# PasteDeploy >3 requires Python 3.7
PasteDeploy = 2.1.1
# WSGIProxy 0.5 and up requires Python 3.7 and up
WSGIProxy2 = 0.4.6
# WebTest 3.0 and up requires Python 3.6 and up
WebTest = 2.0.35
# mock 4.0 and up requires Python 3.6 or higher
mock = 3.0.5
# waitress 2 requires Python 3.6 or higher
waitress = 1.4.4
# zope.dottedname >= 5 requires Python 3.6 or higher
zope.dottedname = 4.3
[versions:python36]
# PasteDeploy >3 requires Python 3.7
PasteDeploy = 2.1.1
# WSGIProxy 0.5 and up requires Python 3.7 and up
WSGIProxy2 = 0.4.6
# waitress 2.1 requires Python 3.7 or higher
waitress = 2.0.0
......@@ -5,7 +5,7 @@
# too late for some components.
%define INSTANCE {{ parameter_dict['instance'] }}
instancehome $INSTANCE
zserver-threads {{ parameter_dict['thread-amount'] }}
# When ownership checking is enabled, the roles a script runs as are the
# intersection between user's roles and script owner's roles. This means
# that revoking a code author's access to the system prevent all scripts
......@@ -15,15 +15,9 @@ zserver-threads {{ parameter_dict['thread-amount'] }}
# revoked when their account is terminated.
skip-ownership-checking true
lock-filename {{ parameter_dict['lock-file'] }}
pid-filename {{ parameter_dict['pid-file'] }}
default-zpublisher-encoding utf-8
rest-input-encoding utf-8
rest-output-encoding utf-8
# XXX: isn't this entry implicit ?
products {{ parameter_dict['instance-products'] }}
# Magic parameter to use the first entry of X-Forwarded-For as the source IP address.
# (see monkey patches in ERP5Type/patches/HTTPRequest.py and ERP5Type/patches/http_server.py)
......@@ -32,41 +26,25 @@ products {{ parameter_dict['instance-products'] }}
# * Backend proxy drops incoming X-Forwarded-For without valid SSL Client Authentification.
trusted-proxy 0.0.0.0
{% if not parameter_dict['wsgi'] -%}
{% if parameter_dict['webdav'] -%}
<webdav-source-server>
address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
force-connection-close off
</webdav-source-server>
{% else %}
<http-server>
address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
</http-server>
{% endif %}
{%- endif %}
<zoperunner>
program $INSTANCE/bin/runzope
</zoperunner>
<product-config DeadlockDebugger>
dump_url {{ parameter_dict['deadlock-path'] }}
secret {{ parameter_dict['deadlock-debugger-password'] }}
</product-config>
{% if 'longrequest-logger-interval' in parameter_dict -%}
<product-config LongRequestLogger>
logfile {{ parameter_dict['longrequest-logger-file'] }}
timeout {{ parameter_dict['longrequest-logger-timeout'] }}
interval {{ parameter_dict['longrequest-logger-interval'] }}
</product-config>
%import haufe.requestmonitoring
<requestmonitor requestmonitor>
period {{ parameter_dict['longrequest-logger-timeout'] }}s
verbosity 0
<monitorhandler dumper>
factory Products.ERP5Type.patches.LongRequestLogger_dumper.factory
repeat -1
time {{ parameter_dict['longrequest-logger-interval'] }}s
</monitorhandler>
</requestmonitor>
{% endif -%}
{% if 'large-file-threshold' in parameter_dict -%}
large-file-threshold {{ parameter_dict['large-file-threshold'] }}
{% endif -%}
{% if 'tidstorage-ip' in parameter_dict -%}
<product-config TIDStorage>
backend-ip {{ parameter_dict['tidstorage-ip'] }}
......@@ -78,16 +56,7 @@ large-file-threshold {{ parameter_dict['large-file-threshold'] }}
node-id {{ node_id }}
</product-config>
{% if not parameter_dict['wsgi'] -%}
{% set timerserver_interval = parameter_dict['timerserver-interval'] -%}
{% if timerserver_interval -%}
%import Products.TimerService.timerserver
<timer-server>
interval {{ timerserver_interval }}
</timer-server>
{% endif %}
{% endif -%}
{% set sql_connection_string = parameter_dict.get('sql-connection-string') -%}
{% if sql_connection_string -%}
{% set bt5_repository_url = [] -%}
......@@ -112,22 +81,6 @@ large-file-threshold {{ parameter_dict['large-file-threshold'] }}
</product-config>
{% endif -%}
<eventlog>
level info
<logfile>
dateformat
path {{ parameter_dict['event-log'] }}
</logfile>
</eventlog>
<logger access>
level WARN
<logfile>
dateformat
format %(message)s
path {{ parameter_dict['z2-log'] }}
</logfile>
</logger>
<zodb_db temporary>
<temporarystorage>
......@@ -152,9 +105,12 @@ large-file-threshold {{ parameter_dict['large-file-threshold'] }}
{% for m in parameter_dict['import-list'] -%}
%import {{ m }}
{% endfor -%}
{% set type_dict = {'neo': 'NEOStorage', 'zeo': 'zeoclient'} %}
{% set type_dict = {'neo': 'NEOStorage', 'zeo': 'clientstorage'} %}
{% for name, zodb_dict in six.iteritems(parameter_dict['zodb-dict']) %}
<zodb_db {{ name }}>
{%- if zodb_dict['type'] == 'zeo' %}
%import ZEO
{%- endif %}
{%- set storage_type = type_dict[zodb_dict.pop('type')] %}
{%- set storage_dict = zodb_dict.pop('storage-dict') %}
{%- do root_common.apply_overrides(zodb_dict, node_id) %}
......
[versions]
# ZTK
zope.annotation = 3.5.0
zope.applicationcontrol = 3.5.5
zope.authentication = 3.7.1
zope.broken = 3.6.0
zope.browser = 1.3
zope.browsermenu = 3.9.1
zope.browserpage = 3.12.2
zope.browserresource = 3.10.3
zope.cachedescriptors = 3.5.1
zope.catalog = 3.8.2
zope.component = 3.9.5
zope.componentvocabulary = 1.0.1
zope.configuration = 3.7.4
zope.container = 3.11.2
zope.contentprovider = 3.7.2
zope.contenttype = 3.5.5
zope.copy = 3.5.0
zope.copypastemove = 3.7.0
zope.datetime = 3.4.1
zope.deferredimport = 3.5.3
zope.deprecation = 3.4.1
zope.dottedname = 3.4.6
zope.dublincore = 3.7.1
zope.error = 3.7.4
zope.event = 3.5.2
zope.exceptions = 3.6.2
zope.filerepresentation = 3.6.1
zope.formlib = 4.0.6
zope.hookable = 3.4.1
zope.i18n = 3.7.4
zope.i18nmessageid = 3.5.3
zope.index = 3.6.4
zope.interface = 3.6.7
zope.intid = 3.7.2
zope.keyreference = 3.6.4
zope.lifecycleevent = 3.6.2
zope.location = 3.9.1
zope.login = 1.0.0
zope.mimetype = 1.3.1
zope.minmax = 1.1.2
zope.pagetemplate = 3.5.2
zope.password = 3.6.1
zope.pluggableauth = 1.0.3
zope.principalannotation = 3.6.1
zope.principalregistry = 3.7.1
zope.processlifetime = 1.0
zope.proxy = 3.6.1
zope.ptresource = 3.9.0
zope.publisher = 3.12.6
zope.ramcache = 1.0
zope.schema = 3.7.1
zope.security = 3.7.4
zope.securitypolicy = 3.7.0
zope.sendmail = 3.7.5
zope.sequencesort = 3.4.0
zope.server = 3.6.3
zope.session = 3.9.5
zope.site = 3.9.2
zope.size = 3.4.1
zope.structuredtext = 3.5.1
zope.tal = 3.5.2
zope.tales = 3.5.3
zope.testing = 3.9.7
zope.traversing = 3.13.2
zope.viewlet = 3.7.2
# Deprecating
zope.documenttemplate = 3.4.3
# Dependencies
# Needed for the mechanize 0.1.x.
ClientForm = 0.2.10
distribute = 0.6.49
docutils = 0.7
Jinja2 = 2.5.5
# Newer versions of mechanize are not fully py24 compatible.
mechanize = 0.1.11
Paste = 1.7.5.1
PasteDeploy = 1.3.4
PasteScript = 1.7.5
py = 1.3.4
Pygments = 1.3.1
python-gettext = 1.0
pytz = 2013b
RestrictedPython = 3.6.0
setuptools = 12.2
Sphinx = 1.0.8
transaction = 1.1.1
unittest2 = 0.5.1
z3c.recipe.sphinxdoc = 0.0.8
zc.buildout = 2.3.1
zc.lockfile = 1.0.2
ZConfig = 2.8.0
zc.recipe.egg = 1.3.2
zc.recipe.testrunner = 1.2.1
zc.resourcelibrary = 1.3.4
zdaemon = 2.0.7
ZODB3 = 3.9.7
zope.mkzeoinstance = 3.9.6
# toolchain
argparse = 1.1
coverage = 3.5.3
lxml = 2.2.8
mr.developer = 1.25
tl.eggdeps = 0.4
nose = 1.1.2
z3c.checkversions = 0.4.2
z3c.recipe.compattest = 0.12.2
z3c.recipe.depgraph = 0.5
zope.kgs = 1.2.0
......@@ -18,8 +18,8 @@ md5sum = 7c41026716d856bba7c1252b72adbf77
[logrotate-entry-template]
filename = logrotate_entry.in
md5sum = ce6ccdd52148770149e6e7525ab71e80
md5sum = 02c1009f8e0dc371cfc1290afef72ec7
[template-logrotate-base]
filename = instance-logrotate-base.cfg.in
md5sum = ed807da528595b7111c19e09056b01ce
md5sum = 4e2baa1edd1d27831dda984769102a7c
......@@ -53,12 +53,14 @@ output = ${logrotate-conf-parameter:logrotate-entries}/${:name}
context =
key backup :backup
key log :log
key copytruncate :copytruncate
key post :post
key pre :pre
key frequency :frequency
key rotate_num :rotate-num
key nocompress :nocompress
key delaycompress :delaycompress
copytruncate = false
post =
pre =
frequency = daily
......
......@@ -10,6 +10,7 @@
create
olddir {{ backup }}
missingok
{% if copytruncate %}copytruncate{% endif %}
{% if pre %}prerotate
{{ pre }}
endscript{% endif %}
......
......@@ -338,7 +338,7 @@ ZConfig = 3.6.1
zdaemon = 4.2.0
zipp = 3.12.0:whl
zodburi = 2.5.0
zope.event = 3.5.2
zope.event = 4.6.0
zope.interface = 5.4.0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment