| 122 | |
| 123 | @dataclass |
| 124 | class ScanLocation(KeepRefs): |
| 125 | location: Union[Path, str] |
| 126 | metadata: dict = field(default_factory=dict) |
| 127 | cleanup: Union[bool, Path, str] = False |
| 128 | parent: Optional[ScanLocation] = None |
| 129 | strip_path: str = "" |
| 130 | size: Optional[int] = None |
| 131 | |
| 132 | def __post_init__(self): |
| 133 | assert type(self.parent) != str # Type guard format change, should be ScanLocation or None now |
| 134 | |
| 135 | if type(self.location) == str: |
| 136 | self.__str_location = self.location |
| 137 | self.location = Path(self.location) |
| 138 | else: |
| 139 | self.__str_location = os.fspath(self.location) |
| 140 | |
| 141 | if self.cleanup: |
| 142 | CLEANUP_LOCATIONS.add(self.location) |
| 143 | |
| 144 | self.__str_parent = None |
| 145 | self._lzset: Optional[set] = None |
| 146 | self.metadata["path"] = self.location |
| 147 | self.metadata["normalized_path"] = str(self) |
| 148 | self.metadata["tags"] = set() |
| 149 | |
| 150 | if self.metadata.get("depth") is None: |
| 151 | self.metadata["depth"] = 0 |
| 152 | warn("Depth is not set for the scan location", stacklevel=2) |
| 153 | |
| 154 | if self.location.is_file(): |
| 155 | self.size = self.location.stat().st_size |
| 156 | self.__compute_hashes() |
| 157 | self.metadata["mime"] = magic.from_file(self.str_location, mime=True) |
| 158 | |
| 159 | if self.metadata["mime"] in ("text/plain", "application/octet-stream", "text/none"): |
| 160 | self.metadata["mime"] = mimetypes.guess_type(self.__str_location)[0] |
| 161 | elif self.metadata["mime"] != "text/x-python" and self.is_python_source_code: # FIXME: not very elegant mime normalization |
| 162 | self.metadata["mime"] = "text/x-python" |
| 163 | |
| 164 | if self.is_python_source_code and "no_imports" not in self.metadata: |
| 165 | try: |
| 166 | imports = find_imports.find_imports(self.location, metadata=self.metadata) |
| 167 | if imports: |
| 168 | self.metadata["py_imports"] = imports |
| 169 | except PythonExecutorError: |
| 170 | pass |
| 171 | |
| 172 | def __compute_hashes(self): |
| 173 | if self.size == 0: # Can't mmap empty file |
| 174 | self.metadata["md5"] = "d41d8cd98f00b204e9800998ecf8427e" |
| 175 | self.metadata["sha1"] = "da39a3ee5e6b4b0d3255bfef95601890afd80709" |
| 176 | self.metadata["sha256"] = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" |
| 177 | self.metadata["sha512"] = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" |
| 178 | return |
| 179 | |
| 180 | |
| 181 | tl = tlsh.Tlsh() |
no outgoing calls