File: protocol_build.py

package info (click to toggle)
pywayland 0.4.18-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 676 kB
  • sloc: python: 3,625; xml: 189; makefile: 174
file content (73 lines) | stat: -rw-r--r-- 2,266 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import os
import tarfile
import urllib.request

wayland_version = "1.21.0"
protocols_version = "1.25"

wayland_source = "https://cgit.freedesktop.org/wayland/wayland/plain/protocol/wayland.xml?id={}".format(
    wayland_version
)
protocols_source = (
    "https://wayland.freedesktop.org/releases/wayland-protocols-{}.tar.xz".format(
        protocols_version
    )
)


def _is_within_directory(directory, target):
    """Helper to check for CVE-2007-4559"""
    abs_directory = os.path.abspath(directory)
    abs_target = os.path.abspath(target)

    prefix = os.path.commonprefix([abs_directory, abs_target])

    return prefix == abs_directory


def _safe_extractall(tar, path=".", members=None, *, numeric_owner=False):
    """Helper to check for CVE-2007-4559"""
    for member in tar.getmembers():
        member_path = os.path.join(path, member.name)
        if not _is_within_directory(path, member_path):
            raise Exception("Attempted Path Traversal in Tar File")

    tar.extractall(path, members, numeric_owner=numeric_owner)


def protocols_build(output_dir):
    from pywayland.scanner import Protocol

    # first, we download the wayland.xml file
    wayland_file = "wayland.xml"
    urllib.request.urlretrieve(wayland_source, wayland_file)

    # download the protocols file and extract it
    protocol_dest = f"wayland-protocols-{protocols_version}"
    urllib.request.urlretrieve(protocols_source, protocol_dest + ".tar.xz")

    with tarfile.open(protocol_dest + ".tar.xz") as f:
        _safe_extractall(f)

    # walk the directory and generate all the protocols
    protocol_files = [
        wayland_file,
        *sorted(
            [
                os.path.join(dirpath, filename)
                for dirpath, _, filenames in os.walk(protocol_dest)
                for filename in filenames
                if os.path.splitext(filename)[1] == ".xml"
            ],
            reverse=True,
        ),
    ]

    protocols = [Protocol.parse_file(protocol_file) for protocol_file in protocol_files]
    protocol_imports = {
        interface.name: protocol.name
        for protocol in protocols
        for interface in protocol.interface
    }
    for protocol in protocols:
        protocol.output(output_dir, protocol_imports)