Replaces LICENSE (GPLv3 -> AGPLv3) and prepends `SPDX-License-Identifier: AGPL-3.0-or-later` to every source file across decnet/, decnet_web/, tests/, scripts/, and tools/. Rationale: closes the GPLv3 ASP loophole so any party operating a modified DECNET as a network service must offer their modified source. Personal copyright (Samuel Paschuan) + inbound=outbound contributions make a future unilateral relicense infeasible. - LICENSE: full AGPL-3.0 text (gnu.org/licenses/agpl-3.0.txt) - COPYRIGHT: project copyright notice - tools/add_spdx_headers.py: idempotent header injector (shebang- and PEP 263-aware) Touches 1565 source files (.py, .ts, .tsx, .js, .jsx, .css, .sh). No behavior change; comments only.
47 lines
1.6 KiB
Python
47 lines
1.6 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||
"""HTML instrumenter — append a 1×1 tracking pixel.
|
||
|
||
Stdlib-only. We don't parse the HTML; we just inject the ``<img>``
|
||
tag immediately before the closing ``</body>`` (or, failing that, at
|
||
the end of the document). Most renderers that support remote images
|
||
(email previewers, IDE doc previews, browsers) will fetch it as
|
||
soon as the document is opened.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import re
|
||
|
||
from decnet.canary.base import CanaryArtifact, CanaryContext, CanaryInstrumenter
|
||
|
||
|
||
_BODY_CLOSE = re.compile(rb"</body\s*>", re.IGNORECASE)
|
||
|
||
|
||
class HtmlInstrumenter(CanaryInstrumenter):
|
||
name = "html"
|
||
mime_prefixes = ("text/html", "application/xhtml+xml")
|
||
|
||
def instrument(
|
||
self, blob: bytes, ctx: CanaryContext, *, target_path: str,
|
||
) -> CanaryArtifact:
|
||
url = f"{ctx.http_base.rstrip('/')}/c/{ctx.callback_token}".encode()
|
||
pixel = (
|
||
b"<img src=\"" + url + b"\" width=\"1\" height=\"1\" "
|
||
b"alt=\"\" style=\"display:none\">\n"
|
||
)
|
||
match = _BODY_CLOSE.search(blob)
|
||
if match:
|
||
out = blob[:match.start()] + pixel + blob[match.start():]
|
||
note = "injected 1x1 pixel before </body>"
|
||
else:
|
||
out = (blob if blob.endswith(b"\n") else blob + b"\n") + pixel
|
||
note = "appended 1x1 pixel (no </body> found)"
|
||
return CanaryArtifact(
|
||
path=target_path,
|
||
content=out,
|
||
mode=0o644,
|
||
mtime_offset=-86400 * 7,
|
||
instrumenter=self.name,
|
||
notes=[note, f"pixel src={url.decode()}"],
|
||
)
|