pangea-sdk 3.8.0__py3-none-any.whl → 5.3.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- pangea/__init__.py +2 -1
- pangea/asyncio/__init__.py +1 -0
- pangea/asyncio/file_uploader.py +39 -0
- pangea/asyncio/request.py +46 -23
- pangea/asyncio/services/__init__.py +2 -0
- pangea/asyncio/services/audit.py +46 -20
- pangea/asyncio/services/authn.py +123 -61
- pangea/asyncio/services/authz.py +57 -31
- pangea/asyncio/services/base.py +21 -2
- pangea/asyncio/services/embargo.py +2 -2
- pangea/asyncio/services/file_scan.py +24 -9
- pangea/asyncio/services/intel.py +104 -30
- pangea/asyncio/services/redact.py +52 -3
- pangea/asyncio/services/sanitize.py +217 -0
- pangea/asyncio/services/share.py +733 -0
- pangea/asyncio/services/vault.py +1709 -766
- pangea/crypto/rsa.py +135 -0
- pangea/deep_verify.py +7 -1
- pangea/dump_audit.py +9 -8
- pangea/file_uploader.py +35 -0
- pangea/request.py +70 -49
- pangea/response.py +36 -17
- pangea/services/__init__.py +2 -0
- pangea/services/audit/audit.py +57 -29
- pangea/services/audit/models.py +12 -3
- pangea/services/audit/signing.py +6 -5
- pangea/services/audit/util.py +3 -3
- pangea/services/authn/authn.py +120 -66
- pangea/services/authn/models.py +167 -11
- pangea/services/authz.py +53 -30
- pangea/services/base.py +16 -2
- pangea/services/embargo.py +2 -2
- pangea/services/file_scan.py +32 -15
- pangea/services/intel.py +155 -30
- pangea/services/redact.py +132 -3
- pangea/services/sanitize.py +388 -0
- pangea/services/share/file_format.py +170 -0
- pangea/services/share/share.py +1440 -0
- pangea/services/vault/models/asymmetric.py +120 -18
- pangea/services/vault/models/common.py +439 -141
- pangea/services/vault/models/keys.py +94 -0
- pangea/services/vault/models/secret.py +27 -3
- pangea/services/vault/models/symmetric.py +68 -22
- pangea/services/vault/vault.py +1690 -766
- pangea/tools.py +6 -7
- pangea/utils.py +94 -33
- pangea/verify_audit.py +270 -83
- {pangea_sdk-3.8.0.dist-info → pangea_sdk-5.3.0.dist-info}/METADATA +21 -29
- pangea_sdk-5.3.0.dist-info/RECORD +56 -0
- {pangea_sdk-3.8.0.dist-info → pangea_sdk-5.3.0.dist-info}/WHEEL +1 -1
- pangea_sdk-3.8.0.dist-info/RECORD +0 -46
@@ -0,0 +1,388 @@
|
|
1
|
+
# Copyright 2022 Pangea Cyber Corporation
|
2
|
+
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import io
|
6
|
+
from typing import Dict, List, Optional, Tuple
|
7
|
+
|
8
|
+
from pydantic import Field
|
9
|
+
|
10
|
+
from pangea.config import PangeaConfig
|
11
|
+
from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult, TransferMethod
|
12
|
+
from pangea.services.base import ServiceBase
|
13
|
+
from pangea.utils import FileUploadParams, get_file_upload_params
|
14
|
+
|
15
|
+
|
16
|
+
class SanitizeFile(APIRequestModel):
|
17
|
+
scan_provider: Optional[str] = None
|
18
|
+
"""Provider to use for File Scan."""
|
19
|
+
|
20
|
+
|
21
|
+
class SanitizeContent(APIRequestModel):
|
22
|
+
url_intel: Optional[bool] = None
|
23
|
+
"""Perform URL Intel lookup."""
|
24
|
+
|
25
|
+
url_intel_provider: Optional[str] = None
|
26
|
+
"""Provider to use for URL Intel."""
|
27
|
+
|
28
|
+
domain_intel: Optional[bool] = None
|
29
|
+
"""Perform Domain Intel lookup."""
|
30
|
+
|
31
|
+
domain_intel_provider: Optional[str] = None
|
32
|
+
"""Provider to use for Domain Intel lookup."""
|
33
|
+
|
34
|
+
defang: Optional[bool] = None
|
35
|
+
"""Defang external links."""
|
36
|
+
|
37
|
+
defang_threshold: Optional[int] = None
|
38
|
+
"""Defang risk threshold."""
|
39
|
+
|
40
|
+
redact: Optional[bool] = None
|
41
|
+
"""Redact sensitive content."""
|
42
|
+
|
43
|
+
redact_detect_only: Optional[bool] = None
|
44
|
+
"""
|
45
|
+
If redact is enabled, avoids redacting the file and instead returns the PII
|
46
|
+
analysis engine results. Only works if redact is enabled.
|
47
|
+
"""
|
48
|
+
|
49
|
+
remove_attachments: Optional[bool] = None
|
50
|
+
"""Remove file attachments (PDF only)."""
|
51
|
+
|
52
|
+
remove_interactive: Optional[bool] = None
|
53
|
+
"""Remove interactive content (PDF only)."""
|
54
|
+
|
55
|
+
|
56
|
+
class SanitizeShareOutput(APIRequestModel):
|
57
|
+
enabled: Optional[bool] = None
|
58
|
+
"""Store Sanitized files to Pangea Secure Share."""
|
59
|
+
|
60
|
+
output_folder: Optional[str] = None
|
61
|
+
"""
|
62
|
+
Store Sanitized files to this Secure Share folder (will be auto-created if
|
63
|
+
it does not exist)
|
64
|
+
"""
|
65
|
+
|
66
|
+
|
67
|
+
class SanitizeRequest(APIRequestModel):
|
68
|
+
transfer_method: TransferMethod = TransferMethod.POST_URL
|
69
|
+
"""The transfer method used to upload the file data."""
|
70
|
+
|
71
|
+
source_url: Optional[str] = None
|
72
|
+
"""A URL where the file to be sanitized can be downloaded."""
|
73
|
+
|
74
|
+
share_id: Optional[str] = None
|
75
|
+
"""A Pangea Secure Share ID where the file to be Sanitized is stored."""
|
76
|
+
|
77
|
+
file: Optional[SanitizeFile] = None
|
78
|
+
"""File."""
|
79
|
+
|
80
|
+
content: Optional[SanitizeContent] = None
|
81
|
+
"""Content."""
|
82
|
+
|
83
|
+
share_output: Optional[SanitizeShareOutput] = None
|
84
|
+
"""Share output."""
|
85
|
+
|
86
|
+
size: Optional[int] = None
|
87
|
+
"""The size (in bytes) of the file. If the upload doesn't match, the call will fail."""
|
88
|
+
|
89
|
+
crc32c: Optional[str] = None
|
90
|
+
"""The CRC32C hash of the file data, which will be verified by the server if provided."""
|
91
|
+
|
92
|
+
sha256: Optional[str] = None
|
93
|
+
"""The hexadecimal-encoded SHA256 hash of the file data, which will be verified by the server if provided."""
|
94
|
+
|
95
|
+
uploaded_file_name: Optional[str] = None
|
96
|
+
"""Name of the user-uploaded file, required for transfer-method 'put-url' and 'post-url'."""
|
97
|
+
|
98
|
+
|
99
|
+
class DefangData(PangeaResponseResult):
|
100
|
+
external_urls_count: Optional[int] = None
|
101
|
+
"""Number of external links found."""
|
102
|
+
|
103
|
+
external_domains_count: Optional[int] = None
|
104
|
+
"""Number of external domains found."""
|
105
|
+
|
106
|
+
defanged_count: Optional[int] = None
|
107
|
+
"""Number of items defanged per provided rules and detections."""
|
108
|
+
|
109
|
+
url_intel_summary: Optional[str] = None
|
110
|
+
"""Processed N URLs: X are malicious, Y are suspicious, Z are unknown."""
|
111
|
+
|
112
|
+
domain_intel_summary: Optional[str] = None
|
113
|
+
"""Processed N Domains: X are malicious, Y are suspicious, Z are unknown."""
|
114
|
+
|
115
|
+
|
116
|
+
class RedactRecognizerResult(PangeaResponseResult):
|
117
|
+
field_type: str
|
118
|
+
"""The entity name."""
|
119
|
+
|
120
|
+
score: float
|
121
|
+
"""The certainty score that the entity matches this specific snippet."""
|
122
|
+
|
123
|
+
text: str
|
124
|
+
"""The text snippet that matched."""
|
125
|
+
|
126
|
+
start: int
|
127
|
+
"""The starting index of a snippet."""
|
128
|
+
|
129
|
+
end: int
|
130
|
+
"""The ending index of a snippet."""
|
131
|
+
|
132
|
+
redacted: bool
|
133
|
+
"""Indicates if this rule was used to anonymize a text snippet."""
|
134
|
+
|
135
|
+
|
136
|
+
class RedactData(PangeaResponseResult):
|
137
|
+
redaction_count: int
|
138
|
+
"""Number of items redacted"""
|
139
|
+
|
140
|
+
summary_counts: Dict[str, int] = Field(default_factory=dict)
|
141
|
+
"""Summary counts."""
|
142
|
+
|
143
|
+
recognizer_results: Optional[List[RedactRecognizerResult]] = None
|
144
|
+
"""The scoring result of a set of rules."""
|
145
|
+
|
146
|
+
|
147
|
+
class CDR(PangeaResponseResult):
|
148
|
+
file_attachments_removed: Optional[int] = None
|
149
|
+
"""Number of file attachments removed."""
|
150
|
+
|
151
|
+
interactive_contents_removed: Optional[int] = None
|
152
|
+
"""Number of interactive content items removed."""
|
153
|
+
|
154
|
+
|
155
|
+
class SanitizeData(PangeaResponseResult):
|
156
|
+
defang: Optional[DefangData] = None
|
157
|
+
"""Defang."""
|
158
|
+
|
159
|
+
redact: Optional[RedactData] = None
|
160
|
+
"""Redact."""
|
161
|
+
|
162
|
+
malicious_file: Optional[bool] = None
|
163
|
+
"""If the file scanned was malicious."""
|
164
|
+
|
165
|
+
cdr: Optional[CDR] = None
|
166
|
+
"""Content Disarm and Reconstruction."""
|
167
|
+
|
168
|
+
|
169
|
+
class SanitizeResult(PangeaResponseResult):
|
170
|
+
dest_url: Optional[str] = None
|
171
|
+
"""A URL where the Sanitized file can be downloaded."""
|
172
|
+
|
173
|
+
dest_share_id: Optional[str] = None
|
174
|
+
"""Pangea Secure Share ID of the Sanitized file."""
|
175
|
+
|
176
|
+
data: SanitizeData
|
177
|
+
"""Sanitize data."""
|
178
|
+
|
179
|
+
parameters: Dict = {}
|
180
|
+
"""The parameters, which were passed in the request, echoed back."""
|
181
|
+
|
182
|
+
|
183
|
+
class Sanitize(ServiceBase):
|
184
|
+
"""Sanitize service client.
|
185
|
+
|
186
|
+
Examples:
|
187
|
+
import os
|
188
|
+
|
189
|
+
# Pangea SDK
|
190
|
+
from pangea.config import PangeaConfig
|
191
|
+
from pangea.services import Sanitize
|
192
|
+
|
193
|
+
PANGEA_SANITIZE_TOKEN = os.getenv("PANGEA_SANITIZE_TOKEN")
|
194
|
+
config = PangeaConfig(domain="pangea.cloud")
|
195
|
+
|
196
|
+
sanitize = Sanitize(token=PANGEA_SANITIZE_TOKEN, config=config)
|
197
|
+
"""
|
198
|
+
|
199
|
+
service_name = "sanitize"
|
200
|
+
|
201
|
+
def __init__(
|
202
|
+
self, token: str, config: PangeaConfig | None = None, logger_name: str = "pangea", config_id: str | None = None
|
203
|
+
) -> None:
|
204
|
+
"""
|
205
|
+
Sanitize client
|
206
|
+
|
207
|
+
Initializes a new Sanitize client.
|
208
|
+
|
209
|
+
Args:
|
210
|
+
token: Pangea API token.
|
211
|
+
config: Configuration.
|
212
|
+
logger_name: Logger name.
|
213
|
+
config_id: Configuration ID.
|
214
|
+
|
215
|
+
Examples:
|
216
|
+
config = PangeaConfig(domain="aws.us.pangea.cloud")
|
217
|
+
authz = Sanitize(token="pangea_token", config=config)
|
218
|
+
"""
|
219
|
+
|
220
|
+
super().__init__(token, config, logger_name, config_id=config_id)
|
221
|
+
|
222
|
+
def sanitize(
|
223
|
+
self,
|
224
|
+
transfer_method: TransferMethod = TransferMethod.POST_URL,
|
225
|
+
file_path: Optional[str] = None,
|
226
|
+
file: Optional[io.BufferedReader] = None,
|
227
|
+
source_url: Optional[str] = None,
|
228
|
+
share_id: Optional[str] = None,
|
229
|
+
file_scan: Optional[SanitizeFile] = None,
|
230
|
+
content: Optional[SanitizeContent] = None,
|
231
|
+
share_output: Optional[SanitizeShareOutput] = None,
|
232
|
+
size: Optional[int] = None,
|
233
|
+
crc32c: Optional[str] = None,
|
234
|
+
sha256: Optional[str] = None,
|
235
|
+
uploaded_file_name: Optional[str] = None,
|
236
|
+
sync_call: bool = True,
|
237
|
+
) -> PangeaResponse[SanitizeResult]:
|
238
|
+
"""
|
239
|
+
Sanitize
|
240
|
+
|
241
|
+
Apply file sanitization actions according to specified rules.
|
242
|
+
|
243
|
+
OperationId: sanitize_post_v1_sanitize
|
244
|
+
|
245
|
+
Args:
|
246
|
+
transfer_method: The transfer method used to upload the file data.
|
247
|
+
file_path: Path to file to sanitize.
|
248
|
+
file: File to sanitize.
|
249
|
+
source_url: A URL where the file to be sanitized can be downloaded.
|
250
|
+
share_id: A Pangea Secure Share ID where the file to be sanitized is stored.
|
251
|
+
file_scan: Options for File Scan.
|
252
|
+
content: Options for how the file should be sanitized.
|
253
|
+
share_output: Integration with Secure Share.
|
254
|
+
size: The size (in bytes) of the file. If the upload doesn't match, the call will fail.
|
255
|
+
crc32c: The CRC32C hash of the file data, which will be verified by the server if provided.
|
256
|
+
sha256: The hexadecimal-encoded SHA256 hash of the file data, which will be verified by the server if provided.
|
257
|
+
uploaded_file_name: Name of the user-uploaded file, required for `TransferMethod.PUT_URL` and `TransferMethod.POST_URL`.
|
258
|
+
sync_call: Whether or not to poll on HTTP/202.
|
259
|
+
|
260
|
+
Raises:
|
261
|
+
PangeaAPIException: If an API error happens.
|
262
|
+
|
263
|
+
Returns:
|
264
|
+
The sanitized file and information on the sanitization that was
|
265
|
+
performed.
|
266
|
+
|
267
|
+
Examples:
|
268
|
+
with open("/path/to/file.pdf", "rb") as f:
|
269
|
+
response = sanitize.sanitize(
|
270
|
+
file=f,
|
271
|
+
transfer_method=TransferMethod.POST_URL,
|
272
|
+
uploaded_file_name="uploaded_file",
|
273
|
+
)
|
274
|
+
"""
|
275
|
+
|
276
|
+
if transfer_method == TransferMethod.SOURCE_URL and source_url is None:
|
277
|
+
raise ValueError("`source_url` argument is required when using `TransferMethod.SOURCE_URL`.")
|
278
|
+
|
279
|
+
if source_url is not None and transfer_method != TransferMethod.SOURCE_URL:
|
280
|
+
raise ValueError(
|
281
|
+
"`transfer_method` should be `TransferMethod.SOURCE_URL` when using the `source_url` argument."
|
282
|
+
)
|
283
|
+
|
284
|
+
files: Optional[List[Tuple]] = None
|
285
|
+
if file or file_path:
|
286
|
+
if file_path:
|
287
|
+
file = open(file_path, "rb")
|
288
|
+
if (
|
289
|
+
transfer_method == TransferMethod.POST_URL
|
290
|
+
and file
|
291
|
+
and (sha256 is None or crc32c is None or size is None)
|
292
|
+
):
|
293
|
+
params = get_file_upload_params(file)
|
294
|
+
crc32c = params.crc_hex if crc32c is None else crc32c
|
295
|
+
sha256 = params.sha256_hex if sha256 is None else sha256
|
296
|
+
size = params.size if size is None else size
|
297
|
+
else:
|
298
|
+
crc32c, sha256, size = None, None, None
|
299
|
+
files = [("upload", ("filename", file, "application/octet-stream"))]
|
300
|
+
elif source_url is None:
|
301
|
+
raise ValueError("Need to set one of `file_path`, `file`, or `source_url` arguments.")
|
302
|
+
|
303
|
+
input = SanitizeRequest(
|
304
|
+
transfer_method=transfer_method,
|
305
|
+
source_url=source_url,
|
306
|
+
share_id=share_id,
|
307
|
+
file=file_scan,
|
308
|
+
content=content,
|
309
|
+
share_output=share_output,
|
310
|
+
crc32c=crc32c,
|
311
|
+
sha256=sha256,
|
312
|
+
size=size,
|
313
|
+
uploaded_file_name=uploaded_file_name,
|
314
|
+
)
|
315
|
+
data = input.model_dump(exclude_none=True)
|
316
|
+
try:
|
317
|
+
response = self.request.post("v1/sanitize", SanitizeResult, data=data, files=files, poll_result=sync_call)
|
318
|
+
finally:
|
319
|
+
if file_path and file is not None:
|
320
|
+
file.close()
|
321
|
+
return response
|
322
|
+
|
323
|
+
def request_upload_url(
|
324
|
+
self,
|
325
|
+
transfer_method: TransferMethod = TransferMethod.PUT_URL,
|
326
|
+
params: Optional[FileUploadParams] = None,
|
327
|
+
file_scan: Optional[SanitizeFile] = None,
|
328
|
+
content: Optional[SanitizeContent] = None,
|
329
|
+
share_output: Optional[SanitizeShareOutput] = None,
|
330
|
+
size: Optional[int] = None,
|
331
|
+
crc32c: Optional[str] = None,
|
332
|
+
sha256: Optional[str] = None,
|
333
|
+
uploaded_file_name: Optional[str] = None,
|
334
|
+
) -> PangeaResponse[SanitizeResult]:
|
335
|
+
"""
|
336
|
+
Sanitize via presigned URL
|
337
|
+
|
338
|
+
Apply file sanitization actions according to specified rules via a
|
339
|
+
[presigned URL](https://pangea.cloud/docs/api/transfer-methods).
|
340
|
+
|
341
|
+
OperationId: sanitize_post_v1_sanitize 2
|
342
|
+
|
343
|
+
Args:
|
344
|
+
transfer_method: The transfer method used to upload the file data.
|
345
|
+
params: File upload parameters.
|
346
|
+
file_scan: Options for File Scan.
|
347
|
+
content: Options for how the file should be sanitized.
|
348
|
+
share_output: Integration with Secure Share.
|
349
|
+
size: The size (in bytes) of the file. If the upload doesn't match, the call will fail.
|
350
|
+
crc32c: The CRC32C hash of the file data, which will be verified by the server if provided.
|
351
|
+
sha256: The hexadecimal-encoded SHA256 hash of the file data, which will be verified by the server if provided.
|
352
|
+
uploaded_file_name: Name of the user-uploaded file, required for `TransferMethod.PUT_URL` and `TransferMethod.POST_URL`.
|
353
|
+
|
354
|
+
Raises:
|
355
|
+
PangeaAPIException: If an API error happens.
|
356
|
+
|
357
|
+
Returns:
|
358
|
+
A presigned URL.
|
359
|
+
|
360
|
+
Examples:
|
361
|
+
presignedUrl = sanitize.request_upload_url(
|
362
|
+
transfer_method=TransferMethod.PUT_URL,
|
363
|
+
uploaded_file_name="uploaded_file",
|
364
|
+
)
|
365
|
+
|
366
|
+
# Upload file to `presignedUrl.accepted_result.put_url`.
|
367
|
+
|
368
|
+
# Poll for Sanitize's result.
|
369
|
+
response: PangeaResponse[SanitizeResult] = sanitize.poll_result(response=presignedUrl)
|
370
|
+
"""
|
371
|
+
|
372
|
+
input = SanitizeRequest(
|
373
|
+
transfer_method=transfer_method,
|
374
|
+
file=file_scan,
|
375
|
+
content=content,
|
376
|
+
share_output=share_output,
|
377
|
+
crc32c=crc32c,
|
378
|
+
sha256=sha256,
|
379
|
+
size=size,
|
380
|
+
uploaded_file_name=uploaded_file_name,
|
381
|
+
)
|
382
|
+
if params is not None and (transfer_method == TransferMethod.POST_URL):
|
383
|
+
input.crc32c = params.crc_hex
|
384
|
+
input.sha256 = params.sha256_hex
|
385
|
+
input.size = params.size
|
386
|
+
|
387
|
+
data = input.model_dump(exclude_none=True)
|
388
|
+
return self.request.request_presigned_url("v1/sanitize", SanitizeResult, data=data)
|
@@ -0,0 +1,170 @@
|
|
1
|
+
import enum
|
2
|
+
|
3
|
+
|
4
|
+
class FileFormat(str, enum.Enum):
|
5
|
+
F3G2 = "3G2"
|
6
|
+
F3GP = "3GP"
|
7
|
+
F3MF = "3MF"
|
8
|
+
F7Z = "7Z"
|
9
|
+
A = "A"
|
10
|
+
AAC = "AAC"
|
11
|
+
ACCDB = "ACCDB"
|
12
|
+
AIFF = "AIFF"
|
13
|
+
AMF = "AMF"
|
14
|
+
AMR = "AMR"
|
15
|
+
APE = "APE"
|
16
|
+
ASF = "ASF"
|
17
|
+
ATOM = "ATOM"
|
18
|
+
AU = "AU"
|
19
|
+
AVI = "AVI"
|
20
|
+
AVIF = "AVIF"
|
21
|
+
BIN = "BIN"
|
22
|
+
BMP = "BMP"
|
23
|
+
BPG = "BPG"
|
24
|
+
BZ2 = "BZ2"
|
25
|
+
CAB = "CAB"
|
26
|
+
CLASS = "CLASS"
|
27
|
+
CPIO = "CPIO"
|
28
|
+
CRX = "CRX"
|
29
|
+
CSV = "CSV"
|
30
|
+
DAE = "DAE"
|
31
|
+
DBF = "DBF"
|
32
|
+
DCM = "DCM"
|
33
|
+
DEB = "DEB"
|
34
|
+
DJVU = "DJVU"
|
35
|
+
DLL = "DLL"
|
36
|
+
DOC = "DOC"
|
37
|
+
DOCX = "DOCX"
|
38
|
+
DWG = "DWG"
|
39
|
+
EOT = "EOT"
|
40
|
+
EPUB = "EPUB"
|
41
|
+
EXE = "EXE"
|
42
|
+
FDF = "FDF"
|
43
|
+
FITS = "FITS"
|
44
|
+
FLAC = "FLAC"
|
45
|
+
FLV = "FLV"
|
46
|
+
GBR = "GBR"
|
47
|
+
GEOJSON = "GEOJSON"
|
48
|
+
GIF = "GIF"
|
49
|
+
GLB = "GLB"
|
50
|
+
GML = "GML"
|
51
|
+
GPX = "GPX"
|
52
|
+
GZ = "GZ"
|
53
|
+
HAR = "HAR"
|
54
|
+
HDR = "HDR"
|
55
|
+
HEIC = "HEIC"
|
56
|
+
HEIF = "HEIF"
|
57
|
+
HTML = "HTML"
|
58
|
+
ICNS = "ICNS"
|
59
|
+
ICO = "ICO"
|
60
|
+
ICS = "ICS"
|
61
|
+
ISO = "ISO"
|
62
|
+
JAR = "JAR"
|
63
|
+
JP2 = "JP2"
|
64
|
+
JPF = "JPF"
|
65
|
+
JPG = "JPG"
|
66
|
+
JPM = "JPM"
|
67
|
+
JS = "JS"
|
68
|
+
JSON = "JSON"
|
69
|
+
JXL = "JXL"
|
70
|
+
JXR = "JXR"
|
71
|
+
KML = "KML"
|
72
|
+
LIT = "LIT"
|
73
|
+
LNK = "LNK"
|
74
|
+
LUA = "LUA"
|
75
|
+
LZ = "LZ"
|
76
|
+
M3U = "M3U"
|
77
|
+
M4A = "M4A"
|
78
|
+
MACHO = "MACHO"
|
79
|
+
MDB = "MDB"
|
80
|
+
MIDI = "MIDI"
|
81
|
+
MKV = "MKV"
|
82
|
+
MOBI = "MOBI"
|
83
|
+
MOV = "MOV"
|
84
|
+
MP3 = "MP3"
|
85
|
+
MP4 = "MP4"
|
86
|
+
MPC = "MPC"
|
87
|
+
MPEG = "MPEG"
|
88
|
+
MQV = "MQV"
|
89
|
+
MRC = "MRC"
|
90
|
+
MSG = "MSG"
|
91
|
+
MSI = "MSI"
|
92
|
+
NDJSON = "NDJSON"
|
93
|
+
NES = "NES"
|
94
|
+
ODC = "ODC"
|
95
|
+
ODF = "ODF"
|
96
|
+
ODG = "ODG"
|
97
|
+
ODP = "ODP"
|
98
|
+
ODS = "ODS"
|
99
|
+
ODT = "ODT"
|
100
|
+
OGA = "OGA"
|
101
|
+
OGV = "OGV"
|
102
|
+
OTF = "OTF"
|
103
|
+
OTG = "OTG"
|
104
|
+
OTP = "OTP"
|
105
|
+
OTS = "OTS"
|
106
|
+
OTT = "OTT"
|
107
|
+
OWL = "OWL"
|
108
|
+
P7S = "P7S"
|
109
|
+
PAT = "PAT"
|
110
|
+
PDF = "PDF"
|
111
|
+
PHP = "PHP"
|
112
|
+
PL = "PL"
|
113
|
+
PNG = "PNG"
|
114
|
+
PPT = "PPT"
|
115
|
+
PPTX = "PPTX"
|
116
|
+
PS = "PS"
|
117
|
+
PSD = "PSD"
|
118
|
+
PUB = "PUB"
|
119
|
+
PY = "PY"
|
120
|
+
QCP = "QCP"
|
121
|
+
RAR = "RAR"
|
122
|
+
RMVB = "RMVB"
|
123
|
+
RPM = "RPM"
|
124
|
+
RSS = "RSS"
|
125
|
+
RTF = "RTF"
|
126
|
+
SHP = "SHP"
|
127
|
+
SHX = "SHX"
|
128
|
+
SO = "SO"
|
129
|
+
SQLITE = "SQLITE"
|
130
|
+
SRT = "SRT"
|
131
|
+
SVG = "SVG"
|
132
|
+
SWF = "SWF"
|
133
|
+
SXC = "SXC"
|
134
|
+
TAR = "TAR"
|
135
|
+
TCL = "TCL"
|
136
|
+
TCX = "TCX"
|
137
|
+
TIFF = "TIFF"
|
138
|
+
TORRENT = "TORRENT"
|
139
|
+
TSV = "TSV"
|
140
|
+
TTC = "TTC"
|
141
|
+
TTF = "TTF"
|
142
|
+
TXT = "TXT"
|
143
|
+
VCF = "VCF"
|
144
|
+
VOC = "VOC"
|
145
|
+
VTT = "VTT"
|
146
|
+
WARC = "WARC"
|
147
|
+
WASM = "WASM"
|
148
|
+
WAV = "WAV"
|
149
|
+
WEBM = "WEBM"
|
150
|
+
WEBP = "WEBP"
|
151
|
+
WOFF = "WOFF"
|
152
|
+
WOFF2 = "WOFF2"
|
153
|
+
X3D = "X3D"
|
154
|
+
XAR = "XAR"
|
155
|
+
XCF = "XCF"
|
156
|
+
XFDF = "XFDF"
|
157
|
+
XLF = "XLF"
|
158
|
+
XLS = "XLS"
|
159
|
+
XLSX = "XLSX"
|
160
|
+
XML = "XML"
|
161
|
+
XPM = "XPM"
|
162
|
+
XZ = "XZ"
|
163
|
+
ZIP = "ZIP"
|
164
|
+
ZST = "ZST"
|
165
|
+
|
166
|
+
def __str__(self):
|
167
|
+
return str(self.value)
|
168
|
+
|
169
|
+
def __repr__(self):
|
170
|
+
return str(self.value)
|