Compare commits

..

No commits in common. "toml_config_feature" and "master" have entirely different histories.

6 changed files with 291 additions and 450 deletions

2
.gitignore vendored
View File

@ -1,3 +1 @@
/target
config.toml
*.html

353
Cargo.lock generated
View File

@ -15,9 +15,9 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.1.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "base64"
@ -33,9 +33,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.9.1"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "bytes"
@ -45,9 +45,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cc"
version = "1.0.73"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
[[package]]
name = "cfg-if"
@ -85,22 +85,11 @@ dependencies = [
"syn",
]
[[package]]
name = "colored"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
dependencies = [
"atty",
"lazy_static",
"winapi",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"
dependencies = [
"core-foundation-sys",
"libc",
@ -114,22 +103,13 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "encoding_rs"
version = "0.8.30"
version = "0.8.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df"
checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746"
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"
@ -163,43 +143,44 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.21"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.21"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
[[package]]
name = "futures-io"
version = "0.3.21"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
[[package]]
name = "futures-sink"
version = "0.3.21"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
[[package]]
name = "futures-task"
version = "0.3.21"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
[[package]]
name = "futures-util"
version = "0.3.21"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
dependencies = [
"autocfg",
"futures-core",
"futures-io",
"futures-task",
@ -210,10 +191,21 @@ dependencies = [
]
[[package]]
name = "h2"
version = "0.3.12"
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "h2"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c06815895acec637cd6ed6e9662c935b866d20a106f8361892893a7d9234964"
dependencies = [
"bytes",
"fnv",
@ -251,9 +243,9 @@ dependencies = [
[[package]]
name = "http"
version = "0.2.6"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
dependencies = [
"bytes",
"fnv",
@ -262,9 +254,9 @@ dependencies = [
[[package]]
name = "http-body"
version = "0.4.4"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5"
dependencies = [
"bytes",
"http",
@ -273,21 +265,21 @@ dependencies = [
[[package]]
name = "httparse"
version = "1.6.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4"
checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
[[package]]
name = "httpdate"
version = "1.0.2"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
[[package]]
name = "hyper"
version = "0.14.17"
version = "0.14.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd"
checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593"
dependencies = [
"bytes",
"futures-channel",
@ -333,53 +325,40 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.8.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "ipnet"
version = "2.4.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c"
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
[[package]]
name = "iserv-ipad-helper"
version = "0.1.0"
dependencies = [
"clap",
"colored",
"reqwest",
"serde",
"serde_derive",
"serde_json",
"toml",
]
[[package]]
name = "itoa"
version = "1.0.1"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.56"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
"wasm-bindgen",
]
@ -392,9 +371,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.121"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce"
[[package]]
name = "log"
@ -425,15 +404,14 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mio"
version = "0.8.2"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"wasi",
"winapi",
]
@ -466,18 +444,18 @@ dependencies = [
[[package]]
name = "ntapi"
version = "0.3.7"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [
"winapi",
]
[[package]]
name = "num_cpus"
version = "1.13.1"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
@ -485,15 +463,15 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.10.0"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "openssl"
version = "0.10.38"
version = "0.10.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a"
dependencies = [
"bitflags",
"cfg-if",
@ -505,15 +483,15 @@ dependencies = [
[[package]]
name = "openssl-probe"
version = "0.1.5"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
[[package]]
name = "openssl-sys"
version = "0.9.72"
version = "0.9.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058"
dependencies = [
"autocfg",
"cc",
@ -539,9 +517,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pin-project-lite"
version = "0.2.8"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pin-utils"
@ -551,9 +529,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.24"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
[[package]]
name = "ppv-lite86"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
[[package]]
name = "proc-macro-error"
@ -581,27 +565,67 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.36"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.16"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4af2ec4714533fcdf07e886f17025ace8b997b9ce51204ee69b6da831c3da57"
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.11"
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
@ -617,16 +641,15 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.10"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
@ -653,9 +676,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.9"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "schannel"
@ -669,9 +692,9 @@ dependencies = [
[[package]]
name = "security-framework"
version = "2.6.1"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87"
dependencies = [
"bitflags",
"core-foundation",
@ -682,9 +705,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.6.1"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e"
dependencies = [
"core-foundation-sys",
"libc",
@ -692,26 +715,15 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.136"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
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",
]
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
[[package]]
name = "serde_json"
version = "1.0.79"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
dependencies = [
"itoa",
"ryu",
@ -720,9 +732,9 @@ dependencies = [
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
dependencies = [
"form_urlencoded",
"itoa",
@ -738,9 +750,9 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "socket2"
version = "0.4.4"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
dependencies = [
"libc",
"winapi",
@ -754,9 +766,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.89"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54"
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
dependencies = [
"proc-macro2",
"quote",
@ -765,13 +777,13 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.3.0"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
@ -794,9 +806,9 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "tinyvec"
version = "1.5.1"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7"
dependencies = [
"tinyvec_macros",
]
@ -809,17 +821,17 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.17.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"pin-project-lite",
"socket2",
"winapi",
]
@ -835,9 +847,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.6.9"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd"
dependencies = [
"bytes",
"futures-core",
@ -847,15 +859,6 @@ 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"
@ -864,9 +867,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.32"
version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
dependencies = [
"cfg-if",
"pin-project-lite",
@ -875,9 +878,9 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.23"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
dependencies = [
"lazy_static",
]
@ -945,15 +948,15 @@ dependencies = [
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
version = "0.2.79"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -961,9 +964,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.79"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
"bumpalo",
"lazy_static",
@ -976,9 +979,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.29"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39"
dependencies = [
"cfg-if",
"js-sys",
@ -988,9 +991,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.79"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -998,9 +1001,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.79"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
@ -1011,15 +1014,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.79"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
name = "web-sys"
version = "0.3.56"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -1058,9 +1061,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winreg"
version = "0.10.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
dependencies = [
"winapi",
]

View File

@ -8,8 +8,4 @@ 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"

View File

@ -1,27 +0,0 @@
# 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.

View File

@ -1,15 +0,0 @@
#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"

View File

@ -1,249 +1,136 @@
use std::{collections::HashMap, borrow::Cow};
use std::borrow::Cow;
use clap::Parser;
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"))]
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
#[clap(short, long)]
hostname: String,
#[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
//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>,
}
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 = Config::parse(&std::fs::read_to_string("config.toml").unwrap_or(String::new()));
loop { main_loop(&args)?; }
let args = Args::parse();
loop { ipad(&args)?; }
}
fn main_loop(args: &Config) -> Result<(), Box<dyn std::error::Error>> {
let header = ("Cookie", &args.cookie);
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);
let client = reqwest::blocking::Client::new();
let resp = client
.get(format!("https://{}/iserv/admin/hosts", args.hostname))
.header(header.0, header.1)
.query(&args.host_filter)
.query(&params)
.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("ERR: Failed to parse JSON data. This may be because the server did not return valid JSON data to parse.");
let json: serde_json::Value = serde_json::from_str(content).expect("Bad Jason!");
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 {}s)
########################################
", &args.retry_delay);
"###################################
No new host: skipping (Retry in 5s)
###################################
");
//sleep for 5 seconds
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() {
eprintln!("{}, {}", "WARN: Found invalid Status Code: ".bright_yellow(), status);
if !status.is_success() && *status != 300 {
eprintln!("WARN: Found invalid Status Code: {status}");
return Ok(())
}
let plain = &resp.text()?;
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))));
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),
];
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);
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);
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(()) };
if args.target_compilation.is_none() { return Ok(()) }
let resp = client
.get(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, target_compilation))
.header(header.0, header.1)
.send()?;
.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);
@ -251,72 +138,62 @@ No new host: skipping (Retry in {}s)
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
let plain_inner_applications = squeeze(plain, "name=\"ioscompilation[applications][]\"", "</select>");
// push apps (<option value="52" selected="selected">)
let plain_inner_applications = squeeze_html_form(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(plain, "name=\"ioscompilation[profiles][]\"", "</select>");
let plain_inner_profiles = squeeze_html_form(plain, "name=\"ioscompilation[profiles][]\"", ">", "</select>");
squeeze_loop(&mut form_data, plain_inner_profiles, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[profiles][]");
// 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 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 new device
let mdm_new_idevice_id = squeeze_right(plain_inner_devices, "<option value=\"", &format!("\">{}", form_name));
let mdm_new_ipad_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_idevice_id.into()));
form_data.push(("ioscompilation[devices][]".into(), mdm_new_ipad_id.into()));
} else {
eprintln!("{}", "WARN: Device not found in compilation form.\nSkipping compilation edit...".bright_yellow());
return Ok(());
eprintln!("Device not found in compilation edit.")
}
// 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.mdm_compilation.unwrap()))
.post(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_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_idevice_id),
("iserv_crud_multi_select[multi][]", mdm_new_ipad_id),
("iserv_crud_multi_select[topReplacementActions][apply-changes]", ""),
("iserv_crud_multi_select[_token]", csrf_token),
];
@ -326,10 +203,6 @@ No new host: skipping (Retry in {}s)
.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(())
}
@ -371,13 +244,26 @@ fn squeeze_right<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str
fn squeeze_html_form<'inp>(
input: &'inp str,
outer_before: &str,
outer_after: &str,
inner_before: &str,
inner_after: &str
first: &str,
second: &str,
last: &str,
) -> &'inp str {
let outer_str = squeeze(input, outer_before, outer_after);
squeeze(outer_str, inner_before, inner_after)
//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];
}
}
}
""
}
fn squeeze_loop<'inp>(