flow.record 3.19.dev7__tar.gz → 3.19.dev8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/PKG-INFO +1 -1
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/fieldtypes/net/__init__.py +8 -1
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/fieldtypes/net/ip.py +58 -6
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/jsonpacker.py +1 -1
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/version.py +2 -2
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/whitelist.py +1 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow.record.egg-info/PKG-INFO +1 -1
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_fieldtype_ip.py +79 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/.git-blame-ignore-revs +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/COPYRIGHT +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/LICENSE +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/MANIFEST.in +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/README.md +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/examples/filesystem.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/examples/passivedns.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/examples/records.json +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/examples/tcpconn.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/__init__.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/__init__.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/archive.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/avro.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/broker.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/csvfile.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/duckdb.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/elastic.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/jsonfile.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/line.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/mongo.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/split.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/splunk.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/sqlite.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/stream.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/text.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/adapter/xlsx.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/base.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/exceptions.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/fieldtypes/__init__.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/fieldtypes/credential.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/fieldtypes/net/ipv4.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/fieldtypes/net/tcp.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/fieldtypes/net/udp.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/packer.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/selector.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/stream.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/tools/__init__.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/tools/geoip.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/tools/rdump.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow/record/utils.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow.record.egg-info/SOURCES.txt +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow.record.egg-info/dependency_links.txt +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow.record.egg-info/entry_points.txt +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow.record.egg-info/requires.txt +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/flow.record.egg-info/top_level.txt +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/pyproject.toml +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/setup.cfg +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/__init__.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/_utils.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/docs/Makefile +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/docs/conf.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/docs/index.rst +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/selector_explain_example.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/standalone_test.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_adapter_line.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_adapter_text.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_avro.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_avro_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_compiled_selector.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_csv_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_deprecations.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_elastic_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_fieldtypes.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_json_packer.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_json_record_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_multi_timestamp.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_packer.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_rdump.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_record.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_record_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_record_descriptor.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_regression.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_selector.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_splunk_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_sqlite_duckdb_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tests/test_xlsx_adapter.py +0 -0
- {flow_record-3.19.dev7 → flow_record-3.19.dev8}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: flow.record
|
|
3
|
-
Version: 3.19.
|
|
3
|
+
Version: 3.19.dev8
|
|
4
4
|
Summary: A library for defining and creating structured data (called records) that can be streamed to disk or piped to other tools that use flow.record
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from flow.record.fieldtypes import string
|
|
4
|
-
from flow.record.fieldtypes.net.ip import
|
|
4
|
+
from flow.record.fieldtypes.net.ip import (
|
|
5
|
+
IPAddress,
|
|
6
|
+
IPNetwork,
|
|
7
|
+
ipaddress,
|
|
8
|
+
ipinterface,
|
|
9
|
+
ipnetwork,
|
|
10
|
+
)
|
|
5
11
|
|
|
6
12
|
__all__ = [
|
|
7
13
|
"IPAddress",
|
|
8
14
|
"IPNetwork",
|
|
9
15
|
"ipaddress",
|
|
16
|
+
"ipinterface",
|
|
10
17
|
"ipnetwork",
|
|
11
18
|
]
|
|
12
19
|
|
|
@@ -2,10 +2,13 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from ipaddress import (
|
|
4
4
|
IPv4Address,
|
|
5
|
+
IPv4Interface,
|
|
5
6
|
IPv4Network,
|
|
6
7
|
IPv6Address,
|
|
8
|
+
IPv6Interface,
|
|
7
9
|
IPv6Network,
|
|
8
10
|
ip_address,
|
|
11
|
+
ip_interface,
|
|
9
12
|
ip_network,
|
|
10
13
|
)
|
|
11
14
|
from typing import Union
|
|
@@ -15,16 +18,19 @@ from flow.record.fieldtypes import defang
|
|
|
15
18
|
|
|
16
19
|
_IPNetwork = Union[IPv4Network, IPv6Network]
|
|
17
20
|
_IPAddress = Union[IPv4Address, IPv6Address]
|
|
21
|
+
_IPInterface = Union[IPv4Interface, IPv6Interface]
|
|
22
|
+
_ConversionTypes = Union[str, int, bytes]
|
|
23
|
+
_IPTypes = Union[_IPNetwork, _IPAddress, _IPInterface]
|
|
18
24
|
|
|
19
25
|
|
|
20
26
|
class ipaddress(FieldType):
|
|
21
|
-
val = None
|
|
27
|
+
val: _IPAddress = None
|
|
22
28
|
_type = "net.ipaddress"
|
|
23
29
|
|
|
24
|
-
def __init__(self, addr:
|
|
30
|
+
def __init__(self, addr: _ConversionTypes | _IPAddress):
|
|
25
31
|
self.val = ip_address(addr)
|
|
26
32
|
|
|
27
|
-
def __eq__(self, b:
|
|
33
|
+
def __eq__(self, b: _ConversionTypes | _IPAddress) -> bool:
|
|
28
34
|
try:
|
|
29
35
|
return self.val == ip_address(b)
|
|
30
36
|
except ValueError:
|
|
@@ -53,13 +59,13 @@ class ipaddress(FieldType):
|
|
|
53
59
|
|
|
54
60
|
|
|
55
61
|
class ipnetwork(FieldType):
|
|
56
|
-
val = None
|
|
62
|
+
val: _IPNetwork = None
|
|
57
63
|
_type = "net.ipnetwork"
|
|
58
64
|
|
|
59
|
-
def __init__(self, addr:
|
|
65
|
+
def __init__(self, addr: _ConversionTypes | _IPNetwork):
|
|
60
66
|
self.val = ip_network(addr)
|
|
61
67
|
|
|
62
|
-
def __eq__(self, b:
|
|
68
|
+
def __eq__(self, b: _ConversionTypes | _IPNetwork) -> bool:
|
|
63
69
|
try:
|
|
64
70
|
return self.val == ip_network(b)
|
|
65
71
|
except ValueError:
|
|
@@ -98,6 +104,52 @@ class ipnetwork(FieldType):
|
|
|
98
104
|
def _unpack(data: str) -> ipnetwork:
|
|
99
105
|
return ipnetwork(data)
|
|
100
106
|
|
|
107
|
+
@property
|
|
108
|
+
def netmask(self) -> ipaddress:
|
|
109
|
+
return ipaddress(self.val.netmask)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class ipinterface(FieldType):
|
|
113
|
+
val: _IPInterface = None
|
|
114
|
+
_type = "net.ipinterface"
|
|
115
|
+
|
|
116
|
+
def __init__(self, addr: _ConversionTypes | _IPTypes) -> None:
|
|
117
|
+
self.val = ip_interface(addr)
|
|
118
|
+
|
|
119
|
+
def __eq__(self, b: _ConversionTypes | _IPTypes) -> bool:
|
|
120
|
+
try:
|
|
121
|
+
return self.val == ip_interface(b)
|
|
122
|
+
except ValueError:
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
def __hash__(self) -> int:
|
|
126
|
+
return hash(self.val)
|
|
127
|
+
|
|
128
|
+
def __str__(self) -> str:
|
|
129
|
+
return str(self.val)
|
|
130
|
+
|
|
131
|
+
def __repr__(self) -> str:
|
|
132
|
+
return f"{self._type}({str(self)!r})"
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def ip(self) -> ipaddress:
|
|
136
|
+
return ipaddress(self.val.ip)
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def network(self) -> ipnetwork:
|
|
140
|
+
return ipnetwork(self.val.network)
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def netmask(self) -> ipaddress:
|
|
144
|
+
return ipaddress(self.val.netmask)
|
|
145
|
+
|
|
146
|
+
def _pack(self) -> str:
|
|
147
|
+
return self.val.compressed
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def _unpack(data: str) -> ipinterface:
|
|
151
|
+
return ipinterface(data)
|
|
152
|
+
|
|
101
153
|
|
|
102
154
|
# alias: net.IPAddress -> net.ipaddress
|
|
103
155
|
# alias: net.IPNetwork -> net.ipnetwork
|
|
@@ -68,7 +68,7 @@ class JsonRecordPacker:
|
|
|
68
68
|
"sha1": obj.sha1,
|
|
69
69
|
"sha256": obj.sha256,
|
|
70
70
|
}
|
|
71
|
-
if isinstance(obj, (fieldtypes.net.ipaddress, fieldtypes.net.ipnetwork)):
|
|
71
|
+
if isinstance(obj, (fieldtypes.net.ipaddress, fieldtypes.net.ipnetwork, fieldtypes.net.ipinterface)):
|
|
72
72
|
return str(obj)
|
|
73
73
|
if isinstance(obj, bytes):
|
|
74
74
|
return base64.b64encode(obj).decode()
|
|
@@ -12,5 +12,5 @@ __version__: str
|
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
|
13
13
|
version_tuple: VERSION_TUPLE
|
|
14
14
|
|
|
15
|
-
__version__ = version = '3.19.
|
|
16
|
-
__version_tuple__ = version_tuple = (3, 19, '
|
|
15
|
+
__version__ = version = '3.19.dev8'
|
|
16
|
+
__version_tuple__ = version_tuple = (3, 19, 'dev8')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: flow.record
|
|
3
|
-
Version: 3.19.
|
|
3
|
+
Version: 3.19.dev8
|
|
4
4
|
Summary: A library for defining and creating structured data (called records) that can be streamed to disk or piped to other tools that use flow.record
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
|
@@ -128,6 +128,85 @@ def test_record_ipnetwork() -> None:
|
|
|
128
128
|
assert "::1" not in data
|
|
129
129
|
|
|
130
130
|
|
|
131
|
+
def test_record_ipinterface() -> None:
|
|
132
|
+
TestRecord = RecordDescriptor(
|
|
133
|
+
"test/ipinterface",
|
|
134
|
+
[
|
|
135
|
+
("net.ipinterface", "interface"),
|
|
136
|
+
],
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# ipv4
|
|
140
|
+
r = TestRecord("192.168.0.0/24")
|
|
141
|
+
assert r.interface == "192.168.0.0/24"
|
|
142
|
+
assert "bad.ip" not in r.interface.network
|
|
143
|
+
assert "192.168.0.1" in r.interface.network
|
|
144
|
+
assert isinstance(r.interface, net.ipinterface)
|
|
145
|
+
assert repr(r.interface) == "net.ipinterface('192.168.0.0/24')"
|
|
146
|
+
assert hash(r.interface) == hash(net.ipinterface("192.168.0.0/24"))
|
|
147
|
+
|
|
148
|
+
r = TestRecord("192.168.1.1")
|
|
149
|
+
assert r.interface.ip == "192.168.1.1"
|
|
150
|
+
assert r.interface.network == "192.168.1.1/32"
|
|
151
|
+
assert r.interface == "192.168.1.1/32"
|
|
152
|
+
assert r.interface.netmask == "255.255.255.255"
|
|
153
|
+
|
|
154
|
+
r = TestRecord("192.168.1.24/255.255.255.0")
|
|
155
|
+
assert r.interface == "192.168.1.24/24"
|
|
156
|
+
assert r.interface.ip == "192.168.1.24"
|
|
157
|
+
assert r.interface.network == "192.168.1.0/24"
|
|
158
|
+
assert r.interface.netmask == "255.255.255.0"
|
|
159
|
+
|
|
160
|
+
# ipv6 - https://en.wikipedia.org/wiki/IPv6_address
|
|
161
|
+
r = TestRecord("::1")
|
|
162
|
+
assert r.interface == "::1"
|
|
163
|
+
assert r.interface == "::1/128"
|
|
164
|
+
|
|
165
|
+
r = TestRecord("64:ff9b::2/96")
|
|
166
|
+
assert r.interface == "64:ff9b::2/96"
|
|
167
|
+
assert r.interface.ip == "64:ff9b::2"
|
|
168
|
+
assert r.interface.network == "64:ff9b::/96"
|
|
169
|
+
assert r.interface.netmask == "ffff:ffff:ffff:ffff:ffff:ffff::"
|
|
170
|
+
|
|
171
|
+
# instantiate from different types
|
|
172
|
+
assert TestRecord(1).interface == "0.0.0.1/32"
|
|
173
|
+
assert TestRecord(0x7F0000FF).interface == "127.0.0.255/32"
|
|
174
|
+
assert TestRecord(b"\x7f\xff\xff\xff").interface == "127.255.255.255/32"
|
|
175
|
+
|
|
176
|
+
# Test whether it functions in a set
|
|
177
|
+
data = {TestRecord(x).interface for x in ["192.168.0.0/24", "192.168.0.0/24", "::1", "::1"]}
|
|
178
|
+
assert len(data) == 2
|
|
179
|
+
assert net.ipinterface("::1") in data
|
|
180
|
+
assert net.ipinterface("192.168.0.0/24") in data
|
|
181
|
+
assert "::1" not in data
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def test_record_ipinterface_types() -> None:
|
|
185
|
+
TestRecord = RecordDescriptor(
|
|
186
|
+
"test/ipinterface",
|
|
187
|
+
[
|
|
188
|
+
(
|
|
189
|
+
"net.ipinterface",
|
|
190
|
+
"interface",
|
|
191
|
+
)
|
|
192
|
+
],
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
r = TestRecord("192.168.0.255/24")
|
|
196
|
+
_if = r.interface
|
|
197
|
+
assert isinstance(_if, net.ipinterface)
|
|
198
|
+
assert isinstance(_if.ip, net.ipaddress)
|
|
199
|
+
assert isinstance(_if.network, net.ipnetwork)
|
|
200
|
+
assert isinstance(_if.netmask, net.ipaddress)
|
|
201
|
+
|
|
202
|
+
r = TestRecord("64:ff9b::/96")
|
|
203
|
+
_if = r.interface
|
|
204
|
+
assert isinstance(_if, net.ipinterface)
|
|
205
|
+
assert isinstance(_if.ip, net.ipaddress)
|
|
206
|
+
assert isinstance(_if.network, net.ipnetwork)
|
|
207
|
+
assert isinstance(_if.netmask, net.ipaddress)
|
|
208
|
+
|
|
209
|
+
|
|
131
210
|
@pytest.mark.parametrize("PSelector", [Selector, CompiledSelector])
|
|
132
211
|
def test_selector_ipaddress(PSelector: type[Selector]) -> None:
|
|
133
212
|
TestRecord = RecordDescriptor(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|