Initial commit

This commit is contained in:
Joey Pillunat 2025-11-03 20:33:06 +01:00
commit a47ba511c9
12 changed files with 2712 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

884
Cargo.lock generated Normal file
View file

@ -0,0 +1,884 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "cc"
version = "1.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossterm"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [
"bitflags",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "flate2"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "icu_collections"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
dependencies = [
"displaydoc",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_locid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
dependencies = [
"displaydoc",
"litemap",
"tinystr",
"writeable",
"zerovec",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
[[package]]
name = "icu_properties"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
[[package]]
name = "icu_provider"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "idna"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
dependencies = [
"idna_adapter",
"smallvec",
"utf8_iter",
]
[[package]]
name = "idna_adapter"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
dependencies = [
"icu_normalizer",
"icu_properties",
]
[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "litemap"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "miniz_oxide"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "oh5_printer_installer"
version = "1.0.3"
dependencies = [
"crossterm",
"ureq",
"windows",
"winres",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.52.6",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
dependencies = [
"bitflags",
]
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
"getrandom",
"libc",
"untrusted",
"windows-sys 0.52.0",
]
[[package]]
name = "rustls"
version = "0.23.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0"
dependencies = [
"log",
"once_cell",
"ring",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-pki-types"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
[[package]]
name = "rustls-webpki"
version = "0.103.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tinystr"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
dependencies = [
"displaydoc",
"zerovec",
]
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
dependencies = [
"base64",
"flate2",
"log",
"once_cell",
"rustls",
"rustls-pki-types",
"url",
"webpki-roots",
]
[[package]]
name = "url"
version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "webpki-roots"
version = "0.26.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winres"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
dependencies = [
"toml",
]
[[package]]
name = "write16"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "yoke"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zerofrom"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zerovec"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
dependencies = [
"yoke",
"zerofrom",
"zerovec-derive",
]
[[package]]
name = "zerovec-derive"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

20
Cargo.toml Normal file
View file

@ -0,0 +1,20 @@
[package]
name = "oh5_printer_installer"
version = "1.0.3"
edition = "2024"
build = "build.rs"
[build-dependencies]
winres = "0.1"
[dependencies]
crossterm = "0.27"
ureq = "2"
windows = { version = "0.52.0", features = [
"Win32_Foundation",
"Win32_Security",
"Win32_System_Threading",
"Win32_UI_Shell", # ← DAS hier ist wichtig!
"Win32_UI_WindowsAndMessaging" # ← für SW_SHOWNORMAL
]}

18
build.rs Normal file
View file

@ -0,0 +1,18 @@
fn main() {
let mut res = winres::WindowsResource::new();
let version = env!("CARGO_PKG_VERSION");
res.set_icon("favicon.ico");
res.set("FileDescription", "OH5 Drucker Installer");
res.set("ProductName", "OH5 Drucker-Tool");
res.set("CompanyName", "Office Hoch 5 GmbH");
res.set("LegalCopyright", "Copyright © 2025 Office Hoch 5 GmbH");
res.set("OriginalFilename", "OH5 Drucker Installer.exe");
// Version aus Cargo.toml ziehen 👇
res.set("FileVersion", version);
res.set("ProductVersion", version);
res.compile().unwrap();
}

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

313
src/brother.rs Normal file
View file

@ -0,0 +1,313 @@
// brother.rs Brother Color Installer als Rust-Funktion (hybrid mit Command)
use std::fs;
use std::io::Stdout;
use std::process::{Command, exit};
use crate::clear_screen;
use crate::utils::{read_input,pause,set_default_printer_config,set_default_printer_config_mono};
//Color
pub fn brother_color(stdout: &mut Stdout) {
clear_screen(stdout);
println!("Brother Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein (ohne SW/Farbe): ");
let printer_name = printer_name.trim();
let printer_list = [format!("{} (SW)", printer_name), format!("{} (Farbe)", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("brother-treiber");
let zip_path = base_path.join("brother-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let url = "https://oh5.kryptographen.eu/Brother-Treiber.zip";
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("GER").join("BHPCL5E.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"Brother PCLXL Generic Driver",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}
//Color End
//Mono
pub fn brother_mono(stdout: &mut Stdout) {
clear_screen(stdout);
println!("Brother Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein: ");
let printer_name = printer_name.trim();
let printer_list = [format!("{}", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("brother-treiber");
let zip_path = base_path.join("brother-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let url = "https://oh5.kryptographen.eu/Brother-Treiber.zip";
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("GER").join("BHPCL5E.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"Brother PCLXL Generic Driver",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config_mono(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}

313
src/epson.rs Normal file
View file

@ -0,0 +1,313 @@
// epson.rs epson Color Installer als Rust-Funktion (hybrid mit Command)
use std::fs;
use std::io::Stdout;
use std::process::{Command, exit};
use crate::clear_screen;
use crate::utils::{read_input,pause,set_default_printer_config,set_default_printer_config_mono};
//Color
pub fn epson_color(stdout: &mut Stdout) {
clear_screen(stdout);
println!("Epson Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein (ohne SW/Farbe): ");
let printer_name = printer_name.trim();
let printer_list = [format!("{} (SW)", printer_name), format!("{} (Farbe)", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("epson-treiber");
let zip_path = base_path.join("epson-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let url = "https://oh5.kryptographen.eu/Epson-Treiber.zip";
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("Universal_Print_Driver_x64_29000").join("E_JFB0DE.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"EPSON Universal Print Driver",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}
//Color End
//Mono
pub fn epson_mono(stdout: &mut Stdout) {
clear_screen(stdout);
println!("Epson Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein: ");
let printer_name = printer_name.trim();
let printer_list = [format!("{}", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("epson-treiber");
let zip_path = base_path.join("epson-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let url = "https://oh5.kryptographen.eu/Epson-Treiber.zip";
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("Universal_Print_Driver_x64_29000").join("E_JFB0DE.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"EPSON Universal Print Driver",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config_mono(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}

313
src/hp.rs Normal file
View file

@ -0,0 +1,313 @@
// hp.rs HP Color Installer als Rust-Funktion (hybrid mit Command)
use std::fs;
use std::io::Stdout;
use std::process::{Command, exit};
use crate::clear_screen;
use crate::utils::{read_input,pause,set_default_printer_config,set_default_printer_config_mono};
//Color
pub fn hp_color(stdout: &mut Stdout) {
clear_screen(stdout);
println!("HP Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein (ohne SW/Farbe): ");
let printer_name = printer_name.trim();
let printer_list = [format!("{} (SW)", printer_name), format!("{} (Farbe)", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("hp-treiber");
let zip_path = base_path.join("hp-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let url = "https://oh5.kryptographen.eu/HP-Treiber.zip";
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("hpcu315u.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"HP Universal Printing PCL 6",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}
//Color End
//Mono
pub fn hp_mono(stdout: &mut Stdout) {
clear_screen(stdout);
println!("HP Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein: ");
let printer_name = printer_name.trim();
let printer_list = [format!("{}", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("hp-treiber");
let zip_path = base_path.join("hp-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let url = "https://oh5.kryptographen.eu/HP-Treiber.zip";
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("hpcu315u.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"HP Universal Printing PCL 6",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config_mono(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}

231
src/main.rs Normal file
View file

@ -0,0 +1,231 @@
// OH5 Drucker Installer Crossterm Edition mit Debounce und Modifier-Ignore
mod hp;
mod epson;
mod brother;
mod sharp;
mod utils;
mod update;
use crossterm::{ExecutableCommand, event::{self, Event, KeyCode, KeyEventKind}, style::{Color, ResetColor, SetForegroundColor}, terminal};
use std::io::{stdout, Write};
use std::time::Duration;
use utils::{is_running_as_admin, relaunch_as_admin, clear_screen, VERSION};
fn main() {
if !is_running_as_admin() {
println!("Starte mit Admin-Rechten neu...");
relaunch_as_admin();
}
let mut stdout = stdout();
terminal::enable_raw_mode().unwrap();
main_menu(&mut stdout);
terminal::disable_raw_mode().unwrap();
}
fn main_menu(stdout: &mut std::io::Stdout) {
let update_info = update::check_for_update();
loop {
clear_screen(stdout);
println!("╔════════════════════════════════════════════════════════════╗");
print!("");
let _ = stdout.execute(SetForegroundColor(Color::Blue));
let _ = write!(stdout, "OH");
let _ = stdout.execute(SetForegroundColor(Color::Red));
let _ = write!(stdout, "5");
let _ = stdout.execute(ResetColor);
// Text + Version zusammensetzen
let line = format!(" Drucker Installer v{VERSION}");
// Fülle auf 57 Zeichen (weil links 19 schon kamen, insgesamt 76)
let padded = format!("{:<42}", line);
let _ = writeln!(stdout, "{}║", padded);
println!("╠════════════════════════════════════════════════════════════╣");
println!("║ Bitte wähle deine Druckermarke: ║");
println!("║ ║");
println!("║ 1. HP ║");
println!("║ 2. Sharp ║");
println!("║ 3. Utax (Work in Progress) ║");
println!("║ 4. Epson ║");
println!("║ 5. Brother ║");
println!("║ ║");
println!("║ 6. Beenden ║");
//update Edit
if update_info.is_some() {
println!("╠════════════════════════════════════════════════════════════╣");
println!("║ [U] = Update ║");
}
//Closing Box
println!("╚════════════════════════════════════════════════════════════╝");
//Update
if let Some(new_version) = update_info.as_ref() {
let _ = stdout.execute(SetForegroundColor(Color::Red));
let _ = write!(stdout, "Eine neue Version ist verfügbar: ");
let _ = stdout.execute(SetForegroundColor(Color::Green));
let _ = writeln!(stdout, "v{}", new_version);
let _ = stdout.execute(ResetColor);
}
match read_clean_key() {
'1' => hp_menu(stdout),
'2' => sharp_menu(stdout),
'3' => utax_menu(stdout),
'4' => epson_menu(stdout),
'5' => brother_menu(stdout),
'6' => break,
'u' | 'U' => {
if let Some(new_version) = update_info.as_ref() {
update::update_software(stdout, new_version);
pause();
}
}
_ => {}
}
}
}
fn hp_menu(stdout: &mut std::io::Stdout) {
loop {
clear_screen(stdout);
println!("╔════════════════════════════════════════════════════════════╗");
println!("║ HP Drucker Installation ║");
println!("╠════════════════════════════════════════════════════════════╣");
println!("║ 1. Einfache Installation (Color) ║");
println!("║ 2. Einfache Installation (Mono) ║");
println!("║ 3. Zurück ║");
println!("╚════════════════════════════════════════════════════════════╝");
match read_clean_key() {
'1' => hp::hp_color(stdout),
'2' => hp::hp_mono(stdout),
'3' => return,
_ => {}
}
}
}
fn sharp_menu(stdout: &mut std::io::Stdout) {
loop {
clear_screen(stdout);
println!("╔════════════════════════════════════════════════════════════╗");
println!("║ Sharp Drucker Installation ║");
println!("╠════════════════════════════════════════════════════════════╣");
println!("║ 1. Einfache Installation (Color) ║");
println!("║ 2. Einfache Installation (Mono) ║");
println!("║ 3. Zurück ║");
println!("╚════════════════════════════════════════════════════════════╝");
match read_clean_key() {
'1' => sharp::sharp_color(stdout),
'2' => sharp::sharp_mono(stdout),
'3' => return,
_ => {}
}
}
}
fn utax_menu(stdout: &mut std::io::Stdout) {
show_wip(stdout, "Utax Menü (WIP)");
}
fn epson_menu(stdout: &mut std::io::Stdout) {
loop {
clear_screen(stdout);
println!("╔════════════════════════════════════════════════════════════╗");
println!("║ Epson Drucker Installation ║");
println!("╠════════════════════════════════════════════════════════════╣");
println!("║ 1. Einfache Installation (Color) ║");
println!("║ 2. Einfache Installation (Mono) ║");
println!("║ 3. Zurück ║");
println!("╚════════════════════════════════════════════════════════════╝");
match read_clean_key() {
'1' => epson::epson_color(stdout),
'2' => epson::epson_mono(stdout),
'3' => return,
_ => {}
}
}
}
fn brother_menu(stdout: &mut std::io::Stdout) {
loop {
clear_screen(stdout);
println!("╔════════════════════════════════════════════════════════════╗");
println!("║ Brother Drucker Installation ║");
println!("╠════════════════════════════════════════════════════════════╣");
println!("║ 1. Einfache Installation (Color) ║");
println!("║ 2. Einfache Installation (Mono) ║");
println!("║ 3. Zurück ║");
println!("╚════════════════════════════════════════════════════════════╝");
match read_clean_key() {
'1' => brother::brother_color(stdout),
'2' => brother::brother_mono(stdout),
'3' => return,
_ => {}
}
}
}
fn show_wip(stdout: &mut std::io::Stdout, msg: &str) {
clear_screen(stdout);
println!("╔════════════════════════════════════════════════════════════╗");
println!("{:<58}", msg);
println!("╠════════════════════════════════════════════════════════════╣");
println!("║ Diese Option ist noch in Arbeit. ║");
println!("║ Bitte versuche es später erneut. ║");
println!("╚════════════════════════════════════════════════════════════╝");
pause();
}
fn pause() {
println!("\nDrücke eine beliebige Taste, um fortzufahren...");
let _ = read_clean_key();
}
fn read_clean_key() -> char {
loop {
if event::poll(Duration::from_millis(10)).unwrap() {
if let Event::Key(event) = event::read().unwrap() {
if event.kind == KeyEventKind::Press && event.modifiers.is_empty() {
if let KeyCode::Char(c) = event.code {
wait_for_key_release(c); // ← erst loslassen!
return c;
}
}
}
}
}
}
fn wait_for_key_release(target: char) {
use crossterm::event::{poll, read, Event, KeyCode, KeyEventKind};
use std::time::Duration;
loop {
if poll(Duration::from_millis(10)).unwrap() {
if let Event::Key(event) = read().unwrap() {
if event.kind == KeyEventKind::Release {
if let KeyCode::Char(c) = event.code {
if c == target {
break; // erst jetzt darf man neu drücken
}
}
}
}
}
}
}

364
src/sharp.rs Normal file
View file

@ -0,0 +1,364 @@
// sharp.rs Sharp Color Installer als Rust-Funktion (hybrid mit Command)
use std::fs;
use std::io::Stdout;
use std::process::{Command, exit};
use crate::clear_screen;
use crate::utils::{read_input,pause,set_default_printer_config,set_default_printer_config_mono};
//Color
pub fn sharp_color(stdout: &mut Stdout) {
clear_screen(stdout);
println!("Sharp Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// Maschinenart auswählen
println!("Waehle die Maschinenart:");
println!("[1] BP Maschine");
println!("[2] MX Maschine");
let machine_type = read_input("Waehle die Maschinenart (1 oder 2): ");
let machine_type = machine_type.trim();
let (url, machine_name) = match machine_type {
"1" => (
"https://oh5.kryptographen.eu/SharpBP-Treiber.zip",
"BP Maschine"
),
"2" => (
"https://oh5.kryptographen.eu/SharpMX-Treiber.zip",
"MX Maschine"
),
_ => {
println!("Ungueltige Eingabe! Bitte wähle 1 oder 2.");
pause(); // deine eigene pause()-Funktion
return;
}
};
println!("Gewählt: {}", machine_name);
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein (ohne SW/Farbe): ");
let printer_name = printer_name.trim();
let printer_list = [format!("{} (SW)", printer_name), format!("{} (Farbe)", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("sharp-treiber");
let zip_path = base_path.join("sharp-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("PCL6").join("64bit").join("sv0emenu.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"SHARP UD3 PCL6",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}
//Color End
//Mono
pub fn sharp_mono(stdout: &mut Stdout) {
clear_screen(stdout);
println!("Sharp Color Installer gestartet\n");
// Admin-Check überspringen (erst später mit UAC)
// Maschinenart auswählen
println!("Waehle die Maschinenart:");
println!("[1] BP Maschine");
println!("[2] MX Maschine");
let machine_type = read_input("Waehle die Maschinenart (1 oder 2): ");
let machine_type = machine_type.trim();
let (url, machine_name) = match machine_type {
"1" => (
"https://oh5.kryptographen.eu/SharpBP-Treiber.zip",
"BP Maschine"
),
"2" => (
"https://oh5.kryptographen.eu/SharpMX-Treiber.zip",
"MX Maschine"
),
_ => {
println!("Ungueltige Eingabe! Bitte wähle 1 oder 2.");
pause(); // deine eigene pause()-Funktion
return;
}
};
println!("Gewählt: {}", machine_name);
// 1. Eingabe IP & Name
let printer_ip = read_input("Gib die IP-Adresse des Druckers ein: ");
let printer_ip = printer_ip.trim();
let printer_name = read_input("Gib den Namen des Druckers ein: ");
let printer_name = printer_name.trim();
let printer_list = [format!("{}", printer_name)];
// 2. Treiberpfad
let base_path = std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
let driver_path = base_path.join("sharp-treiber");
let zip_path = base_path.join("sharp-treiber.zip");
println!("Verwende automatisch den Treiberordner: {:?}", driver_path);
if !driver_path.exists() {
//Download
println!("Treiber nicht gefunden! Lade ihn herunter...");
let zip_path_str = zip_path.to_str().unwrap();
let ps_command = format!(
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
url, zip_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_command])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Der Treiber konnte nicht heruntergeladen werden!");
pause(); // z.B. deine eigene Funktion
return;
}
//Unzip
let driver_path_str = driver_path.to_str().unwrap();
println!("Entpacke den Treiber...");
let ps_expand = format!(
"Expand-Archive -Path '{}' -DestinationPath '{}' -Force",
zip_path_str, driver_path_str
);
let status = Command::new("powershell")
.args(["-NoProfile", "-Command", &ps_expand])
.status()
.expect("PowerShell konnte nicht ausgeführt werden");
if !status.success() {
println!("❌ Fehler: Das Entpacken ist fehlgeschlagen!");
pause(); // deine eigene Pause-Funktion
return;
}
fs::remove_file(&zip_path).unwrap_or(());
println!("Treiber erfolgreich entpackt.\n");
}
if !driver_path.exists() {
println!("Fehler: Der Treiberordner {:?} existiert nicht!", driver_path);
pause();
return;
}
// 3. Port erstellen
println!("Erstelle TCP/IP-Port...");
let windir = std::env::var("WINDIR").expect("WINDIR nicht gefunden");
let prnport_path = format!(r"{}\System32\Printing_Admin_Scripts\de-DE\prnport.vbs", windir);
let _ = Command::new("cscript")
.args([
&prnport_path,
"-a",
"-r",
printer_ip,
"-h",
printer_ip,
"-o",
"raw",
])
.status();
// 4. Treiber installieren
println!("Installiere Druckertreiber...");
let inf_path = driver_path.join("PCL6").join("64bit").join("sv0emenu.inf");
let _ = Command::new("pnputil")
.args(["/add-driver", inf_path.to_str().unwrap(), "/install"])
.status();
// 5. Drucker installieren
for printer in &printer_list {
println!("Installiere Drucker: {}", printer);
let _ = Command::new("rundll32")
.args([
"printui.dll,PrintUIEntry",
"/if",
"/b",
printer,
"/r",
printer_ip,
"/m",
"SHARP UD3 PCL6",
])
.status();
}
// 6. PowerShell: Standarddruckeinstellungen setzen
set_default_printer_config_mono(printer_name);
let confirm = crate::utils::read_input(&format!(
"Soll '{}' als Standard gesetzt werden? (J/N): ",
printer_list[0]
));
if confirm.trim().eq_ignore_ascii_case("j") {
let _ = Command::new("rundll32")
.args(["printui.dll,PrintUIEntry", "/y", "/n", &printer_list[0]])
.status();
}
// 8. Treiberordner löschen
if driver_path.exists() {
println!("Lösche Treiberordner...");
let _ = fs::remove_dir_all(&driver_path);
}
println!("Installation abgeschlossen.");
pause();
exit(0);
}

103
src/update.rs Normal file
View file

@ -0,0 +1,103 @@
use std::cmp::Ordering;
use std::fs;
use std::io::Write;
use std::env;
use std::io::Read;
use crossterm::{ExecutableCommand, style::{Color, SetForegroundColor, ResetColor}};
use ureq;
use std::thread;
use std::time::Duration;
use std::process::exit;
pub fn check_for_update() -> Option<String> {
let local_version = env!("CARGO_PKG_VERSION");
match fetch_latest_version() {
Ok(remote_version) => {
if compare_versions(local_version, &remote_version) == Ordering::Less {
return Some(remote_version); // Neue Version!
}
}
Err(_) => {} // kein Fehler anzeigen
}
None
}
fn fetch_latest_version() -> Result<String, Box<dyn std::error::Error>> {
let response = ureq::get("https://oh5.kryptographen.eu/Utils/PrintInstaller/latest_version.txt")
.call()?;
if response.status() != 200 {
return Err(format!("HTTP {}", response.status()).into());
}
Ok(response.into_string()?.trim().to_string())
}
fn compare_versions(local: &str, remote: &str) -> Ordering {
let parse = |v: &str| {
v.split('.')
.filter_map(|n| n.parse::<u32>().ok())
.collect::<Vec<_>>()
};
let lv = parse(local);
let rv = parse(remote);
for (l, r) in lv.iter().zip(rv.iter()) {
match l.cmp(r) {
Ordering::Equal => continue,
non_eq => return non_eq,
}
}
lv.len().cmp(&rv.len())
}
pub fn update_software(stdout: &mut std::io::Stdout, version: &str) {
let url = "https://oh5.kryptographen.eu/zTool/OH5%20Install%20Printer.exe";
// Pfad zum aktuellen Verzeichnis der EXE
let exe_dir = env::current_exe()
.expect("Konnte aktuellen Pfad nicht ermitteln")
.parent()
.unwrap()
.to_path_buf();
let filename = format!("OH5 Installer v{}.exe", version);
let target_path = exe_dir.join(&filename);
// Download
let response = match ureq::get(url).call() {
Ok(res) => res,
Err(e) => {
let _ = stdout.execute(SetForegroundColor(Color::Red));
println!("❌ Download fehlgeschlagen: {}", e);
let _ = stdout.execute(ResetColor);
return;
}
};
let mut bytes: Vec<u8> = Vec::new();
if let Err(e) = response.into_reader().read_to_end(&mut bytes) {
let _ = stdout.execute(SetForegroundColor(Color::Red));
println!("❌ Fehler beim Lesen der Datei: {}", e);
let _ = stdout.execute(ResetColor);
return;
}
// Speichern
let mut file = fs::File::create(&target_path).expect("Konnte Datei nicht speichern");
file.write_all(&bytes).expect("Konnte Daten nicht schreiben");
let _ = stdout.execute(SetForegroundColor(Color::Green));
println!("✅ Neue Version wurde gespeichert als '{}'", filename);
let _ = stdout.execute(ResetColor);
println!(); // Leerzeile für Style
println!("⏳ Programm wird in 1 Sekunde beendet...");
thread::sleep(Duration::from_secs(1));
exit(0);
}

152
src/utils.rs Normal file
View file

@ -0,0 +1,152 @@
use crossterm::{ExecutableCommand,cursor,terminal::{Clear, ClearType},terminal::{disable_raw_mode, enable_raw_mode}};
use std::io::{stdin, stdout, Write};
use std::process::Command;
use windows::Win32::Security::{TOKEN_QUERY, TOKEN_ELEVATION, GetTokenInformation, TokenElevation};
use windows::Win32::System::Threading::{GetCurrentProcess, OpenProcessToken};
use windows::Win32::Foundation::{HANDLE,HWND};
use windows::core::PCWSTR;
use windows::Win32::UI::Shell::ShellExecuteW;
use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
//Version
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub fn read_input(prompt: &str) -> String {
disable_raw_mode().unwrap(); // ← raus aus Raw Mode
print!("{}", prompt);
stdout().flush().unwrap();
let mut input = String::new();
stdin().read_line(&mut input).unwrap();
enable_raw_mode().unwrap(); // ← zurück in Raw Mode
input.trim().to_string()
}
pub fn clear_screen(stdout: &mut std::io::Stdout) {
let _ = stdout.execute(Clear(ClearType::All));
let _ = stdout.execute(cursor::MoveTo(0, 0));
}
//config Printer
pub fn set_default_printer_config(printer_name: &str) {
let sw = format!("{} (SW)", printer_name);
let color = format!("{} (Farbe)", printer_name);
println!("Setze Standard-Druckeinstellungen fuer: {} ...", sw);
let _ = Command::new("powershell")
.args([
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command",
&format!(
"Set-PrintConfiguration -PrinterName '{}' -Color $false -DuplexingMode OneSided",
sw
),
])
.status();
println!("Setze Standard-Druckeinstellungen fuer: {} ...", color);
let _ = Command::new("powershell")
.args([
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command",
&format!(
"Set-PrintConfiguration -PrinterName '{}' -DuplexingMode OneSided",
color
),
])
.status();
println!("Fertig! Alle Einstellungen wurden erfolgreich gesetzt.");
}
pub fn set_default_printer_config_mono(printer_name: &str) {
let sw = format!("{}", printer_name);
println!("Setze Standard-Druckeinstellungen fuer: {} ...", sw);
let _ = Command::new("powershell")
.args([
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command",
&format!(
"Set-PrintConfiguration -PrinterName '{}' -DuplexingMode OneSided",
sw
),
])
.status();
println!("Fertig! Alle Einstellungen wurden erfolgreich gesetzt.");
}
//pause bei error
pub fn pause() {
println!("\nDrücke eine beliebige Taste, um fortzufahren...");
let _ = crate::read_clean_key();
}
// Admin Things
pub fn is_running_as_admin() -> bool {
unsafe {
let mut token: HANDLE = HANDLE(0);
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token).is_ok() {
let mut elevation = TOKEN_ELEVATION::default();
let mut size = std::mem::size_of::<TOKEN_ELEVATION>() as u32;
if GetTokenInformation(
token,
TokenElevation,
Some(&mut elevation as *mut _ as *mut std::ffi::c_void),
size,
&mut size,
)
.is_ok()
{
return elevation.TokenIsElevated != 0;
}
}
false
}
}
pub fn relaunch_as_admin() {
let exe_path = std::env::current_exe().unwrap();
let exe: Vec<u16> = OsStr::new(&exe_path)
.encode_wide()
.chain(Some(0))
.collect();
let operation: Vec<u16> = OsStr::new("runas")
.encode_wide()
.chain(Some(0))
.collect();
unsafe {
ShellExecuteW(
HWND(0),
PCWSTR(operation.as_ptr()),
PCWSTR(exe.as_ptr()),
PCWSTR::null(),
PCWSTR::null(),
SW_SHOWNORMAL,
);
}
std::process::exit(0);
}