import os import pytest from pyhttpd.conf import HttpdConf class TestPropdbNsLimit: @pytest.fixture(autouse=True, scope='class') def _class_scope(self, env): dav_dir = os.path.join(env.gen_dir, 'dav') os.makedirs(dav_dir, exist_ok=True) with open(os.path.join(dav_dir, 'file.txt'), 'w') as fd: fd.write('hello\n') conf = HttpdConf(env, extras={ 'base': f""" DavLockDB "{env.gen_dir}/davlock" """, f"test1.{env.http_tld}": f""" Alias /dav "{dav_dir}" Dav On Require all granted """, }) conf.add_vhost_test1() conf.install() assert env.apache_restart() == 0 @staticmethod def _propertyupdate(nspaces: int, prefix: str) -> str: # every xmlns declaration in a PROPPATCH body is recorded in the # resource's property database, whether or not it is used decls = ''.join(f' xmlns:{prefix}{i}="urn:{prefix}{i}"' for i in range(nspaces)) return ('' f'' f'<{prefix}0:p>v' '') def _proppatch(self, env, body: str): fpath = os.path.join(env.gen_dir, 'proppatch.xml') with open(fpath, 'w') as fd: fd.write(body) url = env.mkurl("https", "test1", "/dav/file.txt") return env.curl_raw(url, options=[ '-X', 'PROPPATCH', '-H', 'Content-Type: text/xml', '--data-binary', f'@{fpath}']) # a modest number of distinct namespaces is accepted and stored def test_dav_001_01(self, env): r = self._proppatch(env, self._propertyupdate(100, 'a')) assert r.response["status"] == 207 assert 'HTTP/1.1 200' in r.stdout assert 'HTTP/1.1 413' not in r.stdout # declaring more distinct namespaces than one property database will # record must be refused with 413 rather than accepted, and the resource # must remain usable afterwards def test_dav_001_02(self, env): r = self._proppatch(env, self._propertyupdate(2049, 'b')) # the refusal is logged at error level, and writing back the # oversized namespace table on close fails with a warning env.httpd_error_log.ignore_recent( lognos=['AH00577'], matches=[r'.*Too many distinct namespaces']) assert r.response["status"] == 207 assert 'HTTP/1.1 413' in r.stdout url = env.mkurl("https", "test1", "/dav/file.txt") r = env.curl_raw(url, options=['-X', 'PROPFIND', '-H', 'Depth: 0']) assert r.response["status"] == 207