polyfile-weave 0.5.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of polyfile-weave might be problematic. Click here for more details.
- polyfile/__init__.py +15 -0
- polyfile/__main__.py +394 -0
- polyfile/arithmetic.py +27 -0
- polyfile/ast.py +114 -0
- polyfile/debugger.py +1039 -0
- polyfile/expressions.py +346 -0
- polyfile/fileutils.py +343 -0
- polyfile/html.py +135 -0
- polyfile/http/__init__.py +1 -0
- polyfile/http/defacto.py +37 -0
- polyfile/http/deprecated.py +51 -0
- polyfile/http/experimental.py +67 -0
- polyfile/http/http_11.py +548 -0
- polyfile/http/matcher.py +37 -0
- polyfile/http/structured_headers.py +48 -0
- polyfile/iterators.py +72 -0
- polyfile/jpeg.py +24 -0
- polyfile/kaitai/__init__.py +0 -0
- polyfile/kaitai/compiler.py +156 -0
- polyfile/kaitai/parser.py +312 -0
- polyfile/kaitai/parsers/__init__.py +0 -0
- polyfile/kaitai/parsers/aix_utmp.py +116 -0
- polyfile/kaitai/parsers/allegro_dat.py +367 -0
- polyfile/kaitai/parsers/andes_firmware.py +64 -0
- polyfile/kaitai/parsers/android_bootldr_asus.py +105 -0
- polyfile/kaitai/parsers/android_bootldr_huawei.py +181 -0
- polyfile/kaitai/parsers/android_bootldr_qcom.py +217 -0
- polyfile/kaitai/parsers/android_dto.py +138 -0
- polyfile/kaitai/parsers/android_img.py +319 -0
- polyfile/kaitai/parsers/android_nanoapp_header.py +83 -0
- polyfile/kaitai/parsers/android_opengl_shaders_cache.py +151 -0
- polyfile/kaitai/parsers/android_sparse.py +237 -0
- polyfile/kaitai/parsers/android_super.py +401 -0
- polyfile/kaitai/parsers/apm_partition_table.py +196 -0
- polyfile/kaitai/parsers/apple_single_double.py +180 -0
- polyfile/kaitai/parsers/asn1_der.py +235 -0
- polyfile/kaitai/parsers/au.py +138 -0
- polyfile/kaitai/parsers/avantes_roh60.py +112 -0
- polyfile/kaitai/parsers/avi.py +296 -0
- polyfile/kaitai/parsers/bcd.py +111 -0
- polyfile/kaitai/parsers/bitcoin_transaction.py +210 -0
- polyfile/kaitai/parsers/blender_blend.py +334 -0
- polyfile/kaitai/parsers/bmp.py +780 -0
- polyfile/kaitai/parsers/bson.py +411 -0
- polyfile/kaitai/parsers/btrfs_stream.py +318 -0
- polyfile/kaitai/parsers/bytes_with_io.py +27 -0
- polyfile/kaitai/parsers/chrome_pak.py +194 -0
- polyfile/kaitai/parsers/code_6502.py +456 -0
- polyfile/kaitai/parsers/compressed_resource.py +217 -0
- polyfile/kaitai/parsers/cpio_old_le.py +154 -0
- polyfile/kaitai/parsers/cramfs.py +344 -0
- polyfile/kaitai/parsers/creative_voice_file.py +342 -0
- polyfile/kaitai/parsers/dbf.py +274 -0
- polyfile/kaitai/parsers/dcmp_0.py +664 -0
- polyfile/kaitai/parsers/dcmp_1.py +422 -0
- polyfile/kaitai/parsers/dcmp_2.py +312 -0
- polyfile/kaitai/parsers/dcmp_variable_length_integer.py +66 -0
- polyfile/kaitai/parsers/dex.py +1086 -0
- polyfile/kaitai/parsers/dicom.py +4370 -0
- polyfile/kaitai/parsers/dime_message.py +201 -0
- polyfile/kaitai/parsers/dns_packet.py +569 -0
- polyfile/kaitai/parsers/doom_wad.py +654 -0
- polyfile/kaitai/parsers/dos_datetime.py +191 -0
- polyfile/kaitai/parsers/dos_mz.py +172 -0
- polyfile/kaitai/parsers/ds_store.py +513 -0
- polyfile/kaitai/parsers/dtb.py +310 -0
- polyfile/kaitai/parsers/dune_2_pak.py +126 -0
- polyfile/kaitai/parsers/edid.py +472 -0
- polyfile/kaitai/parsers/efivar_signature_list.py +331 -0
- polyfile/kaitai/parsers/elf.py +2482 -0
- polyfile/kaitai/parsers/ethernet_frame.py +114 -0
- polyfile/kaitai/parsers/exif.py +723 -0
- polyfile/kaitai/parsers/ext2.py +537 -0
- polyfile/kaitai/parsers/fallout2_dat.py +187 -0
- polyfile/kaitai/parsers/fallout_dat.py +156 -0
- polyfile/kaitai/parsers/fasttracker_xm_module.py +558 -0
- polyfile/kaitai/parsers/ftl_dat.py +90 -0
- polyfile/kaitai/parsers/genmidi_op2.py +161 -0
- polyfile/kaitai/parsers/gettext_mo.py +541 -0
- polyfile/kaitai/parsers/gif.py +492 -0
- polyfile/kaitai/parsers/gimp_brush.py +244 -0
- polyfile/kaitai/parsers/glibc_utmp.py +114 -0
- polyfile/kaitai/parsers/gltf_binary.py +132 -0
- polyfile/kaitai/parsers/google_protobuf.py +151 -0
- polyfile/kaitai/parsers/gpt_partition_table.py +175 -0
- polyfile/kaitai/parsers/gran_turismo_vol.py +140 -0
- polyfile/kaitai/parsers/grub2_font.py +337 -0
- polyfile/kaitai/parsers/gzip.py +232 -0
- polyfile/kaitai/parsers/hashcat_restore.py +60 -0
- polyfile/kaitai/parsers/hccap.py +111 -0
- polyfile/kaitai/parsers/hccapx.py +103 -0
- polyfile/kaitai/parsers/heaps_pak.py +177 -0
- polyfile/kaitai/parsers/heroes_of_might_and_magic_agg.py +116 -0
- polyfile/kaitai/parsers/heroes_of_might_and_magic_bmp.py +34 -0
- polyfile/kaitai/parsers/icmp_packet.py +136 -0
- polyfile/kaitai/parsers/ico.py +129 -0
- polyfile/kaitai/parsers/id3v1_1.py +220 -0
- polyfile/kaitai/parsers/id3v2_3.py +324 -0
- polyfile/kaitai/parsers/id3v2_4.py +423 -0
- polyfile/kaitai/parsers/ines.py +282 -0
- polyfile/kaitai/parsers/ipv4_packet.py +158 -0
- polyfile/kaitai/parsers/ipv6_packet.py +55 -0
- polyfile/kaitai/parsers/iso9660.py +544 -0
- polyfile/kaitai/parsers/java_class.py +1113 -0
- polyfile/kaitai/parsers/jpeg.py +361 -0
- polyfile/kaitai/parsers/luks.py +149 -0
- polyfile/kaitai/parsers/lzh.py +165 -0
- polyfile/kaitai/parsers/mac_os_resource_snd.py +493 -0
- polyfile/kaitai/parsers/mach_o.py +3033 -0
- polyfile/kaitai/parsers/mach_o_fat.py +92 -0
- polyfile/kaitai/parsers/magicavoxel_vox.py +391 -0
- polyfile/kaitai/parsers/manifest.json +1 -0
- polyfile/kaitai/parsers/mbr_partition_table.py +119 -0
- polyfile/kaitai/parsers/mcap.py +1015 -0
- polyfile/kaitai/parsers/microsoft_cfb.py +293 -0
- polyfile/kaitai/parsers/microsoft_network_monitor_v2.py +309 -0
- polyfile/kaitai/parsers/microsoft_pe.py +765 -0
- polyfile/kaitai/parsers/mifare_classic.py +706 -0
- polyfile/kaitai/parsers/minecraft_nbt.py +449 -0
- polyfile/kaitai/parsers/monomakh_sapr_chg.py +69 -0
- polyfile/kaitai/parsers/mozilla_mar.py +239 -0
- polyfile/kaitai/parsers/mp4.py +333 -0
- polyfile/kaitai/parsers/msgpack.py +467 -0
- polyfile/kaitai/parsers/nitf.py +1189 -0
- polyfile/kaitai/parsers/nt_mdt_pal.py +155 -0
- polyfile/kaitai/parsers/ogg.py +118 -0
- polyfile/kaitai/parsers/openpgp_message.py +993 -0
- polyfile/kaitai/parsers/packet_ppi.py +515 -0
- polyfile/kaitai/parsers/pcap.py +344 -0
- polyfile/kaitai/parsers/pcf_font.py +506 -0
- polyfile/kaitai/parsers/pcx.py +195 -0
- polyfile/kaitai/parsers/pcx_dcx.py +79 -0
- polyfile/kaitai/parsers/phar_without_stub.py +399 -0
- polyfile/kaitai/parsers/php_serialized_value.py +505 -0
- polyfile/kaitai/parsers/png.py +721 -0
- polyfile/kaitai/parsers/protocol_body.py +260 -0
- polyfile/kaitai/parsers/psx_tim.py +104 -0
- polyfile/kaitai/parsers/python_pickle.py +718 -0
- polyfile/kaitai/parsers/python_pyc_27.py +510 -0
- polyfile/kaitai/parsers/quake_mdl.py +441 -0
- polyfile/kaitai/parsers/quake_pak.py +112 -0
- polyfile/kaitai/parsers/quicktime_mov.py +634 -0
- polyfile/kaitai/parsers/rar.py +265 -0
- polyfile/kaitai/parsers/regf.py +569 -0
- polyfile/kaitai/parsers/renderware_binary_stream.py +877 -0
- polyfile/kaitai/parsers/resource_fork.py +611 -0
- polyfile/kaitai/parsers/respack.py +57 -0
- polyfile/kaitai/parsers/riff.py +409 -0
- polyfile/kaitai/parsers/rpm.py +964 -0
- polyfile/kaitai/parsers/rtcp_payload.py +579 -0
- polyfile/kaitai/parsers/rtp_packet.py +150 -0
- polyfile/kaitai/parsers/rtpdump.py +115 -0
- polyfile/kaitai/parsers/ruby_marshal.py +423 -0
- polyfile/kaitai/parsers/s3m.py +493 -0
- polyfile/kaitai/parsers/saints_row_2_vpp_pc.py +254 -0
- polyfile/kaitai/parsers/shapefile_index.py +174 -0
- polyfile/kaitai/parsers/shapefile_main.py +893 -0
- polyfile/kaitai/parsers/some_ip.py +209 -0
- polyfile/kaitai/parsers/some_ip_container.py +37 -0
- polyfile/kaitai/parsers/some_ip_sd.py +86 -0
- polyfile/kaitai/parsers/some_ip_sd_entries.py +160 -0
- polyfile/kaitai/parsers/some_ip_sd_options.py +374 -0
- polyfile/kaitai/parsers/specpr.py +404 -0
- polyfile/kaitai/parsers/sqlite3.py +472 -0
- polyfile/kaitai/parsers/ssh_public_key.py +252 -0
- polyfile/kaitai/parsers/standard_midi_file.py +390 -0
- polyfile/kaitai/parsers/stl.py +111 -0
- polyfile/kaitai/parsers/sudoers_ts.py +201 -0
- polyfile/kaitai/parsers/swf.py +406 -0
- polyfile/kaitai/parsers/systemd_journal.py +361 -0
- polyfile/kaitai/parsers/tcp_segment.py +57 -0
- polyfile/kaitai/parsers/tga.py +213 -0
- polyfile/kaitai/parsers/tls_client_hello.py +293 -0
- polyfile/kaitai/parsers/tr_dos_image.py +322 -0
- polyfile/kaitai/parsers/tsm.py +198 -0
- polyfile/kaitai/parsers/ttf.py +1847 -0
- polyfile/kaitai/parsers/udp_datagram.py +42 -0
- polyfile/kaitai/parsers/uefi_te.py +236 -0
- polyfile/kaitai/parsers/uimage.py +198 -0
- polyfile/kaitai/parsers/utf8_string.py +137 -0
- polyfile/kaitai/parsers/vfat.py +410 -0
- polyfile/kaitai/parsers/vlq_base128_be.py +104 -0
- polyfile/kaitai/parsers/vlq_base128_le.py +129 -0
- polyfile/kaitai/parsers/vmware_vmdk.py +167 -0
- polyfile/kaitai/parsers/vp8_ivf.py +112 -0
- polyfile/kaitai/parsers/warcraft_2_pud.py +423 -0
- polyfile/kaitai/parsers/wav.py +1014 -0
- polyfile/kaitai/parsers/websocket.py +167 -0
- polyfile/kaitai/parsers/windows_evt_log.py +304 -0
- polyfile/kaitai/parsers/windows_lnk_file.py +467 -0
- polyfile/kaitai/parsers/windows_minidump.py +575 -0
- polyfile/kaitai/parsers/windows_resource_file.py +243 -0
- polyfile/kaitai/parsers/windows_shell_items.py +190 -0
- polyfile/kaitai/parsers/windows_systemtime.py +52 -0
- polyfile/kaitai/parsers/wmf.py +502 -0
- polyfile/kaitai/parsers/xar.py +181 -0
- polyfile/kaitai/parsers/xwd.py +189 -0
- polyfile/kaitai/parsers/zip.py +685 -0
- polyfile/kaitai/parsers/zisofs.py +158 -0
- polyfile/kaitai/parsers/zx_spectrum_tap.py +184 -0
- polyfile/kaitaimatcher.py +113 -0
- polyfile/languagematcher.py +217 -0
- polyfile/logger.py +135 -0
- polyfile/magic.py +2983 -0
- polyfile/magic_defs/COPYING +29 -0
- polyfile/magic_defs/__init__.py +0 -0
- polyfile/magic_defs/acorn +102 -0
- polyfile/magic_defs/adi +13 -0
- polyfile/magic_defs/adventure +122 -0
- polyfile/magic_defs/aes +29 -0
- polyfile/magic_defs/algol68 +35 -0
- polyfile/magic_defs/allegro +9 -0
- polyfile/magic_defs/alliant +18 -0
- polyfile/magic_defs/alpha +32 -0
- polyfile/magic_defs/amanda +12 -0
- polyfile/magic_defs/amigaos +218 -0
- polyfile/magic_defs/android +259 -0
- polyfile/magic_defs/animation +1197 -0
- polyfile/magic_defs/aout +46 -0
- polyfile/magic_defs/apache +28 -0
- polyfile/magic_defs/apl +7 -0
- polyfile/magic_defs/apple +773 -0
- polyfile/magic_defs/application +7 -0
- polyfile/magic_defs/applix +13 -0
- polyfile/magic_defs/apt +52 -0
- polyfile/magic_defs/archive +2586 -0
- polyfile/magic_defs/aria +38 -0
- polyfile/magic_defs/arm +50 -0
- polyfile/magic_defs/asf +132 -0
- polyfile/magic_defs/assembler +18 -0
- polyfile/magic_defs/asterix +18 -0
- polyfile/magic_defs/att3b +41 -0
- polyfile/magic_defs/audio +1291 -0
- polyfile/magic_defs/avm +33 -0
- polyfile/magic_defs/basis +18 -0
- polyfile/magic_defs/beetle +7 -0
- polyfile/magic_defs/ber +65 -0
- polyfile/magic_defs/bflt +14 -0
- polyfile/magic_defs/bhl +10 -0
- polyfile/magic_defs/bioinformatics +178 -0
- polyfile/magic_defs/biosig +154 -0
- polyfile/magic_defs/blackberry +8 -0
- polyfile/magic_defs/blcr +25 -0
- polyfile/magic_defs/blender +50 -0
- polyfile/magic_defs/blit +24 -0
- polyfile/magic_defs/bm +10 -0
- polyfile/magic_defs/bout +11 -0
- polyfile/magic_defs/bsdi +33 -0
- polyfile/magic_defs/bsi +10 -0
- polyfile/magic_defs/btsnoop +13 -0
- polyfile/magic_defs/burp +7 -0
- polyfile/magic_defs/bytecode +41 -0
- polyfile/magic_defs/c-lang +110 -0
- polyfile/magic_defs/c64 +531 -0
- polyfile/magic_defs/cad +437 -0
- polyfile/magic_defs/cafebabe +107 -0
- polyfile/magic_defs/cbor +21 -0
- polyfile/magic_defs/ccf +14 -0
- polyfile/magic_defs/cddb +12 -0
- polyfile/magic_defs/chord +15 -0
- polyfile/magic_defs/cisco +12 -0
- polyfile/magic_defs/citrus +12 -0
- polyfile/magic_defs/clarion +27 -0
- polyfile/magic_defs/claris +48 -0
- polyfile/magic_defs/clipper +65 -0
- polyfile/magic_defs/clojure +30 -0
- polyfile/magic_defs/coff +98 -0
- polyfile/magic_defs/commands +201 -0
- polyfile/magic_defs/communications +22 -0
- polyfile/magic_defs/compress +461 -0
- polyfile/magic_defs/console +1213 -0
- polyfile/magic_defs/convex +69 -0
- polyfile/magic_defs/coverage +91 -0
- polyfile/magic_defs/cracklib +14 -0
- polyfile/magic_defs/crypto +31 -0
- polyfile/magic_defs/csv +8 -0
- polyfile/magic_defs/ctags +6 -0
- polyfile/magic_defs/ctf +23 -0
- polyfile/magic_defs/cubemap +8 -0
- polyfile/magic_defs/cups +56 -0
- polyfile/magic_defs/dact +11 -0
- polyfile/magic_defs/database +886 -0
- polyfile/magic_defs/dataone +47 -0
- polyfile/magic_defs/dbpf +15 -0
- polyfile/magic_defs/der +146 -0
- polyfile/magic_defs/diamond +12 -0
- polyfile/magic_defs/dif +33 -0
- polyfile/magic_defs/diff +41 -0
- polyfile/magic_defs/digital +59 -0
- polyfile/magic_defs/dolby +69 -0
- polyfile/magic_defs/dsf +25 -0
- polyfile/magic_defs/dump +96 -0
- polyfile/magic_defs/dwarfs +45 -0
- polyfile/magic_defs/dyadic +61 -0
- polyfile/magic_defs/ebml +8 -0
- polyfile/magic_defs/edid +11 -0
- polyfile/magic_defs/editors +43 -0
- polyfile/magic_defs/efi +15 -0
- polyfile/magic_defs/elf +379 -0
- polyfile/magic_defs/encore +22 -0
- polyfile/magic_defs/epoc +62 -0
- polyfile/magic_defs/erlang +21 -0
- polyfile/magic_defs/espressif +57 -0
- polyfile/magic_defs/esri +28 -0
- polyfile/magic_defs/etf +33 -0
- polyfile/magic_defs/fcs +9 -0
- polyfile/magic_defs/filesystems +2694 -0
- polyfile/magic_defs/finger +16 -0
- polyfile/magic_defs/firmware +133 -0
- polyfile/magic_defs/flash +62 -0
- polyfile/magic_defs/flif +36 -0
- polyfile/magic_defs/fonts +449 -0
- polyfile/magic_defs/forth +82 -0
- polyfile/magic_defs/fortran +9 -0
- polyfile/magic_defs/frame +62 -0
- polyfile/magic_defs/freebsd +164 -0
- polyfile/magic_defs/fsav +128 -0
- polyfile/magic_defs/fusecompress +12 -0
- polyfile/magic_defs/games +696 -0
- polyfile/magic_defs/gcc +17 -0
- polyfile/magic_defs/gconv +10 -0
- polyfile/magic_defs/gentoo +85 -0
- polyfile/magic_defs/geo +166 -0
- polyfile/magic_defs/geos +20 -0
- polyfile/magic_defs/gimp +77 -0
- polyfile/magic_defs/git +13 -0
- polyfile/magic_defs/glibc +21 -0
- polyfile/magic_defs/gnome +59 -0
- polyfile/magic_defs/gnu +173 -0
- polyfile/magic_defs/gnumeric +8 -0
- polyfile/magic_defs/gpt +240 -0
- polyfile/magic_defs/gpu +28 -0
- polyfile/magic_defs/grace +21 -0
- polyfile/magic_defs/graphviz +12 -0
- polyfile/magic_defs/gringotts +48 -0
- polyfile/magic_defs/guile +13 -0
- polyfile/magic_defs/hardware +12 -0
- polyfile/magic_defs/hitachi-sh +30 -0
- polyfile/magic_defs/hp +433 -0
- polyfile/magic_defs/human68k +26 -0
- polyfile/magic_defs/ibm370 +52 -0
- polyfile/magic_defs/ibm6000 +35 -0
- polyfile/magic_defs/icc +214 -0
- polyfile/magic_defs/iff +80 -0
- polyfile/magic_defs/images +4210 -0
- polyfile/magic_defs/inform +9 -0
- polyfile/magic_defs/intel +310 -0
- polyfile/magic_defs/interleaf +9 -0
- polyfile/magic_defs/island +10 -0
- polyfile/magic_defs/ispell +63 -0
- polyfile/magic_defs/isz +15 -0
- polyfile/magic_defs/java +52 -0
- polyfile/magic_defs/javascript +171 -0
- polyfile/magic_defs/jpeg +252 -0
- polyfile/magic_defs/json +8 -0
- polyfile/magic_defs/karma +9 -0
- polyfile/magic_defs/kde +11 -0
- polyfile/magic_defs/keepass +20 -0
- polyfile/magic_defs/kerberos +45 -0
- polyfile/magic_defs/kicad +85 -0
- polyfile/magic_defs/kml +34 -0
- polyfile/magic_defs/lammps +64 -0
- polyfile/magic_defs/lecter +6 -0
- polyfile/magic_defs/lex +12 -0
- polyfile/magic_defs/lif +50 -0
- polyfile/magic_defs/linux +557 -0
- polyfile/magic_defs/lisp +78 -0
- polyfile/magic_defs/llvm +22 -0
- polyfile/magic_defs/locoscript +12 -0
- polyfile/magic_defs/lua +31 -0
- polyfile/magic_defs/luks +126 -0
- polyfile/magic_defs/m4 +11 -0
- polyfile/magic_defs/mach +303 -0
- polyfile/magic_defs/macintosh +505 -0
- polyfile/magic_defs/macos +7 -0
- polyfile/magic_defs/magic +10 -0
- polyfile/magic_defs/magic.mgc +0 -0
- polyfile/magic_defs/mail.news +132 -0
- polyfile/magic_defs/make +21 -0
- polyfile/magic_defs/map +413 -0
- polyfile/magic_defs/maple +109 -0
- polyfile/magic_defs/marc21 +30 -0
- polyfile/magic_defs/mathcad +8 -0
- polyfile/magic_defs/mathematica +188 -0
- polyfile/magic_defs/matroska +17 -0
- polyfile/magic_defs/mcrypt +52 -0
- polyfile/magic_defs/measure +44 -0
- polyfile/magic_defs/mercurial +13 -0
- polyfile/magic_defs/metastore +8 -0
- polyfile/magic_defs/meteorological +53 -0
- polyfile/magic_defs/microfocus +21 -0
- polyfile/magic_defs/mime +9 -0
- polyfile/magic_defs/mips +120 -0
- polyfile/magic_defs/mirage +8 -0
- polyfile/magic_defs/misctools +140 -0
- polyfile/magic_defs/mkid +11 -0
- polyfile/magic_defs/mlssa +8 -0
- polyfile/magic_defs/mmdf +6 -0
- polyfile/magic_defs/modem +92 -0
- polyfile/magic_defs/modulefile +9 -0
- polyfile/magic_defs/motorola +71 -0
- polyfile/magic_defs/mozilla +37 -0
- polyfile/magic_defs/msdos +2304 -0
- polyfile/magic_defs/msooxml +68 -0
- polyfile/magic_defs/msvc +222 -0
- polyfile/magic_defs/msx +309 -0
- polyfile/magic_defs/mup +24 -0
- polyfile/magic_defs/music +17 -0
- polyfile/magic_defs/nasa +7 -0
- polyfile/magic_defs/natinst +24 -0
- polyfile/magic_defs/ncr +49 -0
- polyfile/magic_defs/neko +12 -0
- polyfile/magic_defs/netbsd +251 -0
- polyfile/magic_defs/netscape +26 -0
- polyfile/magic_defs/netware +11 -0
- polyfile/magic_defs/news +13 -0
- polyfile/magic_defs/nifty +202 -0
- polyfile/magic_defs/nim-lang +29 -0
- polyfile/magic_defs/nitpicker +14 -0
- polyfile/magic_defs/numpy +9 -0
- polyfile/magic_defs/oasis +12 -0
- polyfile/magic_defs/ocaml +14 -0
- polyfile/magic_defs/octave +6 -0
- polyfile/magic_defs/ole2compounddocs +760 -0
- polyfile/magic_defs/olf +98 -0
- polyfile/magic_defs/openfst +17 -0
- polyfile/magic_defs/opentimestamps +16 -0
- polyfile/magic_defs/oric +16 -0
- polyfile/magic_defs/os2 +186 -0
- polyfile/magic_defs/os400 +39 -0
- polyfile/magic_defs/os9 +80 -0
- polyfile/magic_defs/osf1 +10 -0
- polyfile/magic_defs/palm +156 -0
- polyfile/magic_defs/parix +13 -0
- polyfile/magic_defs/parrot +22 -0
- polyfile/magic_defs/pascal +39 -0
- polyfile/magic_defs/pbf +11 -0
- polyfile/magic_defs/pbm +8 -0
- polyfile/magic_defs/pc88 +24 -0
- polyfile/magic_defs/pc98 +77 -0
- polyfile/magic_defs/pci_ids +116 -0
- polyfile/magic_defs/pcjr +8 -0
- polyfile/magic_defs/pdf +51 -0
- polyfile/magic_defs/pdp +42 -0
- polyfile/magic_defs/perl +100 -0
- polyfile/magic_defs/pgf +52 -0
- polyfile/magic_defs/pgp +581 -0
- polyfile/magic_defs/pgp-binary-keys +388 -0
- polyfile/magic_defs/pkgadd +7 -0
- polyfile/magic_defs/plan9 +25 -0
- polyfile/magic_defs/playdate +57 -0
- polyfile/magic_defs/plus5 +18 -0
- polyfile/magic_defs/pmem +46 -0
- polyfile/magic_defs/polyfile_zip +5 -0
- polyfile/magic_defs/polyml +23 -0
- polyfile/magic_defs/printer +269 -0
- polyfile/magic_defs/project +10 -0
- polyfile/magic_defs/psdbms +14 -0
- polyfile/magic_defs/psl +14 -0
- polyfile/magic_defs/pulsar +13 -0
- polyfile/magic_defs/puzzle +17 -0
- polyfile/magic_defs/pwsafe +14 -0
- polyfile/magic_defs/pyramid +12 -0
- polyfile/magic_defs/python +305 -0
- polyfile/magic_defs/qt +30 -0
- polyfile/magic_defs/revision +66 -0
- polyfile/magic_defs/riff +840 -0
- polyfile/magic_defs/rinex +44 -0
- polyfile/magic_defs/ringdove +45 -0
- polyfile/magic_defs/rpi +52 -0
- polyfile/magic_defs/rpm +45 -0
- polyfile/magic_defs/rpmsg +7 -0
- polyfile/magic_defs/rst +11 -0
- polyfile/magic_defs/rtf +94 -0
- polyfile/magic_defs/ruby +55 -0
- polyfile/magic_defs/rust +21 -0
- polyfile/magic_defs/sc +7 -0
- polyfile/magic_defs/sccs +24 -0
- polyfile/magic_defs/scientific +144 -0
- polyfile/magic_defs/securitycerts +6 -0
- polyfile/magic_defs/selinux +24 -0
- polyfile/magic_defs/sendmail +37 -0
- polyfile/magic_defs/sequent +42 -0
- polyfile/magic_defs/sereal +35 -0
- polyfile/magic_defs/sgi +144 -0
- polyfile/magic_defs/sgml +161 -0
- polyfile/magic_defs/sharc +23 -0
- polyfile/magic_defs/sinclair +40 -0
- polyfile/magic_defs/sisu +18 -0
- polyfile/magic_defs/sketch +6 -0
- polyfile/magic_defs/smalltalk +25 -0
- polyfile/magic_defs/smile +34 -0
- polyfile/magic_defs/sniffer +482 -0
- polyfile/magic_defs/softquad +40 -0
- polyfile/magic_defs/sosi +40 -0
- polyfile/magic_defs/spec +21 -0
- polyfile/magic_defs/spectrum +184 -0
- polyfile/magic_defs/sql +288 -0
- polyfile/magic_defs/ssh +39 -0
- polyfile/magic_defs/ssl +20 -0
- polyfile/magic_defs/statistics +45 -0
- polyfile/magic_defs/subtitle +38 -0
- polyfile/magic_defs/sun +141 -0
- polyfile/magic_defs/svf +5 -0
- polyfile/magic_defs/sylk +36 -0
- polyfile/magic_defs/symbos +42 -0
- polyfile/magic_defs/sysex +429 -0
- polyfile/magic_defs/tcl +29 -0
- polyfile/magic_defs/teapot +6 -0
- polyfile/magic_defs/terminfo +63 -0
- polyfile/magic_defs/tex +141 -0
- polyfile/magic_defs/tgif +7 -0
- polyfile/magic_defs/ti-8x +239 -0
- polyfile/magic_defs/timezone +42 -0
- polyfile/magic_defs/tplink +95 -0
- polyfile/magic_defs/troff +38 -0
- polyfile/magic_defs/tuxedo +8 -0
- polyfile/magic_defs/typeset +8 -0
- polyfile/magic_defs/uf2 +72 -0
- polyfile/magic_defs/unicode +15 -0
- polyfile/magic_defs/unisig +12 -0
- polyfile/magic_defs/unknown +34 -0
- polyfile/magic_defs/usd +21 -0
- polyfile/magic_defs/uterus +16 -0
- polyfile/magic_defs/uuencode +28 -0
- polyfile/magic_defs/vacuum-cleaner +54 -0
- polyfile/magic_defs/varied.out +46 -0
- polyfile/magic_defs/varied.script +21 -0
- polyfile/magic_defs/vax +32 -0
- polyfile/magic_defs/vicar +17 -0
- polyfile/magic_defs/virtual +307 -0
- polyfile/magic_defs/virtutech +12 -0
- polyfile/magic_defs/visx +32 -0
- polyfile/magic_defs/vms +30 -0
- polyfile/magic_defs/vmware +6 -0
- polyfile/magic_defs/vorbis +155 -0
- polyfile/magic_defs/vxl +14 -0
- polyfile/magic_defs/warc +16 -0
- polyfile/magic_defs/weak +16 -0
- polyfile/magic_defs/web +18 -0
- polyfile/magic_defs/webassembly +17 -0
- polyfile/magic_defs/windows +1811 -0
- polyfile/magic_defs/wireless +7 -0
- polyfile/magic_defs/wordprocessors +630 -0
- polyfile/magic_defs/wsdl +23 -0
- polyfile/magic_defs/x68000 +25 -0
- polyfile/magic_defs/xdelta +13 -0
- polyfile/magic_defs/xenix +106 -0
- polyfile/magic_defs/xilinx +58 -0
- polyfile/magic_defs/xo65 +37 -0
- polyfile/magic_defs/xwindows +43 -0
- polyfile/magic_defs/yara +17 -0
- polyfile/magic_defs/zfs +96 -0
- polyfile/magic_defs/zilog +12 -0
- polyfile/magic_defs/zip +126 -0
- polyfile/magic_defs/zyxel +17 -0
- polyfile/nes.py +144 -0
- polyfile/nitf.py +15 -0
- polyfile/pdf.py +1264 -0
- polyfile/pickles.py +45 -0
- polyfile/polyfile.py +409 -0
- polyfile/profiling.py +115 -0
- polyfile/repl.py +624 -0
- polyfile/search.py +310 -0
- polyfile/serialization.py +323 -0
- polyfile/structmatcher.py +46 -0
- polyfile/structs.py +281 -0
- polyfile/templates/download.js +162 -0
- polyfile/templates/hexdump.css +268 -0
- polyfile/templates/hexdump.js +756 -0
- polyfile/templates/jquery-3.4.1.min.js +2 -0
- polyfile/templates/template.html +119 -0
- polyfile/wildcards.py +62 -0
- polyfile/zipmatcher.py +183 -0
- polyfile_weave-0.5.5.dist-info/METADATA +173 -0
- polyfile_weave-0.5.5.dist-info/RECORD +585 -0
- polyfile_weave-0.5.5.dist-info/WHEEL +5 -0
- polyfile_weave-0.5.5.dist-info/entry_points.txt +2 -0
- polyfile_weave-0.5.5.dist-info/licenses/LICENSE +202 -0
- polyfile_weave-0.5.5.dist-info/top_level.txt +2 -0
- polymerge/__init__.py +1 -0
- polymerge/__main__.py +296 -0
- polymerge/cfg.py +127 -0
- polymerge/polymerge.py +227 -0
- polymerge/polytracker.py +190 -0
polyfile/iterators.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from collections.abc import Sequence as AbstractSequence, Set as AbstractSet
|
|
2
|
+
from typing import Generic, TypeVar, Iterable, Iterator, List, Optional, Sequence, Set
|
|
3
|
+
|
|
4
|
+
T = TypeVar("T")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LazyIterableSequence(Generic[T], Sequence[T], AbstractSequence):
|
|
8
|
+
"""A thread-safe list lazily generated from an iterator"""
|
|
9
|
+
def __init__(self, source: Iterable[T]):
|
|
10
|
+
self._source_iter: Optional[Iterator[T]] = iter(source)
|
|
11
|
+
self._items: List[T] = []
|
|
12
|
+
|
|
13
|
+
def _get_next_source_item(self) -> T:
|
|
14
|
+
if self._source_iter is None:
|
|
15
|
+
raise StopIteration()
|
|
16
|
+
return next(self._source_iter)
|
|
17
|
+
|
|
18
|
+
def _complete(self):
|
|
19
|
+
"""Finishes reading all source items from the input iterator"""
|
|
20
|
+
while self._source_iter is not None:
|
|
21
|
+
try:
|
|
22
|
+
_ = self[len(self._items)]
|
|
23
|
+
except IndexError:
|
|
24
|
+
assert self._source_iter is None
|
|
25
|
+
|
|
26
|
+
def __getitem__(self, index: int) -> T:
|
|
27
|
+
while self._source_iter is not None and len(self._items) <= index:
|
|
28
|
+
# we have not yet read enough items
|
|
29
|
+
try:
|
|
30
|
+
self._items.append(next(self._source_iter))
|
|
31
|
+
except StopIteration:
|
|
32
|
+
self._source_iter = None
|
|
33
|
+
break
|
|
34
|
+
return self._items[index]
|
|
35
|
+
|
|
36
|
+
def __len__(self) -> int:
|
|
37
|
+
self._complete()
|
|
38
|
+
return len(self._items)
|
|
39
|
+
|
|
40
|
+
def __iter__(self) -> Iterator[T]:
|
|
41
|
+
i = 0
|
|
42
|
+
while True:
|
|
43
|
+
try:
|
|
44
|
+
yield self[i]
|
|
45
|
+
i += 1
|
|
46
|
+
except IndexError:
|
|
47
|
+
break
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def unique(iterator: Iterator[T], elements: Optional[Set[T]] = None) -> Iterator[T]:
|
|
51
|
+
"""Yields all of the unique elements of the input sequence"""
|
|
52
|
+
if elements is None:
|
|
53
|
+
elements = set()
|
|
54
|
+
for t in iterator:
|
|
55
|
+
if t not in elements:
|
|
56
|
+
yield t
|
|
57
|
+
elements.add(t)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class LazyIterableSet(Generic[T], AbstractSet, LazyIterableSequence[T]):
|
|
61
|
+
"""
|
|
62
|
+
A collection that is both a set and a sequence that
|
|
63
|
+
"""
|
|
64
|
+
def __init__(self, source: Iterable[T]):
|
|
65
|
+
self._set: Set[T] = set()
|
|
66
|
+
super().__init__(unique(iter(source), elements=self._set))
|
|
67
|
+
|
|
68
|
+
def __contains__(self, x: object) -> bool:
|
|
69
|
+
if x in self._set:
|
|
70
|
+
return True
|
|
71
|
+
self._complete()
|
|
72
|
+
return x in self._set
|
polyfile/jpeg.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
from io import BytesIO
|
|
3
|
+
|
|
4
|
+
from .fileutils import FileStream, Tempfile
|
|
5
|
+
from .polyfile import Match, register_parser, Submatch
|
|
6
|
+
|
|
7
|
+
from PIL import Image
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@register_parser("image/jp2")
|
|
11
|
+
def parse_jpeg2000(file_stream: FileStream, parent: Match):
|
|
12
|
+
with Tempfile(file_stream.read(parent.length)) as input_bytes:
|
|
13
|
+
img = Image.open(input_bytes)
|
|
14
|
+
with BytesIO() as img_data:
|
|
15
|
+
img.save(img_data, "PNG")
|
|
16
|
+
b64data = f"data:image/png;base64,{base64.b64encode(img_data).decode('utf-8')}"
|
|
17
|
+
yield Submatch(
|
|
18
|
+
name='ImageData',
|
|
19
|
+
img_data=b64data,
|
|
20
|
+
match_obj="",
|
|
21
|
+
relative_offset=0,
|
|
22
|
+
length=parent.length,
|
|
23
|
+
parent=parent
|
|
24
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
This module automates compilation of Kaitai Struct definitions into Python code.
|
|
5
|
+
|
|
6
|
+
This script is called from PolyFile's setup.py to compile the entire Kaitai Struct format library at build time.
|
|
7
|
+
Therefore, this script should always be self-contained and not require any dependencies other than the Python standard
|
|
8
|
+
library.
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
from io import BytesIO
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
import shutil
|
|
16
|
+
import stat
|
|
17
|
+
import subprocess
|
|
18
|
+
import sys
|
|
19
|
+
from typing import Iterable, List, Optional, Union
|
|
20
|
+
from urllib.request import urlopen
|
|
21
|
+
from zipfile import ZipFile
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if os.name == "nt":
|
|
25
|
+
KAITAI_COMPILER_NAME: str = "kaitai-struct-compiler.bat"
|
|
26
|
+
else:
|
|
27
|
+
KAITAI_COMPILER_NAME = "kaitai-struct-compiler"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
COMPILER_DIR = Path(__file__).absolute().parent / "kaitai-struct-compiler-0.9"
|
|
31
|
+
COMPILER_BIN_DIR = COMPILER_DIR / "bin"
|
|
32
|
+
COMPILER_BIN = COMPILER_BIN_DIR / KAITAI_COMPILER_NAME
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class KaitaiError(RuntimeError):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CompilationError(KaitaiError):
|
|
40
|
+
def __init__(self, ksy_file: str, message: str):
|
|
41
|
+
super().__init__(message)
|
|
42
|
+
self.ksy_file: str = ksy_file
|
|
43
|
+
|
|
44
|
+
def __str__(self):
|
|
45
|
+
return f"{self.ksy_file}: {super().__str__()}"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class CompiledKSY:
|
|
49
|
+
def __init__(self, class_name: str, python_path: Union[str, Path], dependencies: Iterable["CompiledKSY"] = ()):
|
|
50
|
+
self.class_name: str = class_name
|
|
51
|
+
if not isinstance(python_path, Path):
|
|
52
|
+
python_path = Path(python_path)
|
|
53
|
+
self.python_path: Path = python_path
|
|
54
|
+
self.dependencies: List[CompiledKSY] = list(dependencies)
|
|
55
|
+
|
|
56
|
+
def __repr__(self):
|
|
57
|
+
return f"{self.__class__.__name__}(class_name={self.class_name!r}, python_path={self.python_path!r}, "\
|
|
58
|
+
f"dependencies={self.dependencies!r})"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def install_compiler():
|
|
62
|
+
resp = urlopen("https://github.com/kaitai-io/kaitai_struct_compiler/releases/download/0.9/"
|
|
63
|
+
"kaitai-struct-compiler-0.9.zip")
|
|
64
|
+
zipfile = ZipFile(BytesIO(resp.read()))
|
|
65
|
+
COMPILER_DIR.mkdir(exist_ok=True)
|
|
66
|
+
zipfile.extractall(COMPILER_DIR.parent)
|
|
67
|
+
if COMPILER_BIN.exists():
|
|
68
|
+
COMPILER_BIN.chmod(COMPILER_BIN.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
|
69
|
+
sys.stderr.write(f"Installed the Kaitai Struct Compiler to {COMPILER_BIN}\n")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def compiler_path(auto_install: bool = True) -> Optional[Path]:
|
|
73
|
+
if COMPILER_BIN.exists():
|
|
74
|
+
return COMPILER_BIN
|
|
75
|
+
global_path = shutil.which(KAITAI_COMPILER_NAME)
|
|
76
|
+
if global_path is not None:
|
|
77
|
+
return Path(global_path)
|
|
78
|
+
if not auto_install:
|
|
79
|
+
return None
|
|
80
|
+
install_compiler()
|
|
81
|
+
return compiler_path(auto_install=False)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def compile(ksy_path: Union[str, Path], output_directory: Union[str, Path], auto_install: bool = True) -> CompiledKSY:
|
|
85
|
+
"""Returns the list of compiled KSYs; the original spec being first, followed by its dependencies"""
|
|
86
|
+
compiler = compiler_path(auto_install=auto_install)
|
|
87
|
+
if compiler is None:
|
|
88
|
+
raise KaitaiError(f"{KAITAI_COMPILER_NAME} not found! Please make sure it is in your PATH. "
|
|
89
|
+
f"See https://kaitai.io/#download")
|
|
90
|
+
|
|
91
|
+
# sys.stderr.write(f"Using Kaitai Struct Compiler: {compiler!s}\n")
|
|
92
|
+
|
|
93
|
+
if not isinstance(output_directory, Path):
|
|
94
|
+
output_directory = Path(output_directory)
|
|
95
|
+
|
|
96
|
+
output_directory.mkdir(parents=True, exist_ok=True)
|
|
97
|
+
|
|
98
|
+
cmd = [
|
|
99
|
+
str(compiler), "--target", "python", "--outdir", str(output_directory), str(ksy_path),
|
|
100
|
+
"--debug", "--ksc-json-output", "-I", str(Path.cwd()), "--python-package", "polyfile.kaitai.parsers"
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
104
|
+
out, err = proc.communicate()
|
|
105
|
+
if err:
|
|
106
|
+
raise KaitaiError(err.decode("utf-8"))
|
|
107
|
+
elif proc.returncode != 0:
|
|
108
|
+
raise KaitaiError(f"`{' '.join(cmd)}` returned with non-zero exit code {proc.returncode}")
|
|
109
|
+
|
|
110
|
+
result = json.loads(out)
|
|
111
|
+
|
|
112
|
+
if "errors" in result[ksy_path] and result[ksy_path]["errors"]:
|
|
113
|
+
raise KaitaiError(f"Error compiling {ksy_path}: {result[ksy_path]['errors'][0]['message']}")
|
|
114
|
+
|
|
115
|
+
first_spec_name = result[ksy_path]["firstSpecName"]
|
|
116
|
+
first_spec = result[ksy_path]["output"]["python"][first_spec_name]
|
|
117
|
+
if "errors" in first_spec:
|
|
118
|
+
for error in first_spec["errors"]:
|
|
119
|
+
raise CompilationError(ksy_file=error["file"], message=error["message"])
|
|
120
|
+
return CompiledKSY(
|
|
121
|
+
class_name=first_spec["topLevelName"],
|
|
122
|
+
python_path=output_directory / first_spec["files"][0]["fileName"],
|
|
123
|
+
dependencies=(
|
|
124
|
+
CompiledKSY(
|
|
125
|
+
class_name=compiled["topLevelName"],
|
|
126
|
+
python_path=output_directory / compiled["files"][0]["fileName"]
|
|
127
|
+
)
|
|
128
|
+
for spec_name, compiled in result[ksy_path]["output"]["python"].items()
|
|
129
|
+
if spec_name != first_spec_name
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
import argparse
|
|
136
|
+
|
|
137
|
+
if len(sys.argv) == 2 and sys.argv[1] == "--install":
|
|
138
|
+
if compiler_path() is None:
|
|
139
|
+
sys.exit(1)
|
|
140
|
+
else:
|
|
141
|
+
sys.exit(0)
|
|
142
|
+
|
|
143
|
+
parser = argparse.ArgumentParser(description="A Kaitai Struct to Python compiler")
|
|
144
|
+
parser.add_argument("KSY_PATH", type=str, help="path to the Kaitai Struct definition file")
|
|
145
|
+
parser.add_argument("OUTPUT_DIRECTORY", type=str, help="path to which to save the resulting Python")
|
|
146
|
+
|
|
147
|
+
args = parser.parse_args(sys.argv[1:])
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
compiled = compile(args.KSY_PATH, args.OUTPUT_DIRECTORY)
|
|
151
|
+
print(f"{compiled.class_name}\t{compiled.python_path}")
|
|
152
|
+
for dep in compiled.dependencies:
|
|
153
|
+
print(f"{dep.class_name}\t{dep.python_path}")
|
|
154
|
+
except KaitaiError as e:
|
|
155
|
+
sys.stderr.write(f"{e!s}\n\n")
|
|
156
|
+
sys.exit(1)
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from importlib import resources
|
|
5
|
+
import importlib.util
|
|
6
|
+
import inspect
|
|
7
|
+
from io import BufferedReader, BytesIO
|
|
8
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Any, Dict, Iterator, List, Optional, Set, Type, Union
|
|
12
|
+
|
|
13
|
+
from . import parsers
|
|
14
|
+
from .compiler import CompiledKSY
|
|
15
|
+
from ..fileutils import FileStream
|
|
16
|
+
|
|
17
|
+
from kaitaistruct import KaitaiStruct
|
|
18
|
+
|
|
19
|
+
with resources.path(parsers, "manifest.json") as manifest_path:
|
|
20
|
+
PARSER_DIR: Path = manifest_path.parent
|
|
21
|
+
if sys.version_info >= (3, 9):
|
|
22
|
+
with (resources.files(parsers) / "manifest.json").open("r") as f:
|
|
23
|
+
MANIFEST: Dict[str, Dict[str, Any]] = json.load(f)
|
|
24
|
+
else:
|
|
25
|
+
with resources.open_text(parsers, "manifest.json") as f:
|
|
26
|
+
MANIFEST = json.load(f)
|
|
27
|
+
|
|
28
|
+
COMPILED_INFO_BY_KSY: Dict[str, CompiledKSY] = {
|
|
29
|
+
ksy_path: CompiledKSY(
|
|
30
|
+
class_name=component["class_name"],
|
|
31
|
+
python_path=PARSER_DIR / component["python_path"],
|
|
32
|
+
dependencies=(
|
|
33
|
+
CompiledKSY(class_name=dep["class_name"], python_path=PARSER_DIR / dep["python_path"])
|
|
34
|
+
for dep in component["dependencies"]
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
for ksy_path, component in MANIFEST.items()
|
|
38
|
+
}
|
|
39
|
+
del MANIFEST
|
|
40
|
+
|
|
41
|
+
_IMPORTED_SPECS: Set[Path] = set()
|
|
42
|
+
_PARSERS_BY_KSY: Dict[str, Type[KaitaiStruct]] = {}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def import_spec(compiled: CompiledKSY) -> Optional[Type[KaitaiStruct]]:
|
|
46
|
+
if compiled.python_path in _IMPORTED_SPECS:
|
|
47
|
+
return None
|
|
48
|
+
_IMPORTED_SPECS.add(compiled.python_path)
|
|
49
|
+
module_name = compiled.python_path.name
|
|
50
|
+
assert module_name.lower().endswith(".py")
|
|
51
|
+
module_name = module_name[:-3]
|
|
52
|
+
module_name = f"{__name__}.parsers.{module_name}"
|
|
53
|
+
spec = importlib.util.spec_from_file_location(module_name, compiled.python_path)
|
|
54
|
+
module = importlib.util.module_from_spec(spec)
|
|
55
|
+
spec.loader.exec_module(module)
|
|
56
|
+
for objname, obj in inspect.getmembers(module):
|
|
57
|
+
if inspect.isclass(obj) and objname == compiled.class_name:
|
|
58
|
+
return obj
|
|
59
|
+
raise ImportError(f"Could not find parser class {compiled.class_name!r} in {compiled.python_path}")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(unsafe_hash=True, order=True, frozen=True)
|
|
63
|
+
class Segment:
|
|
64
|
+
start: int
|
|
65
|
+
end: int
|
|
66
|
+
|
|
67
|
+
def __contains__(self, item):
|
|
68
|
+
return isinstance(item, Segment) and item.start >= self.start and item.end <= self.end
|
|
69
|
+
|
|
70
|
+
def __len__(self):
|
|
71
|
+
return self.end - self.start
|
|
72
|
+
|
|
73
|
+
def __bool__(self):
|
|
74
|
+
return len(self) > 0
|
|
75
|
+
|
|
76
|
+
def __getitem__(self, index_or_slice: Union[int, slice]):
|
|
77
|
+
if isinstance(index_or_slice, slice):
|
|
78
|
+
if index_or_slice.step is not None and index_or_slice.step != 1:
|
|
79
|
+
raise ValueError(f"{self.__class__.__name__}.__getitem__ only supports slices with step=1")
|
|
80
|
+
if index_or_slice.start is None:
|
|
81
|
+
new_start = self.start
|
|
82
|
+
else:
|
|
83
|
+
new_start = self.start + index_or_slice.start
|
|
84
|
+
if index_or_slice.stop is None:
|
|
85
|
+
new_end = self.end
|
|
86
|
+
elif index_or_slice.stop < 0:
|
|
87
|
+
new_end = self.end + index_or_slice.stop
|
|
88
|
+
else:
|
|
89
|
+
new_end = self.start + index_or_slice.stop
|
|
90
|
+
if new_start > self.end:
|
|
91
|
+
new_start = self.end
|
|
92
|
+
if new_end < new_start or new_end > self.end:
|
|
93
|
+
new_end = new_start
|
|
94
|
+
return Segment(new_start, new_end)
|
|
95
|
+
elif self.start + index_or_slice >= self.end or (index_or_slice < 0 and -index_or_slice > len(self)):
|
|
96
|
+
raise IndexError(index_or_slice)
|
|
97
|
+
elif index_or_slice < 0:
|
|
98
|
+
return Segment(self.end + index_or_slice, self.end + index_or_slice + 1)
|
|
99
|
+
else:
|
|
100
|
+
return Segment(self.start + index_or_slice, self.start + index_or_slice + 1)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class ASTNode:
|
|
104
|
+
"""Represents an element in a parse."""
|
|
105
|
+
|
|
106
|
+
def __init__(
|
|
107
|
+
self,
|
|
108
|
+
name: str,
|
|
109
|
+
segment: Segment,
|
|
110
|
+
offset: int,
|
|
111
|
+
parent: Optional["CompoundNode"] = None
|
|
112
|
+
):
|
|
113
|
+
self.name: str = name
|
|
114
|
+
self.segment: Segment = segment
|
|
115
|
+
self.offset: int = offset
|
|
116
|
+
if parent is None:
|
|
117
|
+
if not isinstance(self, RootNode):
|
|
118
|
+
raise ValueError(f"Only a RootNode can have no parent, not {self!r}")
|
|
119
|
+
self.root: RootNode = self
|
|
120
|
+
self.level: int = 0
|
|
121
|
+
else:
|
|
122
|
+
self.root = parent.root
|
|
123
|
+
self.level = parent.level + 1
|
|
124
|
+
self.parent: Optional[CompoundNode] = parent
|
|
125
|
+
|
|
126
|
+
def dfs(self) -> Iterator["ASTNode"]:
|
|
127
|
+
yield self
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def start(self) -> int:
|
|
131
|
+
return self.offset + self.segment.start
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def end(self) -> int:
|
|
135
|
+
return self.offset + self.segment.end
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def raw_value(self):
|
|
139
|
+
"""Sequence of bytes of this segment."""
|
|
140
|
+
return self.root.get_value(self.start, self.end)
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def size(self) -> int:
|
|
144
|
+
return self.end - self.start
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def children(self) -> List["ASTNode"]:
|
|
148
|
+
return []
|
|
149
|
+
|
|
150
|
+
def __repr__(self):
|
|
151
|
+
return f"{self.name}({self.__class__.__name__}) [{self.start}:{self.end}]"
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class ValueNode(ASTNode):
|
|
155
|
+
"""A leaf in the parse tree."""
|
|
156
|
+
|
|
157
|
+
TYPES = (int, float, str, bytes, Enum)
|
|
158
|
+
|
|
159
|
+
def __init__(self, value: bytes, *args, **kwargs):
|
|
160
|
+
self._value: bytes = value
|
|
161
|
+
super().__init__(*args, **kwargs)
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def value(self) -> bytes:
|
|
165
|
+
return self._value
|
|
166
|
+
|
|
167
|
+
def __repr__(self):
|
|
168
|
+
return f"{self.name}({self.__class__.__name__}<{self.value.__class__.__name__}>) [{self.start}:{self.end}]"
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class CompoundNode(ASTNode, ABC):
|
|
172
|
+
"""A node that can have children"""
|
|
173
|
+
|
|
174
|
+
def __init__(self, obj: KaitaiStruct, *args, **kwargs):
|
|
175
|
+
self.obj: KaitaiStruct = obj
|
|
176
|
+
super().__init__(*args, **kwargs)
|
|
177
|
+
self._children: Optional[List[ASTNode]] = None
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def children(self) -> List[ASTNode]:
|
|
181
|
+
if self._children is None:
|
|
182
|
+
self._children = list(self.explore())
|
|
183
|
+
return self._children
|
|
184
|
+
|
|
185
|
+
@abstractmethod
|
|
186
|
+
def explore(self) -> Iterator[ASTNode]:
|
|
187
|
+
raise NotImplementedError()
|
|
188
|
+
|
|
189
|
+
def dfs(self) -> Iterator[ASTNode]:
|
|
190
|
+
stack = [self]
|
|
191
|
+
while stack:
|
|
192
|
+
top = stack.pop()
|
|
193
|
+
yield top
|
|
194
|
+
stack.extend(reversed(top.children))
|
|
195
|
+
|
|
196
|
+
def make_child(
|
|
197
|
+
self,
|
|
198
|
+
obj: KaitaiStruct,
|
|
199
|
+
name: str,
|
|
200
|
+
segment: Segment,
|
|
201
|
+
offset: int,
|
|
202
|
+
) -> ASTNode:
|
|
203
|
+
if isinstance(obj, KaitaiStruct):
|
|
204
|
+
node_class = StructNode
|
|
205
|
+
elif isinstance(obj, ValueNode.TYPES):
|
|
206
|
+
node_class = ValueNode
|
|
207
|
+
elif isinstance(obj, list):
|
|
208
|
+
node_class = ArrayNode
|
|
209
|
+
else:
|
|
210
|
+
raise TypeError(f"Unknown object type: {type(obj)}")
|
|
211
|
+
|
|
212
|
+
return node_class(obj, name, segment, offset, self)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class StructNode(CompoundNode):
|
|
216
|
+
"""Represents node of the subtype."""
|
|
217
|
+
|
|
218
|
+
def explore(self) -> Iterator[ASTNode]:
|
|
219
|
+
for name in self.obj.SEQ_FIELDS:
|
|
220
|
+
markers = self.obj._debug[name].copy()
|
|
221
|
+
if "arr" in markers:
|
|
222
|
+
del markers["arr"]
|
|
223
|
+
if "start" not in markers or "end" not in markers:
|
|
224
|
+
continue
|
|
225
|
+
segment = Segment(**markers)
|
|
226
|
+
offset = self.offset
|
|
227
|
+
if isinstance(self.parent, StructNode):
|
|
228
|
+
if self.obj._io != self.parent.obj._io:
|
|
229
|
+
offset = self.start
|
|
230
|
+
if hasattr(self.obj, name):
|
|
231
|
+
yield self.make_child(getattr(self.obj, name), name, segment, offset)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class ArrayNode(CompoundNode):
|
|
235
|
+
"""Represents node of array of subtype items."""
|
|
236
|
+
|
|
237
|
+
def explore(self) -> Iterator[ASTNode]:
|
|
238
|
+
for i, obj in enumerate(self.obj):
|
|
239
|
+
markers = self.parent.obj._debug[self.name]["arr"][i]
|
|
240
|
+
segment = Segment(**markers)
|
|
241
|
+
name = f"{self.name}[{i}]"
|
|
242
|
+
yield self.make_child(obj, name, segment, self.offset)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class RootNode(StructNode):
|
|
246
|
+
def __init__(self, buffer: bytes, obj: KaitaiStruct):
|
|
247
|
+
self.buffer: bytes = buffer
|
|
248
|
+
super().__init__(obj, name=obj.__class__.__name__, segment=Segment(0, len(self.buffer)), offset=0)
|
|
249
|
+
|
|
250
|
+
def get_value(self, start, end):
|
|
251
|
+
return self.buffer[start:end]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class KaitaiInspector:
|
|
255
|
+
def __init__(self, struct: KaitaiStruct):
|
|
256
|
+
self.struct: KaitaiStruct = struct
|
|
257
|
+
self._ast: Optional[RootNode] = None
|
|
258
|
+
|
|
259
|
+
@property
|
|
260
|
+
def ast(self) -> RootNode:
|
|
261
|
+
if self._ast is None:
|
|
262
|
+
_io = self.struct._io._io
|
|
263
|
+
if isinstance(_io, FileStream):
|
|
264
|
+
buffer = _io.content
|
|
265
|
+
elif isinstance(_io, BytesIO):
|
|
266
|
+
buffer = _io.getbuffer().tobytes()
|
|
267
|
+
elif isinstance(_io, BufferedReader):
|
|
268
|
+
with open(self.struct._io._io.name, 'rb') as f:
|
|
269
|
+
buffer = f.read()
|
|
270
|
+
else:
|
|
271
|
+
raise TypeError('Unsupported stream type')
|
|
272
|
+
|
|
273
|
+
self._ast = RootNode(buffer, self.struct)
|
|
274
|
+
|
|
275
|
+
return self._ast
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class KaitaiParser:
|
|
279
|
+
def __init__(self, struct_type: Type[KaitaiStruct]):
|
|
280
|
+
self.struct_type: Type[KaitaiStruct] = struct_type
|
|
281
|
+
|
|
282
|
+
@staticmethod
|
|
283
|
+
def load(ksy_path: str) -> "KaitaiParser":
|
|
284
|
+
"""Returns a parser for the given KSY file and input file.
|
|
285
|
+
|
|
286
|
+
The KSY file is specified as a relative path to the file within the Kaitai struct format library.
|
|
287
|
+
Examples:
|
|
288
|
+
|
|
289
|
+
"executable/dos_mz.ksy"
|
|
290
|
+
"image/jpeg.ksy"
|
|
291
|
+
"network/pcap.ksy"
|
|
292
|
+
|
|
293
|
+
"""
|
|
294
|
+
if ksy_path not in _PARSERS_BY_KSY:
|
|
295
|
+
if ksy_path not in COMPILED_INFO_BY_KSY:
|
|
296
|
+
raise KeyError(ksy_path)
|
|
297
|
+
info = COMPILED_INFO_BY_KSY[ksy_path]
|
|
298
|
+
_PARSERS_BY_KSY[ksy_path] = import_spec(info) # type: ignore
|
|
299
|
+
return KaitaiParser(_PARSERS_BY_KSY[ksy_path])
|
|
300
|
+
|
|
301
|
+
def parse(self, input_file_path_or_content: Union[str, Path, bytes, BytesIO]) -> KaitaiInspector:
|
|
302
|
+
if isinstance(input_file_path_or_content, Path):
|
|
303
|
+
input_file_path_or_content = str(input_file_path_or_content)
|
|
304
|
+
if isinstance(input_file_path_or_content, str):
|
|
305
|
+
struct = self.struct_type.from_file(input_file_path_or_content)
|
|
306
|
+
elif isinstance(input_file_path_or_content, bytes):
|
|
307
|
+
struct = self.struct_type.from_bytes(input_file_path_or_content)
|
|
308
|
+
else:
|
|
309
|
+
# Treat it like BytesIO
|
|
310
|
+
struct = self.struct_type.from_io(input_file_path_or_content)
|
|
311
|
+
struct._read()
|
|
312
|
+
return KaitaiInspector(struct)
|
|
File without changes
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
|
2
|
+
|
|
3
|
+
from pkg_resources import parse_version
|
|
4
|
+
import kaitaistruct
|
|
5
|
+
from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
|
|
6
|
+
from enum import Enum
|
|
7
|
+
import collections
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
if parse_version(kaitaistruct.__version__) < parse_version('0.9'):
|
|
11
|
+
raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__))
|
|
12
|
+
|
|
13
|
+
class AixUtmp(KaitaiStruct):
|
|
14
|
+
"""This spec can be used to parse utmp, wtmp and other similar as created by IBM AIX.
|
|
15
|
+
|
|
16
|
+
.. seealso::
|
|
17
|
+
Source - https://www.ibm.com/docs/en/aix/7.1?topic=files-utmph-file
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
class EntryType(Enum):
|
|
21
|
+
empty = 0
|
|
22
|
+
run_lvl = 1
|
|
23
|
+
boot_time = 2
|
|
24
|
+
old_time = 3
|
|
25
|
+
new_time = 4
|
|
26
|
+
init_process = 5
|
|
27
|
+
login_process = 6
|
|
28
|
+
user_process = 7
|
|
29
|
+
dead_process = 8
|
|
30
|
+
accounting = 9
|
|
31
|
+
SEQ_FIELDS = ["records"]
|
|
32
|
+
def __init__(self, _io, _parent=None, _root=None):
|
|
33
|
+
self._io = _io
|
|
34
|
+
self._parent = _parent
|
|
35
|
+
self._root = _root if _root else self
|
|
36
|
+
self._debug = collections.defaultdict(dict)
|
|
37
|
+
|
|
38
|
+
def _read(self):
|
|
39
|
+
self._debug['records']['start'] = self._io.pos()
|
|
40
|
+
self.records = []
|
|
41
|
+
i = 0
|
|
42
|
+
while not self._io.is_eof():
|
|
43
|
+
if not 'arr' in self._debug['records']:
|
|
44
|
+
self._debug['records']['arr'] = []
|
|
45
|
+
self._debug['records']['arr'].append({'start': self._io.pos()})
|
|
46
|
+
_t_records = AixUtmp.Record(self._io, self, self._root)
|
|
47
|
+
_t_records._read()
|
|
48
|
+
self.records.append(_t_records)
|
|
49
|
+
self._debug['records']['arr'][len(self.records) - 1]['end'] = self._io.pos()
|
|
50
|
+
i += 1
|
|
51
|
+
|
|
52
|
+
self._debug['records']['end'] = self._io.pos()
|
|
53
|
+
|
|
54
|
+
class Record(KaitaiStruct):
|
|
55
|
+
SEQ_FIELDS = ["user", "inittab_id", "device", "pid", "type", "timestamp", "exit_status", "hostname", "dbl_word_pad", "reserved_a", "reserved_v"]
|
|
56
|
+
def __init__(self, _io, _parent=None, _root=None):
|
|
57
|
+
self._io = _io
|
|
58
|
+
self._parent = _parent
|
|
59
|
+
self._root = _root if _root else self
|
|
60
|
+
self._debug = collections.defaultdict(dict)
|
|
61
|
+
|
|
62
|
+
def _read(self):
|
|
63
|
+
self._debug['user']['start'] = self._io.pos()
|
|
64
|
+
self.user = (self._io.read_bytes(256)).decode(u"ascii")
|
|
65
|
+
self._debug['user']['end'] = self._io.pos()
|
|
66
|
+
self._debug['inittab_id']['start'] = self._io.pos()
|
|
67
|
+
self.inittab_id = (self._io.read_bytes(14)).decode(u"ascii")
|
|
68
|
+
self._debug['inittab_id']['end'] = self._io.pos()
|
|
69
|
+
self._debug['device']['start'] = self._io.pos()
|
|
70
|
+
self.device = (self._io.read_bytes(64)).decode(u"ascii")
|
|
71
|
+
self._debug['device']['end'] = self._io.pos()
|
|
72
|
+
self._debug['pid']['start'] = self._io.pos()
|
|
73
|
+
self.pid = self._io.read_u8be()
|
|
74
|
+
self._debug['pid']['end'] = self._io.pos()
|
|
75
|
+
self._debug['type']['start'] = self._io.pos()
|
|
76
|
+
self.type = KaitaiStream.resolve_enum(AixUtmp.EntryType, self._io.read_s2be())
|
|
77
|
+
self._debug['type']['end'] = self._io.pos()
|
|
78
|
+
self._debug['timestamp']['start'] = self._io.pos()
|
|
79
|
+
self.timestamp = self._io.read_s8be()
|
|
80
|
+
self._debug['timestamp']['end'] = self._io.pos()
|
|
81
|
+
self._debug['exit_status']['start'] = self._io.pos()
|
|
82
|
+
self.exit_status = AixUtmp.ExitStatus(self._io, self, self._root)
|
|
83
|
+
self.exit_status._read()
|
|
84
|
+
self._debug['exit_status']['end'] = self._io.pos()
|
|
85
|
+
self._debug['hostname']['start'] = self._io.pos()
|
|
86
|
+
self.hostname = (self._io.read_bytes(256)).decode(u"ascii")
|
|
87
|
+
self._debug['hostname']['end'] = self._io.pos()
|
|
88
|
+
self._debug['dbl_word_pad']['start'] = self._io.pos()
|
|
89
|
+
self.dbl_word_pad = self._io.read_s4be()
|
|
90
|
+
self._debug['dbl_word_pad']['end'] = self._io.pos()
|
|
91
|
+
self._debug['reserved_a']['start'] = self._io.pos()
|
|
92
|
+
self.reserved_a = self._io.read_bytes(8)
|
|
93
|
+
self._debug['reserved_a']['end'] = self._io.pos()
|
|
94
|
+
self._debug['reserved_v']['start'] = self._io.pos()
|
|
95
|
+
self.reserved_v = self._io.read_bytes(24)
|
|
96
|
+
self._debug['reserved_v']['end'] = self._io.pos()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class ExitStatus(KaitaiStruct):
|
|
100
|
+
SEQ_FIELDS = ["termination_code", "exit_code"]
|
|
101
|
+
def __init__(self, _io, _parent=None, _root=None):
|
|
102
|
+
self._io = _io
|
|
103
|
+
self._parent = _parent
|
|
104
|
+
self._root = _root if _root else self
|
|
105
|
+
self._debug = collections.defaultdict(dict)
|
|
106
|
+
|
|
107
|
+
def _read(self):
|
|
108
|
+
self._debug['termination_code']['start'] = self._io.pos()
|
|
109
|
+
self.termination_code = self._io.read_s2be()
|
|
110
|
+
self._debug['termination_code']['end'] = self._io.pos()
|
|
111
|
+
self._debug['exit_code']['start'] = self._io.pos()
|
|
112
|
+
self.exit_code = self._io.read_s2be()
|
|
113
|
+
self._debug['exit_code']['end'] = self._io.pos()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|