| OLD | NEW |
| 1 # This file is part of Adblock Plus <https://adblockplus.org/>, | 1 # This file is part of Adblock Plus <https://adblockplus.org/>, |
| 2 # Copyright (C) 2006-present eyeo GmbH | 2 # Copyright (C) 2006-present eyeo GmbH |
| 3 # | 3 # |
| 4 # Adblock Plus is free software: you can redistribute it and/or modify | 4 # Adblock Plus is free software: you can redistribute it and/or modify |
| 5 # it under the terms of the GNU General Public License version 3 as | 5 # it under the terms of the GNU General Public License version 3 as |
| 6 # published by the Free Software Foundation. | 6 # published by the Free Software Foundation. |
| 7 # | 7 # |
| 8 # Adblock Plus is distributed in the hope that it will be useful, | 8 # Adblock Plus is distributed in the hope that it will be useful, |
| 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 # GNU General Public License for more details. | 11 # GNU General Public License for more details. |
| 12 # | 12 # |
| 13 # You should have received a copy of the GNU General Public License | 13 # You should have received a copy of the GNU General Public License |
| 14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| 15 | 15 |
| 16 """Combine filter list fragments to produce filter lists.""" | 16 """Combine filter list fragments to produce filter lists.""" |
| 17 | 17 |
| 18 from __future__ import unicode_literals | 18 from __future__ import unicode_literals |
| 19 | 19 |
| 20 import base64 | |
| 21 import hashlib | |
| 22 import itertools | 20 import itertools |
| 23 import logging | 21 import logging |
| 24 import time | 22 import time |
| 25 | 23 |
| 26 from .parser import parse_filterlist, Comment, Metadata | 24 from .parser import parse_filterlist, Comment, Metadata |
| 27 from .sources import NotFound | 25 from .sources import NotFound |
| 28 | 26 |
| 29 __all__ = ['IncludeError', 'MissingHeader', 'render_filterlist'] | 27 __all__ = ['IncludeError', 'MissingHeader', 'render_filterlist'] |
| 30 | 28 |
| 31 _logger = logging.getLogger(__name__) | 29 _logger = logging.getLogger(__name__) |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 if line.key not in seen: | 130 if line.key not in seen: |
| 133 seen.add(line.key) | 131 seen.add(line.key) |
| 134 yield line | 132 yield line |
| 135 elif line.type == 'header': | 133 elif line.type == 'header': |
| 136 if i == 0: | 134 if i == 0: |
| 137 yield line | 135 yield line |
| 138 else: | 136 else: |
| 139 yield line | 137 yield line |
| 140 | 138 |
| 141 | 139 |
| 142 def _insert_checksum(lines): | |
| 143 """Add checksum to the filter list. | |
| 144 | |
| 145 See https://adblockplus.org/filters#special-comments for description | |
| 146 of the checksum algorithm. | |
| 147 """ | |
| 148 md5sum = hashlib.md5() | |
| 149 | |
| 150 for line in lines: | |
| 151 if line.type != 'emptyline': | |
| 152 md5sum.update(line.to_string().encode('utf-8') + b'\n') | |
| 153 yield line | |
| 154 | |
| 155 checksum = base64.b64encode(md5sum.digest()).rstrip(b'=') | |
| 156 yield Metadata('Checksum', checksum.decode('utf-8')) | |
| 157 | |
| 158 | |
| 159 def _validate(lines): | 140 def _validate(lines): |
| 160 """Validate the final list.""" | 141 """Validate the final list.""" |
| 161 first_line, rest = _first_and_rest(lines) | 142 first_line, rest = _first_and_rest(lines) |
| 162 if first_line.type != 'header': | 143 if first_line.type != 'header': |
| 163 raise MissingHeader('No header found at the beginning of the input.') | 144 raise MissingHeader('No header found at the beginning of the input.') |
| 164 return itertools.chain([first_line], rest) | 145 return itertools.chain([first_line], rest) |
| 165 | 146 |
| 166 | 147 |
| 167 def render_filterlist(name, sources, top_source=None): | 148 def render_filterlist(name, sources, top_source=None): |
| 168 """Produce filter list from fragments. | 149 """Produce filter list from fragments. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 189 When any of the fragments contain lines that can't be parsed. | 170 When any of the fragments contain lines that can't be parsed. |
| 190 MissingHeader | 171 MissingHeader |
| 191 If the top level fragment doesn't start with a valid header. This would | 172 If the top level fragment doesn't start with a valid header. This would |
| 192 lead to rendering an invalid filter list, so we immediately abort. | 173 lead to rendering an invalid filter list, so we immediately abort. |
| 193 | 174 |
| 194 """ | 175 """ |
| 195 _logger.info('Rendering: %s', name) | 176 _logger.info('Rendering: %s', name) |
| 196 lines, default_source = _get_and_parse_fragment(name, sources, top_source) | 177 lines, default_source = _get_and_parse_fragment(name, sources, top_source) |
| 197 lines = _process_includes(sources, default_source, [name], lines) | 178 lines = _process_includes(sources, default_source, [name], lines) |
| 198 for proc in [_process_timestamps, _insert_version, _remove_duplicates, | 179 for proc in [_process_timestamps, _insert_version, _remove_duplicates, |
| 199 _insert_checksum, _validate]: | 180 _validate]: |
| 200 lines = proc(lines) | 181 lines = proc(lines) |
| 201 return lines | 182 return lines |
| OLD | NEW |