def _extract_bundle(self, bundle):
        if not hasattr(self, "_stream"):
            return False

        bundle_checksum = bundle["checksum"]
        cache_file = CACHE_DIR / self._stream["StreamName"] / bundle_checksum

        # open cache file with gzip
        with cache_file.open("rb") as cache_fp:
            game_base = GAME_ROOT / self._stream["StreamName"]
            # get entries sorted by offset
            entries = sorted(bundle["entries"], key=itemgetter("offset"))
            for entry in entries:
                entry_file = game_base / entry["filename"][1:]

                # make sure that path exists
                if not entry_file.parent.exists():
                    entry_file.parent.mkdir(parents=True)

                entry_offset = int(entry["offset"])
                cache_fp.seek(entry_offset)

                # remove the file first if it already exists
                if entry_file.exists():
                    entry_file.unlink()

                with entry_file.open("xb") as entry_fp:
                    # data might be compressed further, check sizeZ for that
                    if entry["sizeZ"] != "0":
                        entry_size = int(entry["sizeZ"])
                        raw_data = cache_fp.read(entry_size)
                        entry_fp.write(decompress(raw_data))
                    else:
                        entry_size = int(entry["size"])
                        entry_fp.write(cache_fp.read(entry_size))

                # set executable
                if "executable" in entry:
                    entry_file.chmod(entry_file.stat().st_mode | S_IEXEC)

        return True