Compare commits
3 Commits
master
...
toml_confi
Author | SHA1 | Date |
---|---|---|
|
d833c2a76a | |
|
87231e227f | |
|
2bdeef98c1 |
|
@ -1 +1,3 @@
|
|||
/target
|
||||
config.toml
|
||||
*.html
|
|
@ -15,9 +15,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
|
@ -33,9 +33,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.8.0"
|
||||
version = "3.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
||||
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
|
@ -45,9 +45,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.71"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -86,10 +86,21 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.2"
|
||||
name = "colored"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"
|
||||
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"lazy_static",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
@ -103,13 +114,22 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
|||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.29"
|
||||
version = "0.8.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746"
|
||||
checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -143,44 +163,43 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.17"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
|
||||
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.17"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
|
||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.17"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
|
||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.17"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
|
||||
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.17"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
|
||||
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.17"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
|
||||
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-task",
|
||||
|
@ -190,22 +209,11 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.6"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c06815895acec637cd6ed6e9662c935b866d20a106f8361892893a7d9234964"
|
||||
checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -243,9 +251,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
|
||||
checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -254,9 +262,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5"
|
||||
checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
|
@ -265,21 +273,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.5.1"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
|
||||
checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
|
||||
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.13"
|
||||
version = "0.14.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593"
|
||||
checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
|
@ -325,40 +333,53 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.3.1"
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c"
|
||||
|
||||
[[package]]
|
||||
name = "iserv-ipad-helper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"colored",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.55"
|
||||
version = "0.3.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
|
||||
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -371,9 +392,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.104"
|
||||
version = "0.2.121"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce"
|
||||
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -404,14 +425,15 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
|||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.14"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
|
||||
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -444,18 +466,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
|
||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
|
@ -463,15 +485,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.36"
|
||||
version = "0.10.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a"
|
||||
checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
|
@ -483,15 +505,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.67"
|
||||
version = "0.9.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058"
|
||||
checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
|
@ -517,9 +539,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
|||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
|
||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
|
@ -529,15 +551,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
|||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.20"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
|
||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
|
@ -565,67 +581,27 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.30"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.10"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
checksum = "b4af2ec4714533fcdf07e886f17025ace8b997b9ce51204ee69b6da831c3da57"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.10"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
||||
checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
@ -641,15 +617,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.6"
|
||||
version = "0.11.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280"
|
||||
checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
|
@ -676,9 +653,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
|
@ -692,9 +669,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.4.2"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87"
|
||||
checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
|
@ -705,9 +682,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.4.2"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e"
|
||||
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
@ -715,15 +692,26 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
version = "1.0.136"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.136"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.68"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -732,9 +720,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa",
|
||||
|
@ -750,9 +738,9 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
|||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
|
||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
|
@ -766,9 +754,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.80"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
||||
checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -777,13 +765,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.2.0"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
|
@ -806,9 +794,9 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
|||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7"
|
||||
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
@ -821,17 +809,17 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.12.0"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc"
|
||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -847,9 +835,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.6.8"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd"
|
||||
checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
@ -859,6 +847,15 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.1"
|
||||
|
@ -867,9 +864,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
|||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.29"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
|
||||
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
|
@ -878,9 +875,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.21"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
|
||||
checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
@ -948,15 +945,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
|
||||
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -964,9 +961,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
|
||||
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
|
@ -979,9 +976,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.28"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39"
|
||||
checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
|
@ -991,9 +988,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
|
||||
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -1001,9 +998,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
|
||||
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1014,15 +1011,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
|
||||
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.55"
|
||||
version = "0.3.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
|
||||
checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
@ -1061,9 +1058,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.7.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
|
||||
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
|
|
@ -8,4 +8,8 @@ edition = "2021"
|
|||
[dependencies]
|
||||
reqwest = { version = "0.11", features = ["blocking", "json"] }
|
||||
clap = { version = "3.1.6", features = ["derive"] }
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
toml = "0.5"
|
||||
colored = "2.0.0"
|
|
@ -0,0 +1,27 @@
|
|||
# IServ-iPad-Helper
|
||||
|
||||
## Introduction
|
||||
|
||||
The IServ-iPad-Helper makes your admin life easier by automating device creation and compilation assignment for Apple iPads (and perhaps other Apple devices). You just have to connect the iDevices to a lightning ethernet dongle and don't have to touch you computer, allowing you to focus on following the onscreen instructions required by the iPads. This can save you a lot of time when setting up iPads in bulk.
|
||||
|
||||
## Motivation
|
||||
|
||||
My main motivation for writing this program was that IServ currently lacks the functionality of automating iDevice enrollment; all steps have to performed manually through the web interface and you often face long wait times, when a database modification is performed. This quickly gets tedious, especially because the mdm and the general device management are decoupled from another, requiring you to jump back and forth between the two.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Your iPads automatically receive an ip address with unrestricted internet access through a lightning wired ethernet adapter (note that this temporary ip address is overridden once the device is created)
|
||||
- You have a device filter that only returns devices you want to be edited and added to the compilation (usually "empty room" and keyword search for "iPad" should suffice)
|
||||
|
||||
<!-- TODO: Think of more prerequisites -->
|
||||
|
||||
## Workflow
|
||||
|
||||
0. Continously the server is queried for devices matching the specified device filter.
|
||||
1. Once a device has been activated through Apple's servers, a device is added by the IServ mdm. This program detects the new device and assigns the next available ip address that was suggested, as well as a room to the device.
|
||||
2. The device is added to the compilation (most likely you want a compilation that includes a WiFi profile)
|
||||
3. The proposed mdm changes are confirmed
|
||||
|
||||
## Disclaimer
|
||||
|
||||
While I can confirm that the program was fully working the last time I used it, I cannot guarantee that changes to IServ in the future will not break this program in the future or cause unintended side effects. Since IServ sadly does not provide a proper versioned API the only way to achieve this kind of functionality is through programatically using the same human-centered web GUI you would've used for the task. Further, the barebone HTML parsing employed is sensitive to change, because it merely looks for hard-coded strings in the response (proper XML parsing seemed overkill for this simple task and would require more work). Lastly, you should be aware that this program does not come with warranty and that you are responsible for your actions and any damage sustained.
|
|
@ -0,0 +1,15 @@
|
|||
#General settings
|
||||
hostname = "mein-iserv.de"
|
||||
cookie = "IServSAT=mvuvFvCZSlpvuwhk0mmNwF1NKEQypM4d; IServSession=xEPqyJO1a5nsVd34HEpbPqQGMMQKapvw"
|
||||
|
||||
# Targeted device settings
|
||||
host_ip = "10.1.1.1"
|
||||
host_room = 123
|
||||
mdm_compilation = 1
|
||||
|
||||
|
||||
[host_filter]
|
||||
"filter[controllable]" = ""
|
||||
"filter[room][]" = "__none"
|
||||
"filter[group]" = ""
|
||||
"filter[search]" = "iPad"
|
338
src/main.rs
338
src/main.rs
|
@ -1,136 +1,249 @@
|
|||
use std::borrow::Cow;
|
||||
use std::{collections::HashMap, borrow::Cow};
|
||||
use clap::Parser;
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[clap(short, long)]
|
||||
use serde_derive::Deserialize;
|
||||
use colored::Colorize;
|
||||
|
||||
macro_rules! args_or_config {
|
||||
($(#[$($attr: tt)*] $val: ident: $t: ty),* |optional: $(#[$($attr_opt: tt)*] $val_opt: ident: $t_opt: ty),*) => {
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version)]
|
||||
struct ClapArgs {
|
||||
$(
|
||||
#[$($attr)*]
|
||||
$val: Option<$t>,
|
||||
)*
|
||||
$(
|
||||
#[$($attr_opt)*]
|
||||
$val_opt: Option<$t_opt>,
|
||||
)*
|
||||
#[clap(help("Host filter used for finding newly added devices in the device management. The host filter can be retrieved by performing a search in the device admin section and copying the query from the url. On the command line each filters key and value are seperated by a colon."))]
|
||||
host_filter: Vec<String>
|
||||
}
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct TomlArgs {
|
||||
$( $val: Option<$t>, )*
|
||||
$( $val_opt: Option<$t_opt>, )*
|
||||
host_filter: HashMap<String, String>
|
||||
}
|
||||
|
||||
impl ClapArgs {
|
||||
fn combine(self, toml: &str) -> Config {
|
||||
let toml: TomlArgs = toml::from_str(toml).expect("Invalid config");
|
||||
|
||||
Config {
|
||||
$(
|
||||
$val: self.$val.unwrap_or_else(||
|
||||
toml.$val.unwrap_or_else(|| {
|
||||
eprintln!("{}{}{}{}{}{}",
|
||||
"Missing config value for".bright_red(),
|
||||
" '",
|
||||
stringify!($val).cyan(),
|
||||
"'",
|
||||
"\nHINT: ".green(),
|
||||
"Specify it either in the config.toml or as an argument.".yellow()
|
||||
);
|
||||
std::process::exit(187);
|
||||
})
|
||||
),
|
||||
)*
|
||||
$( $val_opt: self.$val_opt.or(toml.$val_opt), )*
|
||||
host_filter: self.host_filter.into_iter()
|
||||
.map(|s| {
|
||||
let (l, r) = s.split_once(':').expect("Params need ':' between key and value");
|
||||
(l.to_owned(), r.to_owned())
|
||||
})
|
||||
.chain(toml.host_filter)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Config {
|
||||
$( $val: $t, )*
|
||||
$( $val_opt: Option<$t_opt>, )*
|
||||
host_filter: HashMap<String, String>
|
||||
}
|
||||
impl Config {
|
||||
fn parse(toml: &str) -> Self {
|
||||
ClapArgs::parse().combine(toml)
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
args_or_config! {
|
||||
#[clap(short('H'), long, help("Hostname where the IServ shall be reached at"))]
|
||||
hostname: String,
|
||||
//example: "IServSAT=mvuvFvCZSlpvuwhk0mmNwF1NKEQypM4d; IServSession=xEPqyJO1a5nsVd34HEpbPqQGMMQKapvw; nav-show-additional-modules=true; PHPSESSID=mchbrl11epjnnp851q0i4rt8rc"
|
||||
#[clap(short, long)]
|
||||
session_cookie: String,
|
||||
#[clap(long)]
|
||||
target_ip: String,
|
||||
#[clap(long)]
|
||||
target_room: u16,
|
||||
#[clap(long)]
|
||||
target_compilation: Option<u16>,
|
||||
#[clap(short, long, help("Cookie used for authentication. 'IServSAT' and 'IServSession' are required. HINT: You can retrieve the cookie data by using the developer tools of your browser."))]
|
||||
cookie: String,
|
||||
#[clap(long, help("Preferred ip address for the newly added device. If the preferred ip address is already used, the next available ip address is used instead."))]
|
||||
host_ip: String,
|
||||
#[clap(long, help("Numerical room id the newly added device should be assigned to. HINT: The id can be found at the end of the url when inspecting a room in the room admin section."))]
|
||||
host_room: u16,
|
||||
#[clap(long, help("Amount of time in seconds to wait for the next retry."))]
|
||||
retry_delay: u64
|
||||
|
||||
|optional:
|
||||
|
||||
#[clap(long, help("Numerical compilation id the newly added device should be assigned to. HINT: The id can be found at the end of the url when inspecting a compilation in the mdm admin section. If this is not specified, the new device will not be added to a collection."))]
|
||||
mdm_compilation: u16
|
||||
}
|
||||
|
||||
macro_rules! print_banner {
|
||||
($f: expr, $($arg: expr),*) => {
|
||||
println!(concat!("-----------------------------------\n", $f, "\n-----------------------------------"), $($arg),*)
|
||||
println!(concat!(
|
||||
"----------------------------------------\n",
|
||||
$f,
|
||||
"\n----------------------------------------"
|
||||
), $($arg),*)
|
||||
};
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args = Args::parse();
|
||||
loop { ipad(&args)?; }
|
||||
let args = Config::parse(&std::fs::read_to_string("config.toml").unwrap_or(String::new()));
|
||||
loop { main_loop(&args)?; }
|
||||
}
|
||||
|
||||
fn ipad(args: &Args) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let params = [
|
||||
("filter[controllable]", ""),
|
||||
("filter[room][]", "__none"),
|
||||
("filter[group]", ""),
|
||||
("filter[search]", "iPad"),
|
||||
];
|
||||
let header = ("Cookie", &args.session_cookie);
|
||||
fn main_loop(args: &Config) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let header = ("Cookie", &args.cookie);
|
||||
let client = reqwest::blocking::Client::new();
|
||||
let resp = client
|
||||
.get(format!("https://{}/iserv/admin/hosts", args.hostname))
|
||||
.header(header.0, header.1)
|
||||
.query(¶ms)
|
||||
.query(&args.host_filter)
|
||||
.send()?;
|
||||
let status = &resp.status();
|
||||
let plain = &resp.text()?;
|
||||
|
||||
if plain.contains("class=\"login-form\"") {
|
||||
eprintln!("ERR: Failed to authorize. Server forwarded to login site. HINT: Check the provided cookie.");
|
||||
std::process::exit(187);
|
||||
}
|
||||
|
||||
if status.is_client_error() || status.is_server_error() {
|
||||
eprintln!("ERR: Received error status (status code: {:?})", status);
|
||||
std::process::exit(187);
|
||||
}
|
||||
|
||||
let content = squeeze(
|
||||
&plain,
|
||||
"<script id=\"crud-data\" type=\"application/json\">",
|
||||
"</script>",
|
||||
);
|
||||
let json: serde_json::Value = serde_json::from_str(content).expect("Bad Jason!");
|
||||
let json: serde_json::Value = serde_json::from_str(content).expect("ERR: Failed to parse JSON data. This may be because the server did not return valid JSON data to parse.");
|
||||
let json_part = &json["data"][0]["name"]["rendered"]
|
||||
.to_string()
|
||||
.replace("\\", "");
|
||||
// skip rest of loop when no entry appeared
|
||||
|
||||
if json_part == "null" {
|
||||
println!(
|
||||
"###################################
|
||||
No new host: skipping (Retry in 5s)
|
||||
###################################
|
||||
");
|
||||
//sleep for 5 seconds
|
||||
"########################################
|
||||
No new host: skipping (Retry in {}s)
|
||||
########################################
|
||||
", &args.retry_delay);
|
||||
std::thread::sleep(std::time::Duration::from_secs(5));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let host_id = squeeze(json_part, "data-host-id=\"", "\"");
|
||||
let device_name = squeeze(json_part, "</span>", "</a>");
|
||||
print_banner!("1/8 Found host\nHost id: {}\nDevice name: {}\nReceived response status: {:?}", host_id, device_name, status);
|
||||
|
||||
let dest = format!("https://{}/iserv/admin/host/edit/{}", args.hostname, &host_id);
|
||||
let resp = client.get(&dest).header(header.0, header.1).send()?;
|
||||
//TODO Check for non 200 response
|
||||
let status = &resp.status();
|
||||
if !status.is_success() && *status != 300 {
|
||||
eprintln!("WARN: Found invalid Status Code: {status}");
|
||||
if !status.is_success() {
|
||||
eprintln!("{}, {}", "WARN: Found invalid Status Code: ".bright_yellow(), status);
|
||||
return Ok(())
|
||||
}
|
||||
let plain = &resp.text()?;
|
||||
let mut form_ip: &str = &args.target_ip; //default
|
||||
let form_name = squeeze_html_form(plain, "name=\"host[name]\"", "value=\"", "\"");
|
||||
let form_tags = squeeze_html_form(plain, "name=\"host[tags][]\"", "value=\"", "\"");
|
||||
let form_mac = squeeze_html_form(plain, "name=\"host[mac]\"", "value=\"", "\"");
|
||||
let form_description = squeeze_html_form(plain, "name=\"host[description]\"", ">", "<");
|
||||
let form_token = squeeze_html_form(plain, "name=\"host[_token]\"", "value=\"", "\"");
|
||||
let mut form_data = [
|
||||
("host[name]", form_name),
|
||||
("host[tags][]", form_tags),
|
||||
("host[room]", &args.target_room.to_string()),
|
||||
("host[ip]", &form_ip),
|
||||
("host[mac]", form_mac),
|
||||
("host[internet]", "1"),
|
||||
("host[proxyEnforce]", "0"),
|
||||
("host[owner]", ""),
|
||||
("host[controllable]", "0"),
|
||||
("host[inventoryNumber]", ""),
|
||||
("host[shutdown]", ""),
|
||||
("host[description]", form_description),
|
||||
("host[image][id]", ""),
|
||||
("host[image][x]", ""),
|
||||
("host[image][y]", ""),
|
||||
("host[actions][submit]", ""),
|
||||
("host[_token]", form_token),
|
||||
];
|
||||
let mut form_ip: &str = &args.host_ip;
|
||||
let mut form_ip_index = 2;
|
||||
let form_name = squeeze_html_form(plain, "name=\"host[name]\"", ">", "value=\"", "\"");
|
||||
let plain_inner_tags = squeeze(plain, "name=\"host[tags][]\"", "</select>");
|
||||
let mut form_tags = Vec::new();
|
||||
squeeze_loop(&mut form_tags, plain_inner_tags, "<option value=\"", "\"", " selected=\"selected\"", 3, "host[tags][]");
|
||||
|
||||
let form_mac = squeeze_html_form(plain, "name=\"host[mac]\"", ">", "value=\"", "\"");
|
||||
let form_description = squeeze_html_form(plain, "name=\"host[description]\"", "/textarea>", ">", "<");
|
||||
let form_token = squeeze_html_form(plain, "name=\"host[_token]\"", ">", "value=\"", "\"");
|
||||
let mut form_data = Vec::from([
|
||||
("host[name]",form_name),
|
||||
].map(|(a, b)| (Cow::Borrowed(a), Cow::Borrowed(b))));
|
||||
|
||||
// empty tag fields are not permitted
|
||||
if !(form_tags.is_empty()) {
|
||||
form_ip_index += form_tags.len();
|
||||
form_data.extend(form_tags);
|
||||
}
|
||||
|
||||
let host_room: &str = &args.host_room.to_string();
|
||||
form_data.extend([
|
||||
("host[room]", host_room),
|
||||
("host[ip]", form_ip),
|
||||
("host[mac]", form_mac),
|
||||
("host[internet]", "1"),
|
||||
("host[proxyEnforce]", "0"),
|
||||
("host[owner]", ""),
|
||||
("host[controllable]", "0"),
|
||||
("host[inventoryNumber]", ""),
|
||||
("host[shutdown]", ""),
|
||||
("host[description]", form_description),
|
||||
("host[image][id]", ""),
|
||||
("host[image][x]", ""),
|
||||
("host[image][y]", ""),
|
||||
("host[actions][submit]", ""),
|
||||
("host[_token]", form_token),
|
||||
].map(|(a, b)| (Cow::Borrowed(a), Cow::Borrowed(b))));
|
||||
|
||||
print_banner!("2/8 Received current host properties\nReceived response status: {:?}", status);
|
||||
|
||||
println!("{:#?}", form_data);
|
||||
let resp = client
|
||||
.post(&dest)
|
||||
.header(header.0, header.1)
|
||||
.form(&form_data)
|
||||
.send()?;
|
||||
let status = &resp.status();
|
||||
if !status.is_success() {
|
||||
eprintln!("{}, {}", "WARN: Found invalid Status Code: ".bright_yellow(), status);
|
||||
return Ok(())
|
||||
}
|
||||
let plain = &resp.text()?;
|
||||
form_ip = squeeze_html_form(plain, "name=\"host[ip]\"", "value=\"", "\"");
|
||||
form_data[3] = ("host[ip]", form_ip);
|
||||
print_banner!("3/8 Received recommended ip: {}\nReceived response status: {:?}", form_ip, status);
|
||||
|
||||
|
||||
if !plain.contains("<form name=\"host\"") {
|
||||
print_banner!("3/8 The configured ip was accepted {}\nReceived response status: {:?}", form_ip, status);
|
||||
print_banner!("{}", "4/8 Ip address resubmission was skipped");
|
||||
} else {
|
||||
// retrieve next available ip address from sent form
|
||||
form_ip = squeeze_html_form(plain, "name=\"host[ip]\"", ">", "value=\"", "\"");
|
||||
form_data[form_ip_index] = ("host[ip]".into(), form_ip.into());
|
||||
print_banner!("3/8 Received recommended ip: {}\nReceived response status: {:?}", form_ip, status);
|
||||
|
||||
let resp = client
|
||||
.post(&dest)
|
||||
.header(header.0, header.1)
|
||||
.form(&form_data)
|
||||
.send()?;
|
||||
let status = &resp.status();
|
||||
print_banner!("4/8 Sucessfully updated host\nReceived response status: {:?}", status);
|
||||
}
|
||||
|
||||
let target_compilation = if let Some(t) = args.mdm_compilation { t } else { return Ok(()) };
|
||||
|
||||
let resp = client
|
||||
.post(&dest)
|
||||
.get(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, target_compilation))
|
||||
.header(header.0, header.1)
|
||||
.form(&form_data)
|
||||
.send()?;
|
||||
let status = &resp.status();
|
||||
print_banner!("4/8 Sucessfully updated host\nReceived response status: {:?}", status);
|
||||
|
||||
if args.target_compilation.is_none() { return Ok(()) }
|
||||
|
||||
let resp = client
|
||||
.get(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap()))
|
||||
.header(header.0, header.1)
|
||||
.send()?;
|
||||
//TODO Check for non 200 response
|
||||
|
||||
let status = &resp.status();
|
||||
if !status.is_success() {
|
||||
eprintln!("{}, {}", "WARN: Found invalid Status Code: ".bright_yellow(), status);
|
||||
return Ok(())
|
||||
}
|
||||
let plain = &resp.text()?;
|
||||
|
||||
print_banner!("5/8 Received MDM compilation\nReceived response status: {:?}", status);
|
||||
|
@ -138,62 +251,72 @@ No new host: skipping (Retry in 5s)
|
|||
let mut form_data = Vec::from([
|
||||
(
|
||||
"ioscompilation[name]",
|
||||
squeeze_html_form(plain, "name=\"ioscompilation[name]\"", "value=\"", "\"")
|
||||
squeeze_html_form(plain, "name=\"ioscompilation[name]\"", ">", "value=\"", "\"")
|
||||
),
|
||||
(
|
||||
"ioscompilation[description]",
|
||||
squeeze_html_form(plain, "name=\"ioscompilation[description]\"", "value=\"", "\"")
|
||||
squeeze_html_form(plain, "name=\"ioscompilation[description]\"", ">", "value=\"", "\"")
|
||||
),
|
||||
].map(|(a, b)| (Cow::Borrowed(a), Cow::Borrowed(b))));
|
||||
|
||||
// push apps (<option value="52" selected="selected">)
|
||||
let plain_inner_applications = squeeze_html_form(plain, "name=\"ioscompilation[applications][]\"", ">", "</select>");
|
||||
// push apps
|
||||
let plain_inner_applications = squeeze(plain, "name=\"ioscompilation[applications][]\"", "</select>");
|
||||
squeeze_loop(&mut form_data, plain_inner_applications, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[applications][]");
|
||||
|
||||
// push profiles
|
||||
let plain_inner_profiles = squeeze_html_form(plain, "name=\"ioscompilation[profiles][]\"", ">", "</select>");
|
||||
let plain_inner_profiles = squeeze(plain, "name=\"ioscompilation[profiles][]\"", "</select>");
|
||||
squeeze_loop(&mut form_data, plain_inner_profiles, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[profiles][]");
|
||||
|
||||
// push existing devices ([\s\n]* seems not needed)
|
||||
let plain_inner_devices = squeeze_html_form(plain, "name=\"ioscompilation[devices][]\"", ">", "</select>");
|
||||
squeeze_loop(&mut form_data, plain_inner_devices, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[devices][]");
|
||||
// push existing devices
|
||||
let plain_inner_devices = squeeze(plain, "name=\"ioscompilation[devices][]\"", "</select>");
|
||||
squeeze_loop(&mut form_data, plain_inner_devices, "<option value=\"", "\"", " selected=\"", 3, "ioscompilation[devices][]");
|
||||
|
||||
// push new device
|
||||
let mdm_new_ipad_id = squeeze_right(plain_inner_devices, "<option value=\"", &format!("\">{}", form_name));
|
||||
let mdm_new_idevice_id = squeeze_right(plain_inner_devices, "<option value=\"", &format!("\">{}", form_name));
|
||||
if plain_inner_devices.contains(form_name) {
|
||||
form_data.push(("ioscompilation[devices][]".into(), mdm_new_ipad_id.into()));
|
||||
form_data.push(("ioscompilation[devices][]".into(), mdm_new_idevice_id.into()));
|
||||
} else {
|
||||
eprintln!("Device not found in compilation edit.")
|
||||
eprintln!("{}", "WARN: Device not found in compilation form.\nSkipping compilation edit...".bright_yellow());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// push submit action
|
||||
form_data.push(("ioscompilation[actions][submit]".into(), "".into()));
|
||||
|
||||
//push token
|
||||
let form_token = squeeze_html_form(plain, "name=\"ioscompilation[_token]\"", "value=\"", "\"");
|
||||
let form_token = squeeze_html_form(plain, "name=\"ioscompilation[_token]\"", ">", "value=\"", "\"");
|
||||
form_data.push(("ioscompilation[_token]".into(), form_token.into()));
|
||||
let resp = client
|
||||
.post(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap()))
|
||||
.post(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.mdm_compilation.unwrap()))
|
||||
.header(header.0, header.1)
|
||||
.form(&form_data)
|
||||
.send()?;
|
||||
|
||||
let status = &resp.status();
|
||||
if !status.is_success() {
|
||||
eprintln!("{}, {}", "WARN: Found invalid Status Code: ".bright_yellow(), status);
|
||||
return Ok(())
|
||||
}
|
||||
print_banner!("6/8 Added device to MDM Compilation\nReceived response status: {:?}", status);
|
||||
|
||||
let resp = client
|
||||
.get(format!("https://{}/iserv/admin/mdm/ios/device", args.hostname))
|
||||
.header(header.0, header.1)
|
||||
.send()?;
|
||||
.get(format!("https://{}/iserv/admin/mdm/ios/device", args.hostname))
|
||||
.header(header.0, header.1)
|
||||
.send()?;
|
||||
|
||||
let status = &resp.status();
|
||||
if !status.is_success() {
|
||||
eprintln!("{}, {}", "WARN: Found invalid Status Code: ".bright_yellow(), status);
|
||||
return Ok(())
|
||||
}
|
||||
let plain = &resp.text()?;
|
||||
let csrf_token = squeeze_html_form(plain, "name=\"iserv_crud_multi_select[_token]\"", "value=\"", "\"");
|
||||
let csrf_token = squeeze_html_form(plain, "name=\"iserv_crud_multi_select[_token]\"", ">", "value=\"", "\"");
|
||||
|
||||
print_banner!("7/8 Retrieved CSRF token\nReceived response status: {:?}", status);
|
||||
|
||||
let form_data = [
|
||||
("iserv_crud_multi_select[confirm]", "apply-changes"),
|
||||
("iserv_crud_multi_select[multi][]", mdm_new_ipad_id),
|
||||
("iserv_crud_multi_select[multi][]", mdm_new_idevice_id),
|
||||
("iserv_crud_multi_select[topReplacementActions][apply-changes]", ""),
|
||||
("iserv_crud_multi_select[_token]", csrf_token),
|
||||
];
|
||||
|
@ -203,6 +326,10 @@ No new host: skipping (Retry in 5s)
|
|||
.form(&form_data)
|
||||
.send()?;
|
||||
let status = &resp.status();
|
||||
if !status.is_success() {
|
||||
eprintln!("{}, {}", "WARN: Found invalid Status Code: ".bright_yellow(), status);
|
||||
return Ok(())
|
||||
}
|
||||
print_banner!("8/8 Confirmed device actions\nReceived response status: {:?}", status);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -244,26 +371,13 @@ fn squeeze_right<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str
|
|||
|
||||
fn squeeze_html_form<'inp>(
|
||||
input: &'inp str,
|
||||
first: &str,
|
||||
second: &str,
|
||||
last: &str,
|
||||
outer_before: &str,
|
||||
outer_after: &str,
|
||||
inner_before: &str,
|
||||
inner_after: &str
|
||||
) -> &'inp str {
|
||||
//find first occurence (broad search)
|
||||
if let Some(from_first_bytes) = input.find(first) {
|
||||
let after_first_bytes = from_first_bytes + first.len();
|
||||
let after_first = &input[after_first_bytes..];
|
||||
//find second occurence (field search)
|
||||
if let Some(rel_from_second_bytes) = after_first.find(second) {
|
||||
let after_second_bytes = rel_from_second_bytes + after_first_bytes + second.len();
|
||||
let after_second = &input[after_second_bytes..];
|
||||
//find closing last match (excluded from output)
|
||||
if let Some(rel_from_last_byte) = after_second.find(last) {
|
||||
let from_last_byte = rel_from_last_byte + after_second_bytes;
|
||||
return &input[after_second_bytes..from_last_byte];
|
||||
}
|
||||
}
|
||||
}
|
||||
""
|
||||
let outer_str = squeeze(input, outer_before, outer_after);
|
||||
squeeze(outer_str, inner_before, inner_after)
|
||||
}
|
||||
|
||||
fn squeeze_loop<'inp>(
|
||||
|
|
Loading…
Reference in New Issue