├── .github
└── workflows
│ ├── lints.yml
│ └── main.yml
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── LICENSE-MIT
├── LICENSE-UNLICENSE
├── README.md
└── src
├── api.rs
├── config.rs
├── crypto.rs
├── error.rs
├── lib.rs
├── logger.rs
├── main.rs
├── opts.rs
├── privatebin.rs
├── uniffi_custom_types.rs
└── util.rs
/.github/workflows/lints.yml:
--------------------------------------------------------------------------------
1 | name: CI:clippy+rustfmt
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches:
7 | - master
8 |
9 | # Make sure CI fails on all warnings, including Clippy lints
10 | env:
11 | RUSTFLAGS: "-Dwarnings"
12 |
13 | jobs:
14 | linting:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v4
19 |
20 | - uses: actions-rs/toolchain@v1
21 | with:
22 | toolchain: nightly
23 | profile: minimal
24 | components: rustfmt, clippy
25 |
26 | - name: Run rust clippy
27 | run: |
28 | cargo clippy --all-targets --all-features
29 |
30 | - name: Run rust fmt
31 | run: |
32 | cargo fmt --check
33 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | tags:
6 | - v*
7 |
8 | jobs:
9 | create_release:
10 | name: Create release
11 | runs-on: ubuntu-latest
12 | outputs:
13 | upload_url: ${{ steps.create_release.outputs.upload_url }}
14 | pbcli_version: ${{ env.PBCLI_VERSION }}
15 | steps:
16 | - name: Retrieve Version
17 | shell: bash
18 | if: env.PBCLI_VERSION == ''
19 | run: |
20 | echo "PBCLI_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
21 | echo "version is: ${{ env.PBCLI_VERSION }}"
22 | - name: Create release
23 | id: create_release
24 | uses: actions/create-release@v1
25 | env:
26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
27 | with:
28 | tag_name: ${{ env.PBCLI_VERSION }}
29 | release_name: ${{ env.PBCLI_VERSION }}
30 | draft: false
31 | prerelease: false
32 |
33 | release_assets:
34 | name: Release assets
35 | needs: create_release
36 | runs-on: ${{ matrix.config.os }}
37 | strategy:
38 | matrix:
39 | config:
40 | - os: ubuntu-latest
41 | name: linux
42 | steps:
43 | - name: Checkout code
44 | uses: actions/checkout@v1
45 |
46 | - name: Install packages (Ubuntu)
47 | if: matrix.config.os == 'ubuntu-latest'
48 | run: |
49 | sudo apt-get update && sudo apt-get install -y --no-install-recommends asciidoctor zsh xz-utils liblz4-tool musl-tools pkg-config libssl-dev
50 |
51 | - name: Install Rust
52 | uses: actions-rs/toolchain@v1
53 | with:
54 | toolchain: nightly
55 | profile: minimal
56 | override: true
57 | target: ${{ matrix.target }}
58 |
59 | - name: Build release binary
60 | run: |
61 | cargo build --verbose --release
62 |
63 | - name: Strip
64 | run: strip "target/release/pbcli"
65 |
66 | - name: Build archive
67 | shell: bash
68 | run: |
69 | staging="pbcli-${{ needs.create_release.outputs.pbcli_version }}-${{ matrix.config.name }}"
70 | mkdir -p "$staging"
71 | cp "target/release/pbcli" "$staging/"
72 | tar czf "$staging.tar.gz" "$staging"
73 | echo "ASSET=$staging.tar.gz" >> $GITHUB_ENV
74 |
75 | - name: Upload release assets
76 | uses: actions/upload-release-asset@v1
77 | env:
78 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79 | with:
80 | upload_url: ${{ needs.create_release.outputs.upload_url }}
81 | asset_name: ${{ env.ASSET }}
82 | asset_path: ${{ env.ASSET }}
83 | asset_content_type: application/octet-stream
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
3 | .idea/
4 | .vscode/
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 4
4 |
5 | [[package]]
6 | name = "addr2line"
7 | version = "0.21.0"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
10 | dependencies = [
11 | "gimli",
12 | ]
13 |
14 | [[package]]
15 | name = "adler"
16 | version = "1.0.2"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19 |
20 | [[package]]
21 | name = "aead"
22 | version = "0.4.3"
23 | source = "registry+https://github.com/rust-lang/crates.io-index"
24 | checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
25 | dependencies = [
26 | "generic-array",
27 | ]
28 |
29 | [[package]]
30 | name = "aes"
31 | version = "0.7.5"
32 | source = "registry+https://github.com/rust-lang/crates.io-index"
33 | checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
34 | dependencies = [
35 | "cfg-if",
36 | "cipher",
37 | "cpufeatures",
38 | "opaque-debug",
39 | ]
40 |
41 | [[package]]
42 | name = "aes-gcm"
43 | version = "0.9.4"
44 | source = "registry+https://github.com/rust-lang/crates.io-index"
45 | checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
46 | dependencies = [
47 | "aead",
48 | "aes",
49 | "cipher",
50 | "ctr",
51 | "ghash",
52 | "subtle",
53 | ]
54 |
55 | [[package]]
56 | name = "ahash"
57 | version = "0.8.11"
58 | source = "registry+https://github.com/rust-lang/crates.io-index"
59 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
60 | dependencies = [
61 | "cfg-if",
62 | "getrandom",
63 | "once_cell",
64 | "version_check",
65 | "zerocopy",
66 | ]
67 |
68 | [[package]]
69 | name = "anstream"
70 | version = "0.6.14"
71 | source = "registry+https://github.com/rust-lang/crates.io-index"
72 | checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
73 | dependencies = [
74 | "anstyle",
75 | "anstyle-parse",
76 | "anstyle-query",
77 | "anstyle-wincon",
78 | "colorchoice",
79 | "is_terminal_polyfill",
80 | "utf8parse",
81 | ]
82 |
83 | [[package]]
84 | name = "anstyle"
85 | version = "1.0.10"
86 | source = "registry+https://github.com/rust-lang/crates.io-index"
87 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
88 |
89 | [[package]]
90 | name = "anstyle-parse"
91 | version = "0.2.4"
92 | source = "registry+https://github.com/rust-lang/crates.io-index"
93 | checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
94 | dependencies = [
95 | "utf8parse",
96 | ]
97 |
98 | [[package]]
99 | name = "anstyle-query"
100 | version = "1.0.3"
101 | source = "registry+https://github.com/rust-lang/crates.io-index"
102 | checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
103 | dependencies = [
104 | "windows-sys 0.52.0",
105 | ]
106 |
107 | [[package]]
108 | name = "anstyle-wincon"
109 | version = "3.0.3"
110 | source = "registry+https://github.com/rust-lang/crates.io-index"
111 | checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
112 | dependencies = [
113 | "anstyle",
114 | "windows-sys 0.52.0",
115 | ]
116 |
117 | [[package]]
118 | name = "anyhow"
119 | version = "1.0.81"
120 | source = "registry+https://github.com/rust-lang/crates.io-index"
121 | checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
122 |
123 | [[package]]
124 | name = "askama"
125 | version = "0.12.1"
126 | source = "registry+https://github.com/rust-lang/crates.io-index"
127 | checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28"
128 | dependencies = [
129 | "askama_derive",
130 | "askama_escape",
131 | ]
132 |
133 | [[package]]
134 | name = "askama_derive"
135 | version = "0.12.5"
136 | source = "registry+https://github.com/rust-lang/crates.io-index"
137 | checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83"
138 | dependencies = [
139 | "askama_parser",
140 | "basic-toml",
141 | "mime",
142 | "mime_guess",
143 | "proc-macro2",
144 | "quote",
145 | "serde",
146 | "syn 2.0.57",
147 | ]
148 |
149 | [[package]]
150 | name = "askama_escape"
151 | version = "0.10.3"
152 | source = "registry+https://github.com/rust-lang/crates.io-index"
153 | checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
154 |
155 | [[package]]
156 | name = "askama_parser"
157 | version = "0.2.1"
158 | source = "registry+https://github.com/rust-lang/crates.io-index"
159 | checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0"
160 | dependencies = [
161 | "nom",
162 | ]
163 |
164 | [[package]]
165 | name = "autocfg"
166 | version = "1.2.0"
167 | source = "registry+https://github.com/rust-lang/crates.io-index"
168 | checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
169 |
170 | [[package]]
171 | name = "backtrace"
172 | version = "0.3.71"
173 | source = "registry+https://github.com/rust-lang/crates.io-index"
174 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
175 | dependencies = [
176 | "addr2line",
177 | "cc",
178 | "cfg-if",
179 | "libc",
180 | "miniz_oxide 0.7.2",
181 | "object",
182 | "rustc-demangle",
183 | ]
184 |
185 | [[package]]
186 | name = "base64"
187 | version = "0.13.1"
188 | source = "registry+https://github.com/rust-lang/crates.io-index"
189 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
190 |
191 | [[package]]
192 | name = "base64"
193 | version = "0.21.7"
194 | source = "registry+https://github.com/rust-lang/crates.io-index"
195 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
196 |
197 | [[package]]
198 | name = "base64ct"
199 | version = "1.0.1"
200 | source = "registry+https://github.com/rust-lang/crates.io-index"
201 | checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b"
202 |
203 | [[package]]
204 | name = "basic-toml"
205 | version = "0.1.9"
206 | source = "registry+https://github.com/rust-lang/crates.io-index"
207 | checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8"
208 | dependencies = [
209 | "serde",
210 | ]
211 |
212 | [[package]]
213 | name = "bincode"
214 | version = "1.3.3"
215 | source = "registry+https://github.com/rust-lang/crates.io-index"
216 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
217 | dependencies = [
218 | "serde",
219 | ]
220 |
221 | [[package]]
222 | name = "bitflags"
223 | version = "1.3.2"
224 | source = "registry+https://github.com/rust-lang/crates.io-index"
225 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
226 |
227 | [[package]]
228 | name = "bitflags"
229 | version = "2.5.0"
230 | source = "registry+https://github.com/rust-lang/crates.io-index"
231 | checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
232 |
233 | [[package]]
234 | name = "block-buffer"
235 | version = "0.9.0"
236 | source = "registry+https://github.com/rust-lang/crates.io-index"
237 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
238 | dependencies = [
239 | "generic-array",
240 | ]
241 |
242 | [[package]]
243 | name = "bs58"
244 | version = "0.4.0"
245 | source = "registry+https://github.com/rust-lang/crates.io-index"
246 | checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
247 |
248 | [[package]]
249 | name = "bumpalo"
250 | version = "3.15.4"
251 | source = "registry+https://github.com/rust-lang/crates.io-index"
252 | checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
253 |
254 | [[package]]
255 | name = "byteorder"
256 | version = "1.5.0"
257 | source = "registry+https://github.com/rust-lang/crates.io-index"
258 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
259 |
260 | [[package]]
261 | name = "bytes"
262 | version = "1.6.0"
263 | source = "registry+https://github.com/rust-lang/crates.io-index"
264 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
265 |
266 | [[package]]
267 | name = "camino"
268 | version = "1.1.6"
269 | source = "registry+https://github.com/rust-lang/crates.io-index"
270 | checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
271 | dependencies = [
272 | "serde",
273 | ]
274 |
275 | [[package]]
276 | name = "cargo-platform"
277 | version = "0.1.8"
278 | source = "registry+https://github.com/rust-lang/crates.io-index"
279 | checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
280 | dependencies = [
281 | "serde",
282 | ]
283 |
284 | [[package]]
285 | name = "cargo_metadata"
286 | version = "0.15.4"
287 | source = "registry+https://github.com/rust-lang/crates.io-index"
288 | checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
289 | dependencies = [
290 | "camino",
291 | "cargo-platform",
292 | "semver",
293 | "serde",
294 | "serde_json",
295 | "thiserror",
296 | ]
297 |
298 | [[package]]
299 | name = "cc"
300 | version = "1.0.90"
301 | source = "registry+https://github.com/rust-lang/crates.io-index"
302 | checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
303 |
304 | [[package]]
305 | name = "cfg-if"
306 | version = "1.0.0"
307 | source = "registry+https://github.com/rust-lang/crates.io-index"
308 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
309 |
310 | [[package]]
311 | name = "cipher"
312 | version = "0.3.0"
313 | source = "registry+https://github.com/rust-lang/crates.io-index"
314 | checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
315 | dependencies = [
316 | "generic-array",
317 | ]
318 |
319 | [[package]]
320 | name = "clap"
321 | version = "4.5.29"
322 | source = "registry+https://github.com/rust-lang/crates.io-index"
323 | checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184"
324 | dependencies = [
325 | "clap_builder",
326 | "clap_derive",
327 | ]
328 |
329 | [[package]]
330 | name = "clap_builder"
331 | version = "4.5.29"
332 | source = "registry+https://github.com/rust-lang/crates.io-index"
333 | checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9"
334 | dependencies = [
335 | "anstream",
336 | "anstyle",
337 | "clap_lex",
338 | "strsim 0.11.1",
339 | ]
340 |
341 | [[package]]
342 | name = "clap_derive"
343 | version = "4.5.28"
344 | source = "registry+https://github.com/rust-lang/crates.io-index"
345 | checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
346 | dependencies = [
347 | "heck",
348 | "proc-macro2",
349 | "quote",
350 | "syn 2.0.57",
351 | ]
352 |
353 | [[package]]
354 | name = "clap_lex"
355 | version = "0.7.4"
356 | source = "registry+https://github.com/rust-lang/crates.io-index"
357 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
358 |
359 | [[package]]
360 | name = "colorchoice"
361 | version = "1.0.1"
362 | source = "registry+https://github.com/rust-lang/crates.io-index"
363 | checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
364 |
365 | [[package]]
366 | name = "console"
367 | version = "0.15.8"
368 | source = "registry+https://github.com/rust-lang/crates.io-index"
369 | checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
370 | dependencies = [
371 | "encode_unicode",
372 | "lazy_static",
373 | "libc",
374 | "unicode-width",
375 | "windows-sys 0.52.0",
376 | ]
377 |
378 | [[package]]
379 | name = "core-foundation"
380 | version = "0.9.4"
381 | source = "registry+https://github.com/rust-lang/crates.io-index"
382 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
383 | dependencies = [
384 | "core-foundation-sys",
385 | "libc",
386 | ]
387 |
388 | [[package]]
389 | name = "core-foundation-sys"
390 | version = "0.8.6"
391 | source = "registry+https://github.com/rust-lang/crates.io-index"
392 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
393 |
394 | [[package]]
395 | name = "cpufeatures"
396 | version = "0.2.12"
397 | source = "registry+https://github.com/rust-lang/crates.io-index"
398 | checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
399 | dependencies = [
400 | "libc",
401 | ]
402 |
403 | [[package]]
404 | name = "crypto-mac"
405 | version = "0.11.1"
406 | source = "registry+https://github.com/rust-lang/crates.io-index"
407 | checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
408 | dependencies = [
409 | "generic-array",
410 | "subtle",
411 | ]
412 |
413 | [[package]]
414 | name = "cssparser"
415 | version = "0.34.0"
416 | source = "registry+https://github.com/rust-lang/crates.io-index"
417 | checksum = "b7c66d1cd8ed61bf80b38432613a7a2f09401ab8d0501110655f8b341484a3e3"
418 | dependencies = [
419 | "cssparser-macros",
420 | "dtoa-short",
421 | "itoa",
422 | "phf",
423 | "smallvec",
424 | ]
425 |
426 | [[package]]
427 | name = "cssparser-macros"
428 | version = "0.6.1"
429 | source = "registry+https://github.com/rust-lang/crates.io-index"
430 | checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
431 | dependencies = [
432 | "quote",
433 | "syn 2.0.57",
434 | ]
435 |
436 | [[package]]
437 | name = "ctr"
438 | version = "0.8.0"
439 | source = "registry+https://github.com/rust-lang/crates.io-index"
440 | checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
441 | dependencies = [
442 | "cipher",
443 | ]
444 |
445 | [[package]]
446 | name = "darling"
447 | version = "0.13.4"
448 | source = "registry+https://github.com/rust-lang/crates.io-index"
449 | checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
450 | dependencies = [
451 | "darling_core",
452 | "darling_macro",
453 | ]
454 |
455 | [[package]]
456 | name = "darling_core"
457 | version = "0.13.4"
458 | source = "registry+https://github.com/rust-lang/crates.io-index"
459 | checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
460 | dependencies = [
461 | "fnv",
462 | "ident_case",
463 | "proc-macro2",
464 | "quote",
465 | "strsim 0.10.0",
466 | "syn 1.0.109",
467 | ]
468 |
469 | [[package]]
470 | name = "darling_macro"
471 | version = "0.13.4"
472 | source = "registry+https://github.com/rust-lang/crates.io-index"
473 | checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
474 | dependencies = [
475 | "darling_core",
476 | "quote",
477 | "syn 1.0.109",
478 | ]
479 |
480 | [[package]]
481 | name = "data-url"
482 | version = "0.1.1"
483 | source = "registry+https://github.com/rust-lang/crates.io-index"
484 | checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193"
485 | dependencies = [
486 | "matches",
487 | ]
488 |
489 | [[package]]
490 | name = "derive_more"
491 | version = "0.99.18"
492 | source = "registry+https://github.com/rust-lang/crates.io-index"
493 | checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
494 | dependencies = [
495 | "proc-macro2",
496 | "quote",
497 | "syn 2.0.57",
498 | ]
499 |
500 | [[package]]
501 | name = "dialoguer"
502 | version = "0.9.0"
503 | source = "registry+https://github.com/rust-lang/crates.io-index"
504 | checksum = "61579ada4ec0c6031cfac3f86fdba0d195a7ebeb5e36693bd53cb5999a25beeb"
505 | dependencies = [
506 | "console",
507 | "lazy_static",
508 | "tempfile",
509 | "zeroize",
510 | ]
511 |
512 | [[package]]
513 | name = "digest"
514 | version = "0.9.0"
515 | source = "registry+https://github.com/rust-lang/crates.io-index"
516 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
517 | dependencies = [
518 | "generic-array",
519 | ]
520 |
521 | [[package]]
522 | name = "directories"
523 | version = "5.0.1"
524 | source = "registry+https://github.com/rust-lang/crates.io-index"
525 | checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
526 | dependencies = [
527 | "dirs-sys",
528 | ]
529 |
530 | [[package]]
531 | name = "dirs-sys"
532 | version = "0.4.1"
533 | source = "registry+https://github.com/rust-lang/crates.io-index"
534 | checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
535 | dependencies = [
536 | "libc",
537 | "option-ext",
538 | "redox_users",
539 | "windows-sys 0.48.0",
540 | ]
541 |
542 | [[package]]
543 | name = "dtoa"
544 | version = "1.0.9"
545 | source = "registry+https://github.com/rust-lang/crates.io-index"
546 | checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653"
547 |
548 | [[package]]
549 | name = "dtoa-short"
550 | version = "0.3.5"
551 | source = "registry+https://github.com/rust-lang/crates.io-index"
552 | checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87"
553 | dependencies = [
554 | "dtoa",
555 | ]
556 |
557 | [[package]]
558 | name = "ego-tree"
559 | version = "0.9.0"
560 | source = "registry+https://github.com/rust-lang/crates.io-index"
561 | checksum = "7c6ba7d4eec39eaa9ab24d44a0e73a7949a1095a8b3f3abb11eddf27dbb56a53"
562 |
563 | [[package]]
564 | name = "encode_unicode"
565 | version = "0.3.6"
566 | source = "registry+https://github.com/rust-lang/crates.io-index"
567 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
568 |
569 | [[package]]
570 | name = "encoding_rs"
571 | version = "0.8.33"
572 | source = "registry+https://github.com/rust-lang/crates.io-index"
573 | checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
574 | dependencies = [
575 | "cfg-if",
576 | ]
577 |
578 | [[package]]
579 | name = "equivalent"
580 | version = "1.0.1"
581 | source = "registry+https://github.com/rust-lang/crates.io-index"
582 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
583 |
584 | [[package]]
585 | name = "errno"
586 | version = "0.3.8"
587 | source = "registry+https://github.com/rust-lang/crates.io-index"
588 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
589 | dependencies = [
590 | "libc",
591 | "windows-sys 0.52.0",
592 | ]
593 |
594 | [[package]]
595 | name = "fastrand"
596 | version = "2.0.2"
597 | source = "registry+https://github.com/rust-lang/crates.io-index"
598 | checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
599 |
600 | [[package]]
601 | name = "fnv"
602 | version = "1.0.7"
603 | source = "registry+https://github.com/rust-lang/crates.io-index"
604 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
605 |
606 | [[package]]
607 | name = "foreign-types"
608 | version = "0.3.2"
609 | source = "registry+https://github.com/rust-lang/crates.io-index"
610 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
611 | dependencies = [
612 | "foreign-types-shared",
613 | ]
614 |
615 | [[package]]
616 | name = "foreign-types-shared"
617 | version = "0.1.1"
618 | source = "registry+https://github.com/rust-lang/crates.io-index"
619 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
620 |
621 | [[package]]
622 | name = "form_urlencoded"
623 | version = "1.2.1"
624 | source = "registry+https://github.com/rust-lang/crates.io-index"
625 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
626 | dependencies = [
627 | "percent-encoding",
628 | ]
629 |
630 | [[package]]
631 | name = "fs-err"
632 | version = "2.11.0"
633 | source = "registry+https://github.com/rust-lang/crates.io-index"
634 | checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41"
635 | dependencies = [
636 | "autocfg",
637 | ]
638 |
639 | [[package]]
640 | name = "futf"
641 | version = "0.1.5"
642 | source = "registry+https://github.com/rust-lang/crates.io-index"
643 | checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
644 | dependencies = [
645 | "mac",
646 | "new_debug_unreachable",
647 | ]
648 |
649 | [[package]]
650 | name = "futures-channel"
651 | version = "0.3.30"
652 | source = "registry+https://github.com/rust-lang/crates.io-index"
653 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
654 | dependencies = [
655 | "futures-core",
656 | "futures-sink",
657 | ]
658 |
659 | [[package]]
660 | name = "futures-core"
661 | version = "0.3.30"
662 | source = "registry+https://github.com/rust-lang/crates.io-index"
663 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
664 |
665 | [[package]]
666 | name = "futures-io"
667 | version = "0.3.30"
668 | source = "registry+https://github.com/rust-lang/crates.io-index"
669 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
670 |
671 | [[package]]
672 | name = "futures-sink"
673 | version = "0.3.30"
674 | source = "registry+https://github.com/rust-lang/crates.io-index"
675 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
676 |
677 | [[package]]
678 | name = "futures-task"
679 | version = "0.3.30"
680 | source = "registry+https://github.com/rust-lang/crates.io-index"
681 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
682 |
683 | [[package]]
684 | name = "futures-util"
685 | version = "0.3.30"
686 | source = "registry+https://github.com/rust-lang/crates.io-index"
687 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
688 | dependencies = [
689 | "futures-core",
690 | "futures-io",
691 | "futures-sink",
692 | "futures-task",
693 | "memchr",
694 | "pin-project-lite",
695 | "pin-utils",
696 | "slab",
697 | ]
698 |
699 | [[package]]
700 | name = "fxhash"
701 | version = "0.2.1"
702 | source = "registry+https://github.com/rust-lang/crates.io-index"
703 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
704 | dependencies = [
705 | "byteorder",
706 | ]
707 |
708 | [[package]]
709 | name = "generic-array"
710 | version = "0.14.7"
711 | source = "registry+https://github.com/rust-lang/crates.io-index"
712 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
713 | dependencies = [
714 | "typenum",
715 | "version_check",
716 | ]
717 |
718 | [[package]]
719 | name = "getopts"
720 | version = "0.2.21"
721 | source = "registry+https://github.com/rust-lang/crates.io-index"
722 | checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
723 | dependencies = [
724 | "unicode-width",
725 | ]
726 |
727 | [[package]]
728 | name = "getrandom"
729 | version = "0.2.12"
730 | source = "registry+https://github.com/rust-lang/crates.io-index"
731 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
732 | dependencies = [
733 | "cfg-if",
734 | "libc",
735 | "wasi",
736 | ]
737 |
738 | [[package]]
739 | name = "ghash"
740 | version = "0.4.4"
741 | source = "registry+https://github.com/rust-lang/crates.io-index"
742 | checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
743 | dependencies = [
744 | "opaque-debug",
745 | "polyval",
746 | ]
747 |
748 | [[package]]
749 | name = "gimli"
750 | version = "0.28.1"
751 | source = "registry+https://github.com/rust-lang/crates.io-index"
752 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
753 |
754 | [[package]]
755 | name = "glob"
756 | version = "0.3.1"
757 | source = "registry+https://github.com/rust-lang/crates.io-index"
758 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
759 |
760 | [[package]]
761 | name = "goblin"
762 | version = "0.8.2"
763 | source = "registry+https://github.com/rust-lang/crates.io-index"
764 | checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47"
765 | dependencies = [
766 | "log",
767 | "plain",
768 | "scroll",
769 | ]
770 |
771 | [[package]]
772 | name = "h2"
773 | version = "0.4.3"
774 | source = "registry+https://github.com/rust-lang/crates.io-index"
775 | checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4"
776 | dependencies = [
777 | "bytes",
778 | "fnv",
779 | "futures-core",
780 | "futures-sink",
781 | "futures-util",
782 | "http",
783 | "indexmap",
784 | "slab",
785 | "tokio",
786 | "tokio-util",
787 | "tracing",
788 | ]
789 |
790 | [[package]]
791 | name = "hashbrown"
792 | version = "0.14.3"
793 | source = "registry+https://github.com/rust-lang/crates.io-index"
794 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
795 |
796 | [[package]]
797 | name = "heck"
798 | version = "0.5.0"
799 | source = "registry+https://github.com/rust-lang/crates.io-index"
800 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
801 |
802 | [[package]]
803 | name = "hermit-abi"
804 | version = "0.3.9"
805 | source = "registry+https://github.com/rust-lang/crates.io-index"
806 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
807 |
808 | [[package]]
809 | name = "hex-literal"
810 | version = "0.3.4"
811 | source = "registry+https://github.com/rust-lang/crates.io-index"
812 | checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
813 |
814 | [[package]]
815 | name = "hmac"
816 | version = "0.11.0"
817 | source = "registry+https://github.com/rust-lang/crates.io-index"
818 | checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
819 | dependencies = [
820 | "crypto-mac",
821 | "digest",
822 | ]
823 |
824 | [[package]]
825 | name = "html5ever"
826 | version = "0.29.0"
827 | source = "registry+https://github.com/rust-lang/crates.io-index"
828 | checksum = "2e15626aaf9c351bc696217cbe29cb9b5e86c43f8a46b5e2f5c6c5cf7cb904ce"
829 | dependencies = [
830 | "log",
831 | "mac",
832 | "markup5ever",
833 | "proc-macro2",
834 | "quote",
835 | "syn 2.0.57",
836 | ]
837 |
838 | [[package]]
839 | name = "http"
840 | version = "1.1.0"
841 | source = "registry+https://github.com/rust-lang/crates.io-index"
842 | checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
843 | dependencies = [
844 | "bytes",
845 | "fnv",
846 | "itoa",
847 | ]
848 |
849 | [[package]]
850 | name = "http-body"
851 | version = "1.0.0"
852 | source = "registry+https://github.com/rust-lang/crates.io-index"
853 | checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
854 | dependencies = [
855 | "bytes",
856 | "http",
857 | ]
858 |
859 | [[package]]
860 | name = "http-body-util"
861 | version = "0.1.1"
862 | source = "registry+https://github.com/rust-lang/crates.io-index"
863 | checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
864 | dependencies = [
865 | "bytes",
866 | "futures-core",
867 | "http",
868 | "http-body",
869 | "pin-project-lite",
870 | ]
871 |
872 | [[package]]
873 | name = "httparse"
874 | version = "1.8.0"
875 | source = "registry+https://github.com/rust-lang/crates.io-index"
876 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
877 |
878 | [[package]]
879 | name = "hyper"
880 | version = "1.2.0"
881 | source = "registry+https://github.com/rust-lang/crates.io-index"
882 | checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
883 | dependencies = [
884 | "bytes",
885 | "futures-channel",
886 | "futures-util",
887 | "h2",
888 | "http",
889 | "http-body",
890 | "httparse",
891 | "itoa",
892 | "pin-project-lite",
893 | "smallvec",
894 | "tokio",
895 | "want",
896 | ]
897 |
898 | [[package]]
899 | name = "hyper-tls"
900 | version = "0.6.0"
901 | source = "registry+https://github.com/rust-lang/crates.io-index"
902 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
903 | dependencies = [
904 | "bytes",
905 | "http-body-util",
906 | "hyper",
907 | "hyper-util",
908 | "native-tls",
909 | "tokio",
910 | "tokio-native-tls",
911 | "tower-service",
912 | ]
913 |
914 | [[package]]
915 | name = "hyper-util"
916 | version = "0.1.3"
917 | source = "registry+https://github.com/rust-lang/crates.io-index"
918 | checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
919 | dependencies = [
920 | "bytes",
921 | "futures-channel",
922 | "futures-util",
923 | "http",
924 | "http-body",
925 | "hyper",
926 | "pin-project-lite",
927 | "socket2",
928 | "tokio",
929 | "tower",
930 | "tower-service",
931 | "tracing",
932 | ]
933 |
934 | [[package]]
935 | name = "ident_case"
936 | version = "1.0.1"
937 | source = "registry+https://github.com/rust-lang/crates.io-index"
938 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
939 |
940 | [[package]]
941 | name = "idna"
942 | version = "0.5.0"
943 | source = "registry+https://github.com/rust-lang/crates.io-index"
944 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
945 | dependencies = [
946 | "unicode-bidi",
947 | "unicode-normalization",
948 | ]
949 |
950 | [[package]]
951 | name = "indexmap"
952 | version = "2.2.6"
953 | source = "registry+https://github.com/rust-lang/crates.io-index"
954 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
955 | dependencies = [
956 | "equivalent",
957 | "hashbrown",
958 | ]
959 |
960 | [[package]]
961 | name = "ipnet"
962 | version = "2.9.0"
963 | source = "registry+https://github.com/rust-lang/crates.io-index"
964 | checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
965 |
966 | [[package]]
967 | name = "is_terminal_polyfill"
968 | version = "1.70.0"
969 | source = "registry+https://github.com/rust-lang/crates.io-index"
970 | checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
971 |
972 | [[package]]
973 | name = "itoa"
974 | version = "1.0.11"
975 | source = "registry+https://github.com/rust-lang/crates.io-index"
976 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
977 |
978 | [[package]]
979 | name = "js-sys"
980 | version = "0.3.69"
981 | source = "registry+https://github.com/rust-lang/crates.io-index"
982 | checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
983 | dependencies = [
984 | "wasm-bindgen",
985 | ]
986 |
987 | [[package]]
988 | name = "lazy_static"
989 | version = "1.4.0"
990 | source = "registry+https://github.com/rust-lang/crates.io-index"
991 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
992 |
993 | [[package]]
994 | name = "libc"
995 | version = "0.2.153"
996 | source = "registry+https://github.com/rust-lang/crates.io-index"
997 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
998 |
999 | [[package]]
1000 | name = "libredox"
1001 | version = "0.1.3"
1002 | source = "registry+https://github.com/rust-lang/crates.io-index"
1003 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
1004 | dependencies = [
1005 | "bitflags 2.5.0",
1006 | "libc",
1007 | ]
1008 |
1009 | [[package]]
1010 | name = "linux-raw-sys"
1011 | version = "0.4.13"
1012 | source = "registry+https://github.com/rust-lang/crates.io-index"
1013 | checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
1014 |
1015 | [[package]]
1016 | name = "lock_api"
1017 | version = "0.4.12"
1018 | source = "registry+https://github.com/rust-lang/crates.io-index"
1019 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
1020 | dependencies = [
1021 | "autocfg",
1022 | "scopeguard",
1023 | ]
1024 |
1025 | [[package]]
1026 | name = "log"
1027 | version = "0.4.22"
1028 | source = "registry+https://github.com/rust-lang/crates.io-index"
1029 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
1030 |
1031 | [[package]]
1032 | name = "mac"
1033 | version = "0.1.1"
1034 | source = "registry+https://github.com/rust-lang/crates.io-index"
1035 | checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
1036 |
1037 | [[package]]
1038 | name = "markup5ever"
1039 | version = "0.14.0"
1040 | source = "registry+https://github.com/rust-lang/crates.io-index"
1041 | checksum = "82c88c6129bd24319e62a0359cb6b958fa7e8be6e19bb1663bc396b90883aca5"
1042 | dependencies = [
1043 | "log",
1044 | "phf",
1045 | "phf_codegen",
1046 | "string_cache",
1047 | "string_cache_codegen",
1048 | "tendril",
1049 | ]
1050 |
1051 | [[package]]
1052 | name = "matches"
1053 | version = "0.1.10"
1054 | source = "registry+https://github.com/rust-lang/crates.io-index"
1055 | checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
1056 |
1057 | [[package]]
1058 | name = "memchr"
1059 | version = "2.7.2"
1060 | source = "registry+https://github.com/rust-lang/crates.io-index"
1061 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
1062 |
1063 | [[package]]
1064 | name = "mime"
1065 | version = "0.3.17"
1066 | source = "registry+https://github.com/rust-lang/crates.io-index"
1067 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
1068 |
1069 | [[package]]
1070 | name = "mime_guess"
1071 | version = "2.0.4"
1072 | source = "registry+https://github.com/rust-lang/crates.io-index"
1073 | checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
1074 | dependencies = [
1075 | "mime",
1076 | "unicase",
1077 | ]
1078 |
1079 | [[package]]
1080 | name = "minimal-lexical"
1081 | version = "0.2.1"
1082 | source = "registry+https://github.com/rust-lang/crates.io-index"
1083 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
1084 |
1085 | [[package]]
1086 | name = "miniz_oxide"
1087 | version = "0.5.4"
1088 | source = "registry+https://github.com/rust-lang/crates.io-index"
1089 | checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
1090 | dependencies = [
1091 | "adler",
1092 | ]
1093 |
1094 | [[package]]
1095 | name = "miniz_oxide"
1096 | version = "0.7.2"
1097 | source = "registry+https://github.com/rust-lang/crates.io-index"
1098 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
1099 | dependencies = [
1100 | "adler",
1101 | ]
1102 |
1103 | [[package]]
1104 | name = "mio"
1105 | version = "0.8.11"
1106 | source = "registry+https://github.com/rust-lang/crates.io-index"
1107 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
1108 | dependencies = [
1109 | "libc",
1110 | "wasi",
1111 | "windows-sys 0.48.0",
1112 | ]
1113 |
1114 | [[package]]
1115 | name = "native-tls"
1116 | version = "0.2.11"
1117 | source = "registry+https://github.com/rust-lang/crates.io-index"
1118 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
1119 | dependencies = [
1120 | "lazy_static",
1121 | "libc",
1122 | "log",
1123 | "openssl",
1124 | "openssl-probe",
1125 | "openssl-sys",
1126 | "schannel",
1127 | "security-framework",
1128 | "security-framework-sys",
1129 | "tempfile",
1130 | ]
1131 |
1132 | [[package]]
1133 | name = "new_debug_unreachable"
1134 | version = "1.0.6"
1135 | source = "registry+https://github.com/rust-lang/crates.io-index"
1136 | checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
1137 |
1138 | [[package]]
1139 | name = "nom"
1140 | version = "7.1.3"
1141 | source = "registry+https://github.com/rust-lang/crates.io-index"
1142 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
1143 | dependencies = [
1144 | "memchr",
1145 | "minimal-lexical",
1146 | ]
1147 |
1148 | [[package]]
1149 | name = "num_cpus"
1150 | version = "1.16.0"
1151 | source = "registry+https://github.com/rust-lang/crates.io-index"
1152 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
1153 | dependencies = [
1154 | "hermit-abi",
1155 | "libc",
1156 | ]
1157 |
1158 | [[package]]
1159 | name = "object"
1160 | version = "0.32.2"
1161 | source = "registry+https://github.com/rust-lang/crates.io-index"
1162 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
1163 | dependencies = [
1164 | "memchr",
1165 | ]
1166 |
1167 | [[package]]
1168 | name = "once_cell"
1169 | version = "1.19.0"
1170 | source = "registry+https://github.com/rust-lang/crates.io-index"
1171 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
1172 |
1173 | [[package]]
1174 | name = "opaque-debug"
1175 | version = "0.3.1"
1176 | source = "registry+https://github.com/rust-lang/crates.io-index"
1177 | checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
1178 |
1179 | [[package]]
1180 | name = "openssl"
1181 | version = "0.10.64"
1182 | source = "registry+https://github.com/rust-lang/crates.io-index"
1183 | checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
1184 | dependencies = [
1185 | "bitflags 2.5.0",
1186 | "cfg-if",
1187 | "foreign-types",
1188 | "libc",
1189 | "once_cell",
1190 | "openssl-macros",
1191 | "openssl-sys",
1192 | ]
1193 |
1194 | [[package]]
1195 | name = "openssl-macros"
1196 | version = "0.1.1"
1197 | source = "registry+https://github.com/rust-lang/crates.io-index"
1198 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
1199 | dependencies = [
1200 | "proc-macro2",
1201 | "quote",
1202 | "syn 2.0.57",
1203 | ]
1204 |
1205 | [[package]]
1206 | name = "openssl-probe"
1207 | version = "0.1.5"
1208 | source = "registry+https://github.com/rust-lang/crates.io-index"
1209 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
1210 |
1211 | [[package]]
1212 | name = "openssl-src"
1213 | version = "300.2.3+3.2.1"
1214 | source = "registry+https://github.com/rust-lang/crates.io-index"
1215 | checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843"
1216 | dependencies = [
1217 | "cc",
1218 | ]
1219 |
1220 | [[package]]
1221 | name = "openssl-sys"
1222 | version = "0.9.102"
1223 | source = "registry+https://github.com/rust-lang/crates.io-index"
1224 | checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
1225 | dependencies = [
1226 | "cc",
1227 | "libc",
1228 | "openssl-src",
1229 | "pkg-config",
1230 | "vcpkg",
1231 | ]
1232 |
1233 | [[package]]
1234 | name = "option-ext"
1235 | version = "0.2.0"
1236 | source = "registry+https://github.com/rust-lang/crates.io-index"
1237 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
1238 |
1239 | [[package]]
1240 | name = "parking_lot"
1241 | version = "0.12.3"
1242 | source = "registry+https://github.com/rust-lang/crates.io-index"
1243 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
1244 | dependencies = [
1245 | "lock_api",
1246 | "parking_lot_core",
1247 | ]
1248 |
1249 | [[package]]
1250 | name = "parking_lot_core"
1251 | version = "0.9.10"
1252 | source = "registry+https://github.com/rust-lang/crates.io-index"
1253 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
1254 | dependencies = [
1255 | "cfg-if",
1256 | "libc",
1257 | "redox_syscall",
1258 | "smallvec",
1259 | "windows-targets 0.52.4",
1260 | ]
1261 |
1262 | [[package]]
1263 | name = "parse-size"
1264 | version = "1.0.0"
1265 | source = "registry+https://github.com/rust-lang/crates.io-index"
1266 | checksum = "944553dd59c802559559161f9816429058b869003836120e262e8caec061b7ae"
1267 |
1268 | [[package]]
1269 | name = "password-hash"
1270 | version = "0.3.2"
1271 | source = "registry+https://github.com/rust-lang/crates.io-index"
1272 | checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8"
1273 | dependencies = [
1274 | "base64ct",
1275 | "rand_core",
1276 | "subtle",
1277 | ]
1278 |
1279 | [[package]]
1280 | name = "paste"
1281 | version = "1.0.14"
1282 | source = "registry+https://github.com/rust-lang/crates.io-index"
1283 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
1284 |
1285 | [[package]]
1286 | name = "pbcli"
1287 | version = "2.8.0"
1288 | dependencies = [
1289 | "aes-gcm",
1290 | "base64 0.13.1",
1291 | "bs58",
1292 | "clap",
1293 | "crypto-mac",
1294 | "data-url",
1295 | "dialoguer",
1296 | "directories",
1297 | "hex-literal",
1298 | "hmac",
1299 | "log",
1300 | "mime_guess",
1301 | "miniz_oxide 0.5.4",
1302 | "openssl",
1303 | "parse-size",
1304 | "pbkdf2",
1305 | "rand_chacha",
1306 | "rand_core",
1307 | "reqwest",
1308 | "ring",
1309 | "scraper",
1310 | "serde",
1311 | "serde_json",
1312 | "serde_with",
1313 | "sha2",
1314 | "terminal_size",
1315 | "typenum",
1316 | "uniffi",
1317 | "url",
1318 | ]
1319 |
1320 | [[package]]
1321 | name = "pbkdf2"
1322 | version = "0.9.0"
1323 | source = "registry+https://github.com/rust-lang/crates.io-index"
1324 | checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"
1325 | dependencies = [
1326 | "crypto-mac",
1327 | "hmac",
1328 | "password-hash",
1329 | "sha2",
1330 | ]
1331 |
1332 | [[package]]
1333 | name = "percent-encoding"
1334 | version = "2.3.1"
1335 | source = "registry+https://github.com/rust-lang/crates.io-index"
1336 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
1337 |
1338 | [[package]]
1339 | name = "phf"
1340 | version = "0.11.2"
1341 | source = "registry+https://github.com/rust-lang/crates.io-index"
1342 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
1343 | dependencies = [
1344 | "phf_macros",
1345 | "phf_shared 0.11.2",
1346 | ]
1347 |
1348 | [[package]]
1349 | name = "phf_codegen"
1350 | version = "0.11.2"
1351 | source = "registry+https://github.com/rust-lang/crates.io-index"
1352 | checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
1353 | dependencies = [
1354 | "phf_generator 0.11.2",
1355 | "phf_shared 0.11.2",
1356 | ]
1357 |
1358 | [[package]]
1359 | name = "phf_generator"
1360 | version = "0.10.0"
1361 | source = "registry+https://github.com/rust-lang/crates.io-index"
1362 | checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
1363 | dependencies = [
1364 | "phf_shared 0.10.0",
1365 | "rand",
1366 | ]
1367 |
1368 | [[package]]
1369 | name = "phf_generator"
1370 | version = "0.11.2"
1371 | source = "registry+https://github.com/rust-lang/crates.io-index"
1372 | checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
1373 | dependencies = [
1374 | "phf_shared 0.11.2",
1375 | "rand",
1376 | ]
1377 |
1378 | [[package]]
1379 | name = "phf_macros"
1380 | version = "0.11.2"
1381 | source = "registry+https://github.com/rust-lang/crates.io-index"
1382 | checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
1383 | dependencies = [
1384 | "phf_generator 0.11.2",
1385 | "phf_shared 0.11.2",
1386 | "proc-macro2",
1387 | "quote",
1388 | "syn 2.0.57",
1389 | ]
1390 |
1391 | [[package]]
1392 | name = "phf_shared"
1393 | version = "0.10.0"
1394 | source = "registry+https://github.com/rust-lang/crates.io-index"
1395 | checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
1396 | dependencies = [
1397 | "siphasher",
1398 | ]
1399 |
1400 | [[package]]
1401 | name = "phf_shared"
1402 | version = "0.11.2"
1403 | source = "registry+https://github.com/rust-lang/crates.io-index"
1404 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
1405 | dependencies = [
1406 | "siphasher",
1407 | ]
1408 |
1409 | [[package]]
1410 | name = "pin-project"
1411 | version = "1.1.5"
1412 | source = "registry+https://github.com/rust-lang/crates.io-index"
1413 | checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
1414 | dependencies = [
1415 | "pin-project-internal",
1416 | ]
1417 |
1418 | [[package]]
1419 | name = "pin-project-internal"
1420 | version = "1.1.5"
1421 | source = "registry+https://github.com/rust-lang/crates.io-index"
1422 | checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
1423 | dependencies = [
1424 | "proc-macro2",
1425 | "quote",
1426 | "syn 2.0.57",
1427 | ]
1428 |
1429 | [[package]]
1430 | name = "pin-project-lite"
1431 | version = "0.2.14"
1432 | source = "registry+https://github.com/rust-lang/crates.io-index"
1433 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
1434 |
1435 | [[package]]
1436 | name = "pin-utils"
1437 | version = "0.1.0"
1438 | source = "registry+https://github.com/rust-lang/crates.io-index"
1439 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
1440 |
1441 | [[package]]
1442 | name = "pkg-config"
1443 | version = "0.3.30"
1444 | source = "registry+https://github.com/rust-lang/crates.io-index"
1445 | checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
1446 |
1447 | [[package]]
1448 | name = "plain"
1449 | version = "0.2.3"
1450 | source = "registry+https://github.com/rust-lang/crates.io-index"
1451 | checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
1452 |
1453 | [[package]]
1454 | name = "polyval"
1455 | version = "0.5.3"
1456 | source = "registry+https://github.com/rust-lang/crates.io-index"
1457 | checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
1458 | dependencies = [
1459 | "cfg-if",
1460 | "cpufeatures",
1461 | "opaque-debug",
1462 | "universal-hash",
1463 | ]
1464 |
1465 | [[package]]
1466 | name = "ppv-lite86"
1467 | version = "0.2.17"
1468 | source = "registry+https://github.com/rust-lang/crates.io-index"
1469 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
1470 |
1471 | [[package]]
1472 | name = "precomputed-hash"
1473 | version = "0.1.1"
1474 | source = "registry+https://github.com/rust-lang/crates.io-index"
1475 | checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
1476 |
1477 | [[package]]
1478 | name = "proc-macro2"
1479 | version = "1.0.79"
1480 | source = "registry+https://github.com/rust-lang/crates.io-index"
1481 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
1482 | dependencies = [
1483 | "unicode-ident",
1484 | ]
1485 |
1486 | [[package]]
1487 | name = "quote"
1488 | version = "1.0.35"
1489 | source = "registry+https://github.com/rust-lang/crates.io-index"
1490 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
1491 | dependencies = [
1492 | "proc-macro2",
1493 | ]
1494 |
1495 | [[package]]
1496 | name = "rand"
1497 | version = "0.8.5"
1498 | source = "registry+https://github.com/rust-lang/crates.io-index"
1499 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
1500 | dependencies = [
1501 | "libc",
1502 | "rand_chacha",
1503 | "rand_core",
1504 | ]
1505 |
1506 | [[package]]
1507 | name = "rand_chacha"
1508 | version = "0.3.1"
1509 | source = "registry+https://github.com/rust-lang/crates.io-index"
1510 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
1511 | dependencies = [
1512 | "ppv-lite86",
1513 | "rand_core",
1514 | ]
1515 |
1516 | [[package]]
1517 | name = "rand_core"
1518 | version = "0.6.4"
1519 | source = "registry+https://github.com/rust-lang/crates.io-index"
1520 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
1521 | dependencies = [
1522 | "getrandom",
1523 | ]
1524 |
1525 | [[package]]
1526 | name = "redox_syscall"
1527 | version = "0.5.7"
1528 | source = "registry+https://github.com/rust-lang/crates.io-index"
1529 | checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
1530 | dependencies = [
1531 | "bitflags 2.5.0",
1532 | ]
1533 |
1534 | [[package]]
1535 | name = "redox_users"
1536 | version = "0.4.6"
1537 | source = "registry+https://github.com/rust-lang/crates.io-index"
1538 | checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
1539 | dependencies = [
1540 | "getrandom",
1541 | "libredox",
1542 | "thiserror",
1543 | ]
1544 |
1545 | [[package]]
1546 | name = "reqwest"
1547 | version = "0.12.2"
1548 | source = "registry+https://github.com/rust-lang/crates.io-index"
1549 | checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338"
1550 | dependencies = [
1551 | "base64 0.21.7",
1552 | "bytes",
1553 | "encoding_rs",
1554 | "futures-channel",
1555 | "futures-core",
1556 | "futures-util",
1557 | "h2",
1558 | "http",
1559 | "http-body",
1560 | "http-body-util",
1561 | "hyper",
1562 | "hyper-tls",
1563 | "hyper-util",
1564 | "ipnet",
1565 | "js-sys",
1566 | "log",
1567 | "mime",
1568 | "native-tls",
1569 | "once_cell",
1570 | "percent-encoding",
1571 | "pin-project-lite",
1572 | "rustls-pemfile",
1573 | "serde",
1574 | "serde_json",
1575 | "serde_urlencoded",
1576 | "sync_wrapper",
1577 | "system-configuration",
1578 | "tokio",
1579 | "tokio-native-tls",
1580 | "tower-service",
1581 | "url",
1582 | "wasm-bindgen",
1583 | "wasm-bindgen-futures",
1584 | "web-sys",
1585 | "winreg",
1586 | ]
1587 |
1588 | [[package]]
1589 | name = "ring"
1590 | version = "0.16.20"
1591 | source = "registry+https://github.com/rust-lang/crates.io-index"
1592 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
1593 | dependencies = [
1594 | "cc",
1595 | "libc",
1596 | "once_cell",
1597 | "spin",
1598 | "untrusted",
1599 | "web-sys",
1600 | "winapi",
1601 | ]
1602 |
1603 | [[package]]
1604 | name = "rustc-demangle"
1605 | version = "0.1.23"
1606 | source = "registry+https://github.com/rust-lang/crates.io-index"
1607 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
1608 |
1609 | [[package]]
1610 | name = "rustix"
1611 | version = "0.38.32"
1612 | source = "registry+https://github.com/rust-lang/crates.io-index"
1613 | checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
1614 | dependencies = [
1615 | "bitflags 2.5.0",
1616 | "errno",
1617 | "libc",
1618 | "linux-raw-sys",
1619 | "windows-sys 0.52.0",
1620 | ]
1621 |
1622 | [[package]]
1623 | name = "rustls-pemfile"
1624 | version = "1.0.4"
1625 | source = "registry+https://github.com/rust-lang/crates.io-index"
1626 | checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
1627 | dependencies = [
1628 | "base64 0.21.7",
1629 | ]
1630 |
1631 | [[package]]
1632 | name = "ryu"
1633 | version = "1.0.17"
1634 | source = "registry+https://github.com/rust-lang/crates.io-index"
1635 | checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
1636 |
1637 | [[package]]
1638 | name = "schannel"
1639 | version = "0.1.23"
1640 | source = "registry+https://github.com/rust-lang/crates.io-index"
1641 | checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
1642 | dependencies = [
1643 | "windows-sys 0.52.0",
1644 | ]
1645 |
1646 | [[package]]
1647 | name = "scopeguard"
1648 | version = "1.2.0"
1649 | source = "registry+https://github.com/rust-lang/crates.io-index"
1650 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1651 |
1652 | [[package]]
1653 | name = "scraper"
1654 | version = "0.21.0"
1655 | source = "registry+https://github.com/rust-lang/crates.io-index"
1656 | checksum = "b0e749d29b2064585327af5038a5a8eb73aeebad4a3472e83531a436563f7208"
1657 | dependencies = [
1658 | "ahash",
1659 | "cssparser",
1660 | "ego-tree",
1661 | "getopts",
1662 | "html5ever",
1663 | "precomputed-hash",
1664 | "selectors",
1665 | "tendril",
1666 | ]
1667 |
1668 | [[package]]
1669 | name = "scroll"
1670 | version = "0.12.0"
1671 | source = "registry+https://github.com/rust-lang/crates.io-index"
1672 | checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6"
1673 | dependencies = [
1674 | "scroll_derive",
1675 | ]
1676 |
1677 | [[package]]
1678 | name = "scroll_derive"
1679 | version = "0.12.0"
1680 | source = "registry+https://github.com/rust-lang/crates.io-index"
1681 | checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
1682 | dependencies = [
1683 | "proc-macro2",
1684 | "quote",
1685 | "syn 2.0.57",
1686 | ]
1687 |
1688 | [[package]]
1689 | name = "security-framework"
1690 | version = "2.10.0"
1691 | source = "registry+https://github.com/rust-lang/crates.io-index"
1692 | checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6"
1693 | dependencies = [
1694 | "bitflags 1.3.2",
1695 | "core-foundation",
1696 | "core-foundation-sys",
1697 | "libc",
1698 | "security-framework-sys",
1699 | ]
1700 |
1701 | [[package]]
1702 | name = "security-framework-sys"
1703 | version = "2.10.0"
1704 | source = "registry+https://github.com/rust-lang/crates.io-index"
1705 | checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef"
1706 | dependencies = [
1707 | "core-foundation-sys",
1708 | "libc",
1709 | ]
1710 |
1711 | [[package]]
1712 | name = "selectors"
1713 | version = "0.26.0"
1714 | source = "registry+https://github.com/rust-lang/crates.io-index"
1715 | checksum = "fd568a4c9bb598e291a08244a5c1f5a8a6650bee243b5b0f8dbb3d9cc1d87fe8"
1716 | dependencies = [
1717 | "bitflags 2.5.0",
1718 | "cssparser",
1719 | "derive_more",
1720 | "fxhash",
1721 | "log",
1722 | "new_debug_unreachable",
1723 | "phf",
1724 | "phf_codegen",
1725 | "precomputed-hash",
1726 | "servo_arc",
1727 | "smallvec",
1728 | ]
1729 |
1730 | [[package]]
1731 | name = "semver"
1732 | version = "1.0.22"
1733 | source = "registry+https://github.com/rust-lang/crates.io-index"
1734 | checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
1735 | dependencies = [
1736 | "serde",
1737 | ]
1738 |
1739 | [[package]]
1740 | name = "serde"
1741 | version = "1.0.197"
1742 | source = "registry+https://github.com/rust-lang/crates.io-index"
1743 | checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
1744 | dependencies = [
1745 | "serde_derive",
1746 | ]
1747 |
1748 | [[package]]
1749 | name = "serde_derive"
1750 | version = "1.0.197"
1751 | source = "registry+https://github.com/rust-lang/crates.io-index"
1752 | checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
1753 | dependencies = [
1754 | "proc-macro2",
1755 | "quote",
1756 | "syn 2.0.57",
1757 | ]
1758 |
1759 | [[package]]
1760 | name = "serde_json"
1761 | version = "1.0.115"
1762 | source = "registry+https://github.com/rust-lang/crates.io-index"
1763 | checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
1764 | dependencies = [
1765 | "itoa",
1766 | "ryu",
1767 | "serde",
1768 | ]
1769 |
1770 | [[package]]
1771 | name = "serde_urlencoded"
1772 | version = "0.7.1"
1773 | source = "registry+https://github.com/rust-lang/crates.io-index"
1774 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
1775 | dependencies = [
1776 | "form_urlencoded",
1777 | "itoa",
1778 | "ryu",
1779 | "serde",
1780 | ]
1781 |
1782 | [[package]]
1783 | name = "serde_with"
1784 | version = "1.14.0"
1785 | source = "registry+https://github.com/rust-lang/crates.io-index"
1786 | checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff"
1787 | dependencies = [
1788 | "serde",
1789 | "serde_with_macros",
1790 | ]
1791 |
1792 | [[package]]
1793 | name = "serde_with_macros"
1794 | version = "1.5.2"
1795 | source = "registry+https://github.com/rust-lang/crates.io-index"
1796 | checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
1797 | dependencies = [
1798 | "darling",
1799 | "proc-macro2",
1800 | "quote",
1801 | "syn 1.0.109",
1802 | ]
1803 |
1804 | [[package]]
1805 | name = "servo_arc"
1806 | version = "0.4.0"
1807 | source = "registry+https://github.com/rust-lang/crates.io-index"
1808 | checksum = "ae65c4249478a2647db249fb43e23cec56a2c8974a427e7bd8cb5a1d0964921a"
1809 | dependencies = [
1810 | "stable_deref_trait",
1811 | ]
1812 |
1813 | [[package]]
1814 | name = "sha2"
1815 | version = "0.9.9"
1816 | source = "registry+https://github.com/rust-lang/crates.io-index"
1817 | checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
1818 | dependencies = [
1819 | "block-buffer",
1820 | "cfg-if",
1821 | "cpufeatures",
1822 | "digest",
1823 | "opaque-debug",
1824 | ]
1825 |
1826 | [[package]]
1827 | name = "siphasher"
1828 | version = "0.3.11"
1829 | source = "registry+https://github.com/rust-lang/crates.io-index"
1830 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
1831 |
1832 | [[package]]
1833 | name = "slab"
1834 | version = "0.4.9"
1835 | source = "registry+https://github.com/rust-lang/crates.io-index"
1836 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
1837 | dependencies = [
1838 | "autocfg",
1839 | ]
1840 |
1841 | [[package]]
1842 | name = "smallvec"
1843 | version = "1.13.2"
1844 | source = "registry+https://github.com/rust-lang/crates.io-index"
1845 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
1846 |
1847 | [[package]]
1848 | name = "smawk"
1849 | version = "0.3.2"
1850 | source = "registry+https://github.com/rust-lang/crates.io-index"
1851 | checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
1852 |
1853 | [[package]]
1854 | name = "socket2"
1855 | version = "0.5.6"
1856 | source = "registry+https://github.com/rust-lang/crates.io-index"
1857 | checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
1858 | dependencies = [
1859 | "libc",
1860 | "windows-sys 0.52.0",
1861 | ]
1862 |
1863 | [[package]]
1864 | name = "spin"
1865 | version = "0.5.2"
1866 | source = "registry+https://github.com/rust-lang/crates.io-index"
1867 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
1868 |
1869 | [[package]]
1870 | name = "stable_deref_trait"
1871 | version = "1.2.0"
1872 | source = "registry+https://github.com/rust-lang/crates.io-index"
1873 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
1874 |
1875 | [[package]]
1876 | name = "static_assertions"
1877 | version = "1.1.0"
1878 | source = "registry+https://github.com/rust-lang/crates.io-index"
1879 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1880 |
1881 | [[package]]
1882 | name = "string_cache"
1883 | version = "0.8.7"
1884 | source = "registry+https://github.com/rust-lang/crates.io-index"
1885 | checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
1886 | dependencies = [
1887 | "new_debug_unreachable",
1888 | "once_cell",
1889 | "parking_lot",
1890 | "phf_shared 0.10.0",
1891 | "precomputed-hash",
1892 | "serde",
1893 | ]
1894 |
1895 | [[package]]
1896 | name = "string_cache_codegen"
1897 | version = "0.5.2"
1898 | source = "registry+https://github.com/rust-lang/crates.io-index"
1899 | checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
1900 | dependencies = [
1901 | "phf_generator 0.10.0",
1902 | "phf_shared 0.10.0",
1903 | "proc-macro2",
1904 | "quote",
1905 | ]
1906 |
1907 | [[package]]
1908 | name = "strsim"
1909 | version = "0.10.0"
1910 | source = "registry+https://github.com/rust-lang/crates.io-index"
1911 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
1912 |
1913 | [[package]]
1914 | name = "strsim"
1915 | version = "0.11.1"
1916 | source = "registry+https://github.com/rust-lang/crates.io-index"
1917 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
1918 |
1919 | [[package]]
1920 | name = "subtle"
1921 | version = "2.4.1"
1922 | source = "registry+https://github.com/rust-lang/crates.io-index"
1923 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
1924 |
1925 | [[package]]
1926 | name = "syn"
1927 | version = "1.0.109"
1928 | source = "registry+https://github.com/rust-lang/crates.io-index"
1929 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
1930 | dependencies = [
1931 | "proc-macro2",
1932 | "quote",
1933 | "unicode-ident",
1934 | ]
1935 |
1936 | [[package]]
1937 | name = "syn"
1938 | version = "2.0.57"
1939 | source = "registry+https://github.com/rust-lang/crates.io-index"
1940 | checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35"
1941 | dependencies = [
1942 | "proc-macro2",
1943 | "quote",
1944 | "unicode-ident",
1945 | ]
1946 |
1947 | [[package]]
1948 | name = "sync_wrapper"
1949 | version = "0.1.2"
1950 | source = "registry+https://github.com/rust-lang/crates.io-index"
1951 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
1952 |
1953 | [[package]]
1954 | name = "system-configuration"
1955 | version = "0.5.1"
1956 | source = "registry+https://github.com/rust-lang/crates.io-index"
1957 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
1958 | dependencies = [
1959 | "bitflags 1.3.2",
1960 | "core-foundation",
1961 | "system-configuration-sys",
1962 | ]
1963 |
1964 | [[package]]
1965 | name = "system-configuration-sys"
1966 | version = "0.5.0"
1967 | source = "registry+https://github.com/rust-lang/crates.io-index"
1968 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
1969 | dependencies = [
1970 | "core-foundation-sys",
1971 | "libc",
1972 | ]
1973 |
1974 | [[package]]
1975 | name = "tempfile"
1976 | version = "3.10.1"
1977 | source = "registry+https://github.com/rust-lang/crates.io-index"
1978 | checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
1979 | dependencies = [
1980 | "cfg-if",
1981 | "fastrand",
1982 | "rustix",
1983 | "windows-sys 0.52.0",
1984 | ]
1985 |
1986 | [[package]]
1987 | name = "tendril"
1988 | version = "0.4.3"
1989 | source = "registry+https://github.com/rust-lang/crates.io-index"
1990 | checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0"
1991 | dependencies = [
1992 | "futf",
1993 | "mac",
1994 | "utf-8",
1995 | ]
1996 |
1997 | [[package]]
1998 | name = "terminal_size"
1999 | version = "0.1.17"
2000 | source = "registry+https://github.com/rust-lang/crates.io-index"
2001 | checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
2002 | dependencies = [
2003 | "libc",
2004 | "winapi",
2005 | ]
2006 |
2007 | [[package]]
2008 | name = "textwrap"
2009 | version = "0.16.1"
2010 | source = "registry+https://github.com/rust-lang/crates.io-index"
2011 | checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
2012 | dependencies = [
2013 | "smawk",
2014 | ]
2015 |
2016 | [[package]]
2017 | name = "thiserror"
2018 | version = "1.0.59"
2019 | source = "registry+https://github.com/rust-lang/crates.io-index"
2020 | checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
2021 | dependencies = [
2022 | "thiserror-impl",
2023 | ]
2024 |
2025 | [[package]]
2026 | name = "thiserror-impl"
2027 | version = "1.0.59"
2028 | source = "registry+https://github.com/rust-lang/crates.io-index"
2029 | checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
2030 | dependencies = [
2031 | "proc-macro2",
2032 | "quote",
2033 | "syn 2.0.57",
2034 | ]
2035 |
2036 | [[package]]
2037 | name = "tinyvec"
2038 | version = "1.6.0"
2039 | source = "registry+https://github.com/rust-lang/crates.io-index"
2040 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
2041 | dependencies = [
2042 | "tinyvec_macros",
2043 | ]
2044 |
2045 | [[package]]
2046 | name = "tinyvec_macros"
2047 | version = "0.1.1"
2048 | source = "registry+https://github.com/rust-lang/crates.io-index"
2049 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
2050 |
2051 | [[package]]
2052 | name = "tokio"
2053 | version = "1.37.0"
2054 | source = "registry+https://github.com/rust-lang/crates.io-index"
2055 | checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
2056 | dependencies = [
2057 | "backtrace",
2058 | "bytes",
2059 | "libc",
2060 | "mio",
2061 | "num_cpus",
2062 | "pin-project-lite",
2063 | "socket2",
2064 | "windows-sys 0.48.0",
2065 | ]
2066 |
2067 | [[package]]
2068 | name = "tokio-native-tls"
2069 | version = "0.3.1"
2070 | source = "registry+https://github.com/rust-lang/crates.io-index"
2071 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
2072 | dependencies = [
2073 | "native-tls",
2074 | "tokio",
2075 | ]
2076 |
2077 | [[package]]
2078 | name = "tokio-util"
2079 | version = "0.7.10"
2080 | source = "registry+https://github.com/rust-lang/crates.io-index"
2081 | checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
2082 | dependencies = [
2083 | "bytes",
2084 | "futures-core",
2085 | "futures-sink",
2086 | "pin-project-lite",
2087 | "tokio",
2088 | "tracing",
2089 | ]
2090 |
2091 | [[package]]
2092 | name = "toml"
2093 | version = "0.5.11"
2094 | source = "registry+https://github.com/rust-lang/crates.io-index"
2095 | checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
2096 | dependencies = [
2097 | "serde",
2098 | ]
2099 |
2100 | [[package]]
2101 | name = "tower"
2102 | version = "0.4.13"
2103 | source = "registry+https://github.com/rust-lang/crates.io-index"
2104 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
2105 | dependencies = [
2106 | "futures-core",
2107 | "futures-util",
2108 | "pin-project",
2109 | "pin-project-lite",
2110 | "tokio",
2111 | "tower-layer",
2112 | "tower-service",
2113 | "tracing",
2114 | ]
2115 |
2116 | [[package]]
2117 | name = "tower-layer"
2118 | version = "0.3.2"
2119 | source = "registry+https://github.com/rust-lang/crates.io-index"
2120 | checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
2121 |
2122 | [[package]]
2123 | name = "tower-service"
2124 | version = "0.3.2"
2125 | source = "registry+https://github.com/rust-lang/crates.io-index"
2126 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
2127 |
2128 | [[package]]
2129 | name = "tracing"
2130 | version = "0.1.40"
2131 | source = "registry+https://github.com/rust-lang/crates.io-index"
2132 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
2133 | dependencies = [
2134 | "log",
2135 | "pin-project-lite",
2136 | "tracing-core",
2137 | ]
2138 |
2139 | [[package]]
2140 | name = "tracing-core"
2141 | version = "0.1.32"
2142 | source = "registry+https://github.com/rust-lang/crates.io-index"
2143 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
2144 | dependencies = [
2145 | "once_cell",
2146 | ]
2147 |
2148 | [[package]]
2149 | name = "try-lock"
2150 | version = "0.2.5"
2151 | source = "registry+https://github.com/rust-lang/crates.io-index"
2152 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
2153 |
2154 | [[package]]
2155 | name = "typenum"
2156 | version = "1.17.0"
2157 | source = "registry+https://github.com/rust-lang/crates.io-index"
2158 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
2159 |
2160 | [[package]]
2161 | name = "unicase"
2162 | version = "2.7.0"
2163 | source = "registry+https://github.com/rust-lang/crates.io-index"
2164 | checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
2165 | dependencies = [
2166 | "version_check",
2167 | ]
2168 |
2169 | [[package]]
2170 | name = "unicode-bidi"
2171 | version = "0.3.15"
2172 | source = "registry+https://github.com/rust-lang/crates.io-index"
2173 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
2174 |
2175 | [[package]]
2176 | name = "unicode-ident"
2177 | version = "1.0.12"
2178 | source = "registry+https://github.com/rust-lang/crates.io-index"
2179 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
2180 |
2181 | [[package]]
2182 | name = "unicode-normalization"
2183 | version = "0.1.23"
2184 | source = "registry+https://github.com/rust-lang/crates.io-index"
2185 | checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
2186 | dependencies = [
2187 | "tinyvec",
2188 | ]
2189 |
2190 | [[package]]
2191 | name = "unicode-width"
2192 | version = "0.1.11"
2193 | source = "registry+https://github.com/rust-lang/crates.io-index"
2194 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
2195 |
2196 | [[package]]
2197 | name = "uniffi"
2198 | version = "0.28.0"
2199 | source = "registry+https://github.com/rust-lang/crates.io-index"
2200 | checksum = "f31bff6daf87277a9014bcdefbc2842b0553392919d1096843c5aad899ca4588"
2201 | dependencies = [
2202 | "anyhow",
2203 | "camino",
2204 | "clap",
2205 | "uniffi_bindgen",
2206 | "uniffi_core",
2207 | "uniffi_macros",
2208 | ]
2209 |
2210 | [[package]]
2211 | name = "uniffi_bindgen"
2212 | version = "0.28.0"
2213 | source = "registry+https://github.com/rust-lang/crates.io-index"
2214 | checksum = "96061d7e01b185aa405f7c9b134741ab3e50cc6796a47d6fd8ab9a5364b5feed"
2215 | dependencies = [
2216 | "anyhow",
2217 | "askama",
2218 | "camino",
2219 | "cargo_metadata",
2220 | "fs-err",
2221 | "glob",
2222 | "goblin",
2223 | "heck",
2224 | "once_cell",
2225 | "paste",
2226 | "serde",
2227 | "textwrap",
2228 | "toml",
2229 | "uniffi_meta",
2230 | "uniffi_testing",
2231 | "uniffi_udl",
2232 | ]
2233 |
2234 | [[package]]
2235 | name = "uniffi_checksum_derive"
2236 | version = "0.28.0"
2237 | source = "registry+https://github.com/rust-lang/crates.io-index"
2238 | checksum = "2fcfa22f55829d3aaa7acfb1c5150224188fe0f27c59a8a3eddcaa24d1ffbe58"
2239 | dependencies = [
2240 | "quote",
2241 | "syn 2.0.57",
2242 | ]
2243 |
2244 | [[package]]
2245 | name = "uniffi_core"
2246 | version = "0.28.0"
2247 | source = "registry+https://github.com/rust-lang/crates.io-index"
2248 | checksum = "3210d57d6ab6065ab47a2898dacdb7c606fd6a4156196831fa3bf82e34ac58a6"
2249 | dependencies = [
2250 | "anyhow",
2251 | "bytes",
2252 | "camino",
2253 | "log",
2254 | "once_cell",
2255 | "paste",
2256 | "static_assertions",
2257 | ]
2258 |
2259 | [[package]]
2260 | name = "uniffi_macros"
2261 | version = "0.28.0"
2262 | source = "registry+https://github.com/rust-lang/crates.io-index"
2263 | checksum = "b58691741080935437dc862122e68d7414432a11824ac1137868de46181a0bd2"
2264 | dependencies = [
2265 | "bincode",
2266 | "camino",
2267 | "fs-err",
2268 | "once_cell",
2269 | "proc-macro2",
2270 | "quote",
2271 | "serde",
2272 | "syn 2.0.57",
2273 | "toml",
2274 | "uniffi_meta",
2275 | ]
2276 |
2277 | [[package]]
2278 | name = "uniffi_meta"
2279 | version = "0.28.0"
2280 | source = "registry+https://github.com/rust-lang/crates.io-index"
2281 | checksum = "7663eacdbd9fbf4a88907ddcfe2e6fa85838eb6dc2418a7d91eebb3786f8e20b"
2282 | dependencies = [
2283 | "anyhow",
2284 | "bytes",
2285 | "siphasher",
2286 | "uniffi_checksum_derive",
2287 | ]
2288 |
2289 | [[package]]
2290 | name = "uniffi_testing"
2291 | version = "0.28.0"
2292 | source = "registry+https://github.com/rust-lang/crates.io-index"
2293 | checksum = "f922465f7566f25f8fe766920205fdfa9a3fcdc209c6bfb7557f0b5bf45b04dd"
2294 | dependencies = [
2295 | "anyhow",
2296 | "camino",
2297 | "cargo_metadata",
2298 | "fs-err",
2299 | "once_cell",
2300 | ]
2301 |
2302 | [[package]]
2303 | name = "uniffi_udl"
2304 | version = "0.28.0"
2305 | source = "registry+https://github.com/rust-lang/crates.io-index"
2306 | checksum = "cef408229a3a407fafa4c36dc4f6ece78a6fb258ab28d2b64bddd49c8cb680f6"
2307 | dependencies = [
2308 | "anyhow",
2309 | "textwrap",
2310 | "uniffi_meta",
2311 | "uniffi_testing",
2312 | "weedle2",
2313 | ]
2314 |
2315 | [[package]]
2316 | name = "universal-hash"
2317 | version = "0.4.1"
2318 | source = "registry+https://github.com/rust-lang/crates.io-index"
2319 | checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
2320 | dependencies = [
2321 | "generic-array",
2322 | "subtle",
2323 | ]
2324 |
2325 | [[package]]
2326 | name = "untrusted"
2327 | version = "0.7.1"
2328 | source = "registry+https://github.com/rust-lang/crates.io-index"
2329 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
2330 |
2331 | [[package]]
2332 | name = "url"
2333 | version = "2.5.0"
2334 | source = "registry+https://github.com/rust-lang/crates.io-index"
2335 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
2336 | dependencies = [
2337 | "form_urlencoded",
2338 | "idna",
2339 | "percent-encoding",
2340 | "serde",
2341 | ]
2342 |
2343 | [[package]]
2344 | name = "utf-8"
2345 | version = "0.7.6"
2346 | source = "registry+https://github.com/rust-lang/crates.io-index"
2347 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
2348 |
2349 | [[package]]
2350 | name = "utf8parse"
2351 | version = "0.2.1"
2352 | source = "registry+https://github.com/rust-lang/crates.io-index"
2353 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
2354 |
2355 | [[package]]
2356 | name = "vcpkg"
2357 | version = "0.2.15"
2358 | source = "registry+https://github.com/rust-lang/crates.io-index"
2359 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
2360 |
2361 | [[package]]
2362 | name = "version_check"
2363 | version = "0.9.4"
2364 | source = "registry+https://github.com/rust-lang/crates.io-index"
2365 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
2366 |
2367 | [[package]]
2368 | name = "want"
2369 | version = "0.3.1"
2370 | source = "registry+https://github.com/rust-lang/crates.io-index"
2371 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
2372 | dependencies = [
2373 | "try-lock",
2374 | ]
2375 |
2376 | [[package]]
2377 | name = "wasi"
2378 | version = "0.11.0+wasi-snapshot-preview1"
2379 | source = "registry+https://github.com/rust-lang/crates.io-index"
2380 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
2381 |
2382 | [[package]]
2383 | name = "wasm-bindgen"
2384 | version = "0.2.92"
2385 | source = "registry+https://github.com/rust-lang/crates.io-index"
2386 | checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
2387 | dependencies = [
2388 | "cfg-if",
2389 | "wasm-bindgen-macro",
2390 | ]
2391 |
2392 | [[package]]
2393 | name = "wasm-bindgen-backend"
2394 | version = "0.2.92"
2395 | source = "registry+https://github.com/rust-lang/crates.io-index"
2396 | checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
2397 | dependencies = [
2398 | "bumpalo",
2399 | "log",
2400 | "once_cell",
2401 | "proc-macro2",
2402 | "quote",
2403 | "syn 2.0.57",
2404 | "wasm-bindgen-shared",
2405 | ]
2406 |
2407 | [[package]]
2408 | name = "wasm-bindgen-futures"
2409 | version = "0.4.42"
2410 | source = "registry+https://github.com/rust-lang/crates.io-index"
2411 | checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
2412 | dependencies = [
2413 | "cfg-if",
2414 | "js-sys",
2415 | "wasm-bindgen",
2416 | "web-sys",
2417 | ]
2418 |
2419 | [[package]]
2420 | name = "wasm-bindgen-macro"
2421 | version = "0.2.92"
2422 | source = "registry+https://github.com/rust-lang/crates.io-index"
2423 | checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
2424 | dependencies = [
2425 | "quote",
2426 | "wasm-bindgen-macro-support",
2427 | ]
2428 |
2429 | [[package]]
2430 | name = "wasm-bindgen-macro-support"
2431 | version = "0.2.92"
2432 | source = "registry+https://github.com/rust-lang/crates.io-index"
2433 | checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
2434 | dependencies = [
2435 | "proc-macro2",
2436 | "quote",
2437 | "syn 2.0.57",
2438 | "wasm-bindgen-backend",
2439 | "wasm-bindgen-shared",
2440 | ]
2441 |
2442 | [[package]]
2443 | name = "wasm-bindgen-shared"
2444 | version = "0.2.92"
2445 | source = "registry+https://github.com/rust-lang/crates.io-index"
2446 | checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
2447 |
2448 | [[package]]
2449 | name = "web-sys"
2450 | version = "0.3.69"
2451 | source = "registry+https://github.com/rust-lang/crates.io-index"
2452 | checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
2453 | dependencies = [
2454 | "js-sys",
2455 | "wasm-bindgen",
2456 | ]
2457 |
2458 | [[package]]
2459 | name = "weedle2"
2460 | version = "5.0.0"
2461 | source = "registry+https://github.com/rust-lang/crates.io-index"
2462 | checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e"
2463 | dependencies = [
2464 | "nom",
2465 | ]
2466 |
2467 | [[package]]
2468 | name = "winapi"
2469 | version = "0.3.9"
2470 | source = "registry+https://github.com/rust-lang/crates.io-index"
2471 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
2472 | dependencies = [
2473 | "winapi-i686-pc-windows-gnu",
2474 | "winapi-x86_64-pc-windows-gnu",
2475 | ]
2476 |
2477 | [[package]]
2478 | name = "winapi-i686-pc-windows-gnu"
2479 | version = "0.4.0"
2480 | source = "registry+https://github.com/rust-lang/crates.io-index"
2481 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
2482 |
2483 | [[package]]
2484 | name = "winapi-x86_64-pc-windows-gnu"
2485 | version = "0.4.0"
2486 | source = "registry+https://github.com/rust-lang/crates.io-index"
2487 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
2488 |
2489 | [[package]]
2490 | name = "windows-sys"
2491 | version = "0.48.0"
2492 | source = "registry+https://github.com/rust-lang/crates.io-index"
2493 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
2494 | dependencies = [
2495 | "windows-targets 0.48.5",
2496 | ]
2497 |
2498 | [[package]]
2499 | name = "windows-sys"
2500 | version = "0.52.0"
2501 | source = "registry+https://github.com/rust-lang/crates.io-index"
2502 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
2503 | dependencies = [
2504 | "windows-targets 0.52.4",
2505 | ]
2506 |
2507 | [[package]]
2508 | name = "windows-targets"
2509 | version = "0.48.5"
2510 | source = "registry+https://github.com/rust-lang/crates.io-index"
2511 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
2512 | dependencies = [
2513 | "windows_aarch64_gnullvm 0.48.5",
2514 | "windows_aarch64_msvc 0.48.5",
2515 | "windows_i686_gnu 0.48.5",
2516 | "windows_i686_msvc 0.48.5",
2517 | "windows_x86_64_gnu 0.48.5",
2518 | "windows_x86_64_gnullvm 0.48.5",
2519 | "windows_x86_64_msvc 0.48.5",
2520 | ]
2521 |
2522 | [[package]]
2523 | name = "windows-targets"
2524 | version = "0.52.4"
2525 | source = "registry+https://github.com/rust-lang/crates.io-index"
2526 | checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
2527 | dependencies = [
2528 | "windows_aarch64_gnullvm 0.52.4",
2529 | "windows_aarch64_msvc 0.52.4",
2530 | "windows_i686_gnu 0.52.4",
2531 | "windows_i686_msvc 0.52.4",
2532 | "windows_x86_64_gnu 0.52.4",
2533 | "windows_x86_64_gnullvm 0.52.4",
2534 | "windows_x86_64_msvc 0.52.4",
2535 | ]
2536 |
2537 | [[package]]
2538 | name = "windows_aarch64_gnullvm"
2539 | version = "0.48.5"
2540 | source = "registry+https://github.com/rust-lang/crates.io-index"
2541 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
2542 |
2543 | [[package]]
2544 | name = "windows_aarch64_gnullvm"
2545 | version = "0.52.4"
2546 | source = "registry+https://github.com/rust-lang/crates.io-index"
2547 | checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
2548 |
2549 | [[package]]
2550 | name = "windows_aarch64_msvc"
2551 | version = "0.48.5"
2552 | source = "registry+https://github.com/rust-lang/crates.io-index"
2553 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
2554 |
2555 | [[package]]
2556 | name = "windows_aarch64_msvc"
2557 | version = "0.52.4"
2558 | source = "registry+https://github.com/rust-lang/crates.io-index"
2559 | checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
2560 |
2561 | [[package]]
2562 | name = "windows_i686_gnu"
2563 | version = "0.48.5"
2564 | source = "registry+https://github.com/rust-lang/crates.io-index"
2565 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
2566 |
2567 | [[package]]
2568 | name = "windows_i686_gnu"
2569 | version = "0.52.4"
2570 | source = "registry+https://github.com/rust-lang/crates.io-index"
2571 | checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
2572 |
2573 | [[package]]
2574 | name = "windows_i686_msvc"
2575 | version = "0.48.5"
2576 | source = "registry+https://github.com/rust-lang/crates.io-index"
2577 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
2578 |
2579 | [[package]]
2580 | name = "windows_i686_msvc"
2581 | version = "0.52.4"
2582 | source = "registry+https://github.com/rust-lang/crates.io-index"
2583 | checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
2584 |
2585 | [[package]]
2586 | name = "windows_x86_64_gnu"
2587 | version = "0.48.5"
2588 | source = "registry+https://github.com/rust-lang/crates.io-index"
2589 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
2590 |
2591 | [[package]]
2592 | name = "windows_x86_64_gnu"
2593 | version = "0.52.4"
2594 | source = "registry+https://github.com/rust-lang/crates.io-index"
2595 | checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
2596 |
2597 | [[package]]
2598 | name = "windows_x86_64_gnullvm"
2599 | version = "0.48.5"
2600 | source = "registry+https://github.com/rust-lang/crates.io-index"
2601 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
2602 |
2603 | [[package]]
2604 | name = "windows_x86_64_gnullvm"
2605 | version = "0.52.4"
2606 | source = "registry+https://github.com/rust-lang/crates.io-index"
2607 | checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
2608 |
2609 | [[package]]
2610 | name = "windows_x86_64_msvc"
2611 | version = "0.48.5"
2612 | source = "registry+https://github.com/rust-lang/crates.io-index"
2613 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
2614 |
2615 | [[package]]
2616 | name = "windows_x86_64_msvc"
2617 | version = "0.52.4"
2618 | source = "registry+https://github.com/rust-lang/crates.io-index"
2619 | checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
2620 |
2621 | [[package]]
2622 | name = "winreg"
2623 | version = "0.50.0"
2624 | source = "registry+https://github.com/rust-lang/crates.io-index"
2625 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
2626 | dependencies = [
2627 | "cfg-if",
2628 | "windows-sys 0.48.0",
2629 | ]
2630 |
2631 | [[package]]
2632 | name = "zerocopy"
2633 | version = "0.7.35"
2634 | source = "registry+https://github.com/rust-lang/crates.io-index"
2635 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
2636 | dependencies = [
2637 | "zerocopy-derive",
2638 | ]
2639 |
2640 | [[package]]
2641 | name = "zerocopy-derive"
2642 | version = "0.7.35"
2643 | source = "registry+https://github.com/rust-lang/crates.io-index"
2644 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
2645 | dependencies = [
2646 | "proc-macro2",
2647 | "quote",
2648 | "syn 2.0.57",
2649 | ]
2650 |
2651 | [[package]]
2652 | name = "zeroize"
2653 | version = "1.7.0"
2654 | source = "registry+https://github.com/rust-lang/crates.io-index"
2655 | checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
2656 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "pbcli"
3 | description = """
4 | pbcli is a command line client which allows to upload and download
5 | pastes from privatebin directly from the command line.
6 | """
7 | version = "2.8.0"
8 | authors = ["Mydayyy"]
9 | edition = "2021"
10 | documentation = "https://github.com/Mydayyy/pbcli"
11 | homepage = "https://github.com/Mydayyy/pbcli"
12 | repository = "https://github.com/Mydayyy/pbcli"
13 | keywords = ["privatebin", "pastebin", "pasteservice"]
14 | categories = ["command-line-utilities"]
15 | license = "Unlicense OR MIT"
16 |
17 | [lib]
18 | crate-type = ["lib", "cdylib", "staticlib"]
19 | name = "pbcli"
20 |
21 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
22 |
23 | [dependencies]
24 | clap = { version = "4.5.29", features = ["derive"] }
25 | reqwest = { version = "0.12", features = ["blocking", "json"] }
26 | serde = { version = "1.0.130", features = ["derive"] }
27 | serde_json = "1.0.69"
28 | serde_with = "1"
29 | miniz_oxide = "0.5.0"
30 | ring = "0.16"
31 | aes-gcm = { version = "0.9.4", features = ["aes"] }
32 | bs58 = "0.4.0"
33 | base64 = "0.13"
34 | typenum = "1.14.0"
35 | hex-literal = "0.3.3"
36 | pbkdf2 = "0.9.0"
37 | rand_core = { version = "0.6.3", features = ["std"] }
38 | crypto-mac = "0.11.1"
39 | hmac = "0.11.0"
40 | sha2 = "0.9.8"
41 | url = { version = "2.2.2", features = ["serde"] }
42 | rand_chacha = "0.3.1"
43 | dialoguer = "0.9.0"
44 | data-url = "0.1.1"
45 | mime_guess = "2.0.3"
46 | terminal_size = "0.1.17"
47 | parse-size = { version = "1.0.0", features = ["std"] }
48 | uniffi = { version = "0.28.0", optional = true, features = ["cli"] }
49 | openssl = { version = "0.10", features = ["vendored"] }
50 | directories = "5.0.1"
51 | log = "0.4.22"
52 | scraper = "0.21.0"
53 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Mydayyy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/LICENSE-UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Privatebin CLI
2 | ------------
3 | pbcli is a command line client which allows to upload and download
4 | pastes from privatebin directly from the command line.
5 |
6 | It is dual licensed under MIT or the [UNLICENSE](https://unlicense.org).
7 |
8 | ### Table of Contents
9 |
10 | * [Installation](#Installation)
11 | * [Building](#Building)
12 | * [User Guide](#User-Guide)
13 | * [Configuration Files](#Configuration-File)
14 | * [Roadmap](#Roadmap)
15 |
16 | ### Installation
17 |
18 | You can find pre-compiled binaries under the release tab in github.
19 |
20 | For Archlinux, it is [available inside the AUR](https://aur.archlinux.org/packages/pbcli/).
21 |
22 | ### Building
23 |
24 | pbcli is written in Rust, so you will need a rust toolchain to
25 | build it.
26 |
27 | ```
28 | git clone https://github.com/Mydayyy/pbcli.git
29 | cd pbcli
30 | cargo build --release
31 | ./target/release/pbcli --version
32 | ```
33 |
34 | ### User Guide
35 |
36 | pbcli is simple to use and only involves a few flags. The only
37 | needed argument is either the positional argument `URL` or the option flag
38 | `host`. If both are provided the positional argument URL takes
39 | precedence. To avoid specifying the host / url everytime you can
40 | take advantage of a config file as described [here](#Configuration-File).
41 |
42 | When posting a paste you can specify `--json` to receive post details. The output
43 | includes the base58 encoded key used to encrypt/decrypt the paste.
44 | Constructed paste url (including key) and delete url (including token) are also provided for convenience.
45 |
46 | Example output:
47 |
48 | ```json
49 | {
50 | "baseurl": "https://privatebin.net/",
51 | "bs58key": "GN3qty1kAFbsGi9FbKKXigXwux1eofhiZQXNVFRMrNQd",
52 | "deletetoken": "8536f6f8310ed4a9aae0e111b1763f5851cdbefe4c35e4b96bd690269635354a",
53 | "deleteurl": "https://privatebin.net/?pasteid=31e2e7b19481fa7d&deletetoken=8536f6f8310ed4a9aae0e111b1763f5851cdbefe4c35e4b96bd690269635354a",
54 | "id": "31e2e7b19481fa7d",
55 | "pasteurl": "https://privatebin.net/?31e2e7b19481fa7d#GN3qty1kAFbsGi9FbKKXigXwux1eofhiZQXNVFRMrNQd",
56 | "status": 0,
57 | "url": "/?31e2e7b19481fa7d"
58 | }
59 | ```
60 |
61 | ---
62 |
63 | #### Example usages to get a paste:
64 |
65 | ```
66 | pbcli https://privatebin.net/?f37ca34e72e2ef77#G8wFGVnpSb4pogzGbMMcgbDgeYkQ5cfcWkcsVwTQJmzd
67 | ```
68 |
69 | ```
70 | pbcli --host https://privatebin.net/?f37ca34e72e2ef77#G8wFGVnpSb4pogzGbMMcgbDgeYkQ5cfcWkcsVwTQJmzd
71 | ```
72 |
73 | ---
74 |
75 | #### Example usages to post a new poste
76 |
77 | ```
78 | echo 'TestPaste' | pbcli --host https://privatebin.net/
79 | ```
80 |
81 | ```
82 | echo 'TestPaste' | pbcli https://privatebin.net/ --json
83 | ```
84 |
85 | ```
86 | echo 'TestPaste' | pbcli --host https://privatebin.net/ --expire=1hour
87 | ```
88 |
89 | ```
90 | echo '## Title\nSome Markdown' | pbcli https://privatebin.net/ --format markdown
91 | ```
92 |
93 | ```
94 | echo 'TestPaste' | pbcli --host https://privatebin.net/ --burn
95 | ```
96 |
97 | ---
98 |
99 | #### CLI Help:
100 |
101 | ```
102 | pbcli is a command line client which allows to upload and download
103 | pastes from privatebin directly from the command line.
104 |
105 | Project home page: https://github.com/Mydayyy/pbcli
106 |
107 | Usage: pbcli [OPTIONS] [URL]
108 |
109 | Arguments:
110 | [URL]
111 |
112 | Options:
113 | --host
114 | -f, --format [default: plaintext] [possible values: plaintext, syntax, markdown]
115 | -e, --expire [default: 1week]
116 | --size-limit Prompt if the paste exceeds the given size. Fail in non-interactive environments.
117 | --json richer output: for delete_url, comments, etc
118 | -b, --burn enable burn on read for new paste
119 | -B, --no-burn disable burn if set
120 | -d, --discussion enable discussion for new paste
121 | -D, --no-discussion disable burn if set
122 | --comment make new comment on existing paste
123 | --comment-as use this nick for comment
124 | --comment-to reply to this parent comment
125 | -o, --download
126 | -w, --overwrite overwrite the file given with --download if it already exists
127 | -u, --upload
128 | -p, --password
129 | --oidc-token-url oidc token endpoint from which to obtain an access token
130 | --oidc-client-id client id to send to the token endpoint
131 | --oidc-username username to send to the token endpoint
132 | --oidc-password password to send to the token endpoint
133 | --debug print debug output to stderr
134 | --no-default-config do not look for config in default locations
135 | --scrape-expiries attempt scraping supported expiries of given host and exit
136 | -h, --help Print help
137 | -V, --version Print version
138 | ```
139 |
140 | ### Configuration File
141 |
142 | pbcli supports a configuration file to fine tune the default behaviour.
143 | You need to set the environment variable `PBCLI_CONFIG_PATH` to a file path. The file
144 | needs to contain flags you want to pass to pbcli, one per line.
145 | Lines starting with a # are ignored. An useful case for this may be
146 | setting a default instance to use by setting the --host argument.
147 |
148 | Additionally, pbcli will look in a few default directories to find a config. This can be disabled
149 | via the `--no-default-config` argument. The directories it checks are:
150 |
151 | - `$XDG_CONFIG_HOME/pbcli/config` if the XDG variable is set. Otherwise `$HOME/.config/pbcli/config`
152 | - /etc/pbcli/config
153 |
154 | As well as the windows and mac equivalents to those linux paths. Details can be found
155 | here: https://docs.rs/directories/latest/directories/struct.ProjectDirs.html#method.config_local_dir
156 |
157 | The debug mode can be used to troubleshoot config loading issues. It will print the used config as well
158 | as the directories that were searched for a config.
159 |
160 | Instead of typing `echo 'test' | pbcli https://privatebin.net/` you'll only need
161 | to type `echo 'test' | pbcli`
162 |
163 | Example config:
164 |
165 | ```
166 | --host=https://privatebin.net/
167 | --expire=1month
168 | ```
169 |
170 | ### Uniffi
171 |
172 | This projects offers uniffi bindings. In order to enable them,
173 | build the library with the uniffi feature enabled.
174 | You can learn more about uniffi [here](https://github.com/mozilla/uniffi-rs).
175 | Additionally to see an example integration of pbcli with uniffi
176 | enabled into an android project you can check out [sharepaste](https://github.com/nain-F49FF806/sharepaste.oo).
177 |
178 | ### Roadmap
179 |
180 | - Descriptive error messages
181 | - Add support for auth mechanism
182 | - Basic auth
183 | - ~~oauth~~ Added in v2.2.0 using Resource Owner Password Credential Grant flow
184 | - ~~Add support for file attachments~~ Added in v2.1.0
185 |
186 | ### Credits
187 |
188 | - [nain](https://github.com/nain-F49FF806) for the uniffi implementation
189 |
--------------------------------------------------------------------------------
/src/api.rs:
--------------------------------------------------------------------------------
1 | use crate::crypto::{encrypt, Decryptable};
2 | use crate::error::{PasteError, PbError, PbResult};
3 | use crate::opts::Opts;
4 | use crate::privatebin::{Comment, DecryptedComment, Paste, PostCommentResponse, PostPasteResponse};
5 | use crate::util::check_filesize;
6 | use crate::DecryptedPaste;
7 | use rand_chacha::rand_core::{RngCore, SeedableRng};
8 | use reqwest::{Method, Url};
9 | use scraper::{Html, Selector};
10 | use std::str::FromStr;
11 |
12 | #[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
13 | pub struct API {
14 | base: Url,
15 | opts: Opts,
16 | }
17 |
18 | #[cfg_attr(feature = "uniffi", uniffi::export)]
19 | impl API {
20 | #[cfg_attr(feature = "uniffi", uniffi::constructor)]
21 | pub fn new(mut url: Url, opts: Opts) -> Self {
22 | url.set_fragment(None);
23 | url.set_query(None);
24 | if !url.path().ends_with('/') {
25 | url.set_path(&format!("{}{}", url.path(), "/"))
26 | }
27 | Self { base: url, opts }
28 | }
29 | }
30 |
31 | impl API {
32 | fn get_oidc_access_token(&self) -> PbResult {
33 | let oidc_token_endpoint = self.opts.oidc_token_url.as_ref().unwrap();
34 | let oidc_client_id = self.opts.oidc_client_id.as_ref().unwrap();
35 | let oidc_username = self.opts.oidc_username.as_ref().unwrap();
36 | let oidc_password = self.opts.oidc_password.as_ref().unwrap();
37 |
38 | let mut post_fields = std::collections::HashMap::new();
39 | post_fields.insert("grant_type", "password");
40 | post_fields.insert("client_id", oidc_client_id);
41 | post_fields.insert("username", oidc_username);
42 | post_fields.insert("password", oidc_password);
43 |
44 | let client = reqwest::blocking::Client::builder().build()?;
45 | let mut request = client.post(oidc_token_endpoint);
46 | request = request.form(&post_fields);
47 |
48 | let response = request.send()?;
49 |
50 | if response.status().as_u16() != 200 {
51 | return Err(PbError::OidcBadRequest(response.json()?));
52 | }
53 |
54 | let access_token_response: serde_json::Value = response.json()?;
55 |
56 | let token_type = access_token_response
57 | .get("token_type")
58 | .unwrap()
59 | .as_str()
60 | .unwrap();
61 | if !token_type.eq_ignore_ascii_case("bearer") {
62 | return Err(PbError::InvalidTokenType(token_type.to_string()));
63 | }
64 |
65 | let token: String = access_token_response
66 | .get("access_token")
67 | .unwrap()
68 | .as_str()
69 | .unwrap()
70 | .to_string();
71 |
72 | Ok(token)
73 | }
74 |
75 | fn preconfigured_privatebin_request_builder(
76 | &self,
77 | method: &str,
78 | url: Url,
79 | json_request: bool,
80 | ) -> PbResult {
81 | let client = reqwest::blocking::Client::builder().build()?;
82 |
83 | let mut request = client.request(Method::from_str(method).unwrap(), url);
84 | if json_request {
85 | request = request.header("X-Requested-With", "JSONHttpRequest");
86 | }
87 |
88 | if self.opts.oidc_token_url.is_some() {
89 | let access_token = self.get_oidc_access_token()?;
90 | let auth_header = ["Bearer".into(), access_token].join(" ");
91 | request = request.header("Authorization", auth_header)
92 | }
93 |
94 | Ok(request)
95 | }
96 | }
97 |
98 | #[cfg_attr(feature = "uniffi", uniffi::export)]
99 | impl API {
100 | pub fn get_paste(&self, paste_id: &str) -> PbResult {
101 | let url = reqwest::Url::parse_with_params(self.base.as_str(), [("pasteid", paste_id)])?;
102 | let value: serde_json::Value = self
103 | .preconfigured_privatebin_request_builder("GET", url, true)?
104 | .send()?
105 | .json()?;
106 | let status: u32 = value.get("status").unwrap().as_u64().unwrap() as u32;
107 |
108 | match status {
109 | 0 => Ok(serde_json::from_value(value)?),
110 | 1 => Err(PasteError::PasteNotFound),
111 | s => Err(PasteError::UnknownPasteStatus(s)),
112 | }
113 | }
114 |
115 | pub fn post_paste(
116 | &self,
117 | content: &DecryptedPaste,
118 | password: &str,
119 | opts: &Opts,
120 | ) -> PbResult {
121 | let mut rng = rand_chacha::ChaCha20Rng::from_entropy();
122 | let mut paste_passphrase = [0u8; 32];
123 | rng.fill_bytes(&mut paste_passphrase);
124 |
125 | let mut paste = Paste {
126 | v: 2,
127 | ..Default::default()
128 | };
129 | paste.adata.format = opts.format;
130 | paste.adata.discuss = opts.discussion as u8;
131 | paste.adata.burn = opts.burn as u8;
132 | paste.meta.expire = Some(opts.expire.clone());
133 |
134 | let cipher = &paste.adata.cipher;
135 |
136 | let encrypted_content = encrypt(
137 | &serde_json::to_string(content)?,
138 | &paste_passphrase,
139 | password,
140 | &cipher.vec_kdf_salt()?,
141 | &cipher.vec_cipher_iv()?,
142 | cipher.kdf_iterations,
143 | &paste.get_adata_str(),
144 | )?;
145 |
146 | let b64_encrpyed_content = base64::encode(encrypted_content);
147 | check_filesize(b64_encrpyed_content.len() as u64, opts.size_limit);
148 | paste.ct = b64_encrpyed_content;
149 |
150 | let url = self.base.clone();
151 | let response = self
152 | .preconfigured_privatebin_request_builder("POST", url, true)?
153 | .body::(serde_json::to_string(&paste).unwrap())
154 | .send()?;
155 | let mut rsv: serde_json::Value = response.json()?;
156 | rsv["bs58key"] = serde_json::Value::String(bs58::encode(paste_passphrase).into_string());
157 | rsv["baseurl"] = serde_json::Value::String(self.base.to_string());
158 | let status: u32 = rsv.get("status").unwrap().as_u64().unwrap() as u32;
159 |
160 | match status {
161 | 0 => Ok(serde_json::from_value::(rsv)?),
162 | 1 => Err(PasteError::InvalidData),
163 | s => Err(PasteError::UnknownPasteStatus(s)),
164 | }
165 | }
166 |
167 | pub fn post_comment(
168 | &self,
169 | content: &DecryptedComment,
170 | paste_id: &str,
171 | parent_id: &str,
172 | bs58key: &str,
173 | password: &str,
174 | opts: &Opts,
175 | ) -> PbResult {
176 | let mut comment = Comment {
177 | v: 2,
178 | pasteid: paste_id.into(),
179 | parentid: parent_id.into(),
180 | ..Default::default()
181 | };
182 | let cipher = &comment.adata;
183 | let paste_passphrase = bs58::decode(bs58key).into_vec()?;
184 |
185 | let encrypted_content = encrypt(
186 | &serde_json::to_string(content)?,
187 | &paste_passphrase,
188 | password,
189 | &cipher.vec_kdf_salt()?,
190 | &cipher.vec_cipher_iv()?,
191 | cipher.kdf_iterations,
192 | &comment.get_adata_str(),
193 | )?;
194 |
195 | let b64_encrpyed_content = base64::encode(encrypted_content);
196 | check_filesize(b64_encrpyed_content.len() as u64, opts.size_limit);
197 | comment.ct = b64_encrpyed_content;
198 |
199 | let url = self.base.clone();
200 | let response = self
201 | .preconfigured_privatebin_request_builder("POST", url, true)?
202 | .body::(serde_json::to_string(&comment).unwrap())
203 | .send()?;
204 | let rsv: serde_json::Value = response.json()?;
205 | let status: u32 = rsv.get("status").unwrap().as_u64().unwrap() as u32;
206 |
207 | match status {
208 | 0 => Ok(serde_json::from_value::(rsv)?),
209 | 1 => Err(PasteError::InvalidData),
210 | s => Err(PasteError::UnknownPasteStatus(s)),
211 | }
212 | }
213 |
214 | pub fn scrape_expiries(&self) -> PbResult> {
215 | let url = self.base.clone();
216 | let response = self
217 | .preconfigured_privatebin_request_builder("GET", url, false)?
218 | .send()?;
219 | response.error_for_status_ref()?;
220 | let html = response.text()?;
221 | let document = Html::parse_document(&html);
222 | let expiries_selector = Selector::parse("#expiration + ul > li > a").unwrap();
223 | let mut expiries = Vec::new();
224 | for expiry_anchor in document.select(&expiries_selector) {
225 | if let Some(expiry) = expiry_anchor.attr("data-expiration") {
226 | expiries.push(expiry.to_string());
227 | }
228 | }
229 | Ok(expiries)
230 | }
231 |
232 | pub fn base(&self) -> Url {
233 | self.base.clone()
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/src/config.rs:
--------------------------------------------------------------------------------
1 | use std::env;
2 | use std::ffi::OsString;
3 | use std::io::BufRead;
4 | use std::path::{Path, PathBuf};
5 |
6 | fn is_valid_config(p: &Path) -> bool {
7 | log::debug!("looking for config at {}", p.display());
8 | p.exists() && p.is_file()
9 | }
10 |
11 | fn get_config_path(skip_default_locations: bool) -> Option {
12 | // check if config env var is set and use it
13 | if let Some(path) = env::var_os("PBCLI_CONFIG_PATH") {
14 | log::debug!("using config pointed to by PBCLI_CONFIG_PATH");
15 | return Some(path);
16 | };
17 |
18 | log::debug!("PBCLI_CONFIG_PATH not set");
19 |
20 | if skip_default_locations {
21 | log::debug!("skip_default_locations set. not checking default config locations");
22 | return None;
23 | }
24 |
25 | // check user specific config location
26 | let project_dirs = directories::ProjectDirs::from("eu", "mydayyy", env!("CARGO_PKG_NAME"))?;
27 | let user_config_dir = project_dirs.config_local_dir();
28 | let user_config_file = user_config_dir.join("config");
29 | if is_valid_config(&user_config_file) {
30 | return Some(user_config_file.into());
31 | }
32 |
33 | // linux only: check /etc/pbcli/config
34 | if cfg!(unix) {
35 | let system_config_file = PathBuf::from("/etc/pbcli/config");
36 | if is_valid_config(&system_config_file) {
37 | return Some(system_config_file.into());
38 | }
39 | }
40 |
41 | None
42 | }
43 |
44 | pub fn get_config_args(skip_default_locations: bool) -> Vec {
45 | let path = match get_config_path(skip_default_locations) {
46 | None => {
47 | log::debug!("no config found");
48 | return vec![];
49 | }
50 | Some(path) => path,
51 | };
52 |
53 | log::debug!("using config {}", path.to_string_lossy());
54 |
55 | let handle = match std::fs::File::open(path) {
56 | Ok(file) => file,
57 | Err(_) => {
58 | log::debug!("failed to open config. using cli args only");
59 | return vec![];
60 | } // TODO: Raise error
61 | };
62 |
63 | let reader = std::io::BufReader::new(handle);
64 | let mut config_args: Vec = vec![];
65 | reader.lines().for_each(|line| {
66 | let line = match line {
67 | Ok(line) => line.trim().to_owned(),
68 | Err(_) => return,
69 | };
70 |
71 | if line.starts_with('#') {
72 | return;
73 | }
74 |
75 | if line.is_empty() {
76 | return;
77 | }
78 |
79 | if line.chars().all(char::is_whitespace) {
80 | return;
81 | }
82 |
83 | config_args.push(line.into());
84 | });
85 |
86 | config_args
87 | }
88 |
89 | pub fn get_cli_args() -> Vec {
90 | std::env::args_os().collect()
91 | }
92 |
93 | fn has_flag(flag_name: &str) -> bool {
94 | get_cli_args().contains(&OsString::from(flag_name))
95 | }
96 | pub fn has_debug_flag() -> bool {
97 | has_flag("--debug")
98 | }
99 |
100 | pub fn has_skip_default_config_flag() -> bool {
101 | has_flag("--skip-default-config")
102 | }
103 |
--------------------------------------------------------------------------------
/src/crypto.rs:
--------------------------------------------------------------------------------
1 | use crate::error::{PasteError, PbResult};
2 | use crate::privatebin::{Cipher, CompressionType};
3 | use aes_gcm::aead::{Aead, NewAead};
4 | use aes_gcm::{Key, Nonce};
5 |
6 | /// Trait implemented by any decrypt-able type (paste or comment)
7 | pub trait Decryptable {
8 | /// Get ciphertext.
9 | /// We prefer to borrow this and not copy, because ct may be large.
10 | fn get_ct(&self) -> &str;
11 | /// Additional authenticated (but not encrypted) data.
12 | /// Sensitive to formatting changes.
13 | fn get_adata_str(&self) -> String;
14 | /// Cipher parameters
15 | fn get_cipher(&self) -> &Cipher;
16 | }
17 |
18 | fn derive_key(iterations: std::num::NonZeroU32, salt: &[u8], key: &[u8], out: &mut [u8]) {
19 | ring::pbkdf2::derive(ring::pbkdf2::PBKDF2_HMAC_SHA256, iterations, salt, key, out);
20 | }
21 |
22 | /// Decrypt decryptable, then attempt deserialize to requested type (DecryptedT)
23 | pub fn decrypt_with_password(
24 | decryptable: &impl Decryptable,
25 | key: &[u8],
26 | password: &str,
27 | ) -> PbResult {
28 | let cipher_algo = &decryptable.get_cipher().cipher_algo;
29 | let cipher_mode = &decryptable.get_cipher().cipher_mode;
30 | let kdf_keysize = decryptable.get_cipher().kdf_keysize;
31 | let compression_type = &decryptable.get_cipher().compression_type;
32 |
33 | let salt = &decryptable.get_cipher().vec_kdf_salt()?;
34 | let iterations = std::num::NonZeroU32::new(decryptable.get_cipher().kdf_iterations).unwrap();
35 |
36 | let key = [key, password.as_bytes()].concat();
37 |
38 | let mut derived_key = [0u8; 32];
39 | derive_key(iterations, salt, &key, &mut derived_key);
40 |
41 | match (&cipher_algo[..], &cipher_mode[..], kdf_keysize) {
42 | ("aes", "gcm", 256) => {
43 | let data = decrypt_aes_256_gcm(decryptable, &derived_key, compression_type)?;
44 | let value: serde_json::Value = serde_json::from_slice(&data)?;
45 | Ok(serde_json::from_value(value)?)
46 | }
47 | _ => Err(PasteError::CipherNotImplemented {
48 | cipher_mode: decryptable.get_cipher().cipher_mode.clone(),
49 | cipher_algo: decryptable.get_cipher().cipher_algo.clone(),
50 | keysize: decryptable.get_cipher().kdf_keysize,
51 | }),
52 | }
53 | }
54 |
55 | pub fn encrypt(
56 | content: &str,
57 | key: &[u8],
58 | password: &str,
59 | salt: &[u8],
60 | nonce: &[u8],
61 | iterations: u32,
62 | aad: &str,
63 | ) -> PbResult> {
64 | let paste_blob = miniz_oxide::deflate::compress_to_vec(content.as_bytes(), 10);
65 |
66 | let key = [key, password.as_bytes()].concat();
67 |
68 | let mut derived_key = [0u8; 32];
69 | derive_key(
70 | std::num::NonZeroU32::new(iterations).unwrap(),
71 | salt,
72 | &key,
73 | &mut derived_key,
74 | );
75 |
76 | type Cipher = aes_gcm::AesGcm;
77 | let cipher = Cipher::new(Key::from_slice(&derived_key));
78 | let payload = aes_gcm::aead::Payload {
79 | msg: &paste_blob,
80 | aad: aad.as_bytes(),
81 | };
82 | let encrypted_data = cipher.encrypt(Nonce::from_slice(nonce), payload)?;
83 |
84 | Ok(encrypted_data)
85 | }
86 |
87 | fn decrypt_aes_256_gcm(
88 | decryptable: &impl Decryptable,
89 | derived_key: &[u8],
90 | compression_type: &CompressionType,
91 | ) -> PbResult> {
92 | type Cipher = aes_gcm::AesGcm;
93 | let ciphertext = base64::decode(decryptable.get_ct())?;
94 | let nonce = decryptable.get_cipher().vec_cipher_iv()?;
95 |
96 | let cipher = Cipher::new(Key::from_slice(derived_key));
97 | let adata_str = decryptable.get_adata_str();
98 | let payload = aes_gcm::aead::Payload {
99 | msg: &ciphertext,
100 | aad: adata_str.as_bytes(),
101 | };
102 | let data = cipher.decrypt(Nonce::from_slice(&nonce), payload)?;
103 | let decompressed = match compression_type {
104 | CompressionType::None => data,
105 | CompressionType::Zlib => miniz_oxide::inflate::decompress_to_vec(&data)?,
106 | };
107 | Ok(decompressed)
108 | }
109 |
--------------------------------------------------------------------------------
/src/error.rs:
--------------------------------------------------------------------------------
1 | use base64::DecodeError;
2 | use data_url::DataUrlError;
3 | use log::SetLoggerError;
4 | use miniz_oxide::inflate::TINFLStatus;
5 | use serde_json::Error;
6 | use std::fmt;
7 | use std::fmt::Formatter;
8 |
9 | pub type PbError = PasteError;
10 | pub type PbResult = std::result::Result;
11 |
12 | #[derive(Debug)]
13 | #[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
14 | #[cfg_attr(feature = "uniffi", uniffi(flat_error))]
15 | pub enum PasteError {
16 | CipherNotImplemented {
17 | cipher_algo: String,
18 | cipher_mode: String,
19 | keysize: u32,
20 | },
21 | MissingDecryptionKey,
22 | // BadUrl,
23 | PasteNotFound,
24 | InvalidData,
25 | UnknownPasteStatus(u32),
26 | Json(serde_json::error::Error),
27 | Request(reqwest::Error),
28 | Io(std::io::Error),
29 | ParseError(url::ParseError),
30 | Base64Error(DecodeError),
31 | Base58Error(bs58::decode::Error),
32 | Aes(aes_gcm::Error),
33 | Zlib(miniz_oxide::inflate::TINFLStatus),
34 | InvalidAttachment(data_url::DataUrlError),
35 | FileExists,
36 | NotAFile,
37 | InvalidTokenType(String),
38 | OidcBadRequest(serde_json::Value),
39 | LoggerInit(log::SetLoggerError),
40 | }
41 |
42 | impl std::error::Error for PasteError {}
43 |
44 | impl fmt::Display for PasteError {
45 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46 | match self {
47 | PasteError::CipherNotImplemented {
48 | cipher_algo,
49 | cipher_mode,
50 | keysize,
51 | } => write!(
52 | f,
53 | "Cipher not implemented algo: {} mode: {} keysize: {}",
54 | cipher_algo, cipher_mode, keysize
55 | ),
56 | PasteError::Json(r) => r.fmt(f),
57 | PasteError::Request(r) => r.fmt(f),
58 | PasteError::Io(r) => r.fmt(f),
59 | PasteError::ParseError(r) => r.fmt(f),
60 | PasteError::Base64Error(r) => r.fmt(f),
61 | PasteError::Aes(err) => err.fmt(f),
62 | PasteError::Zlib(err) => write!(f, "Zlib error: {:?}", err),
63 | PasteError::Base58Error(err) => err.fmt(f),
64 | PasteError::UnknownPasteStatus(err) => write!(f, "Unknown paste status: {}", err),
65 | PasteError::PasteNotFound => write!(f, "Invalid paste ID"),
66 | PasteError::MissingDecryptionKey => write!(f, "Missing decryption key"),
67 | // PasteError::BadUrl => write!(f, "Badly formatted url"),
68 | PasteError::InvalidData => write!(f, "Invalid Data"),
69 | PasteError::InvalidAttachment(err) => write!(f, "Invalid attachment: {:?}", err),
70 | PasteError::FileExists => write!(f, "File already exists. Use --overwrite to force"),
71 | PasteError::NotAFile => write!(f, "Given path is not a file"),
72 | PasteError::InvalidTokenType(token_type) => {
73 | write!(f, "Invalid token type: {}", token_type)
74 | }
75 | PasteError::OidcBadRequest(json) => write!(f, "{}", json),
76 | PasteError::LoggerInit(err) => {
77 | write!(f, "Failed to init logger: {}", err)
78 | }
79 | }
80 | }
81 | }
82 |
83 | impl From for PasteError {
84 | fn from(err: std::io::Error) -> Self {
85 | PasteError::Io(err)
86 | }
87 | }
88 |
89 | impl From for PasteError {
90 | fn from(err: Error) -> Self {
91 | PasteError::Json(err)
92 | }
93 | }
94 |
95 | impl From for PasteError {
96 | fn from(err: url::ParseError) -> Self {
97 | PasteError::ParseError(err)
98 | }
99 | }
100 |
101 | impl From for PasteError {
102 | fn from(err: reqwest::Error) -> Self {
103 | PasteError::Request(err)
104 | }
105 | }
106 |
107 | impl From for PasteError {
108 | fn from(err: DecodeError) -> Self {
109 | PasteError::Base64Error(err)
110 | }
111 | }
112 |
113 | impl From for PasteError {
114 | fn from(err: aes_gcm::Error) -> Self {
115 | PasteError::Aes(err)
116 | }
117 | }
118 |
119 | impl From for PasteError {
120 | fn from(err: TINFLStatus) -> Self {
121 | PasteError::Zlib(err)
122 | }
123 | }
124 |
125 | impl From for PasteError {
126 | fn from(err: bs58::decode::Error) -> Self {
127 | PasteError::Base58Error(err)
128 | }
129 | }
130 |
131 | impl From for PasteError {
132 | fn from(err: DataUrlError) -> Self {
133 | PasteError::InvalidAttachment(err)
134 | }
135 | }
136 |
137 | impl From for PasteError {
138 | fn from(err: SetLoggerError) -> Self {
139 | PasteError::LoggerInit(err)
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod api;
2 | pub mod config;
3 | pub mod crypto;
4 | pub mod error;
5 | pub mod opts;
6 | pub mod privatebin;
7 | pub mod util;
8 |
9 | #[cfg(feature = "uniffi")]
10 | mod uniffi_custom_types;
11 |
12 | pub use api::API;
13 | pub use error::{PasteError, PbResult};
14 | pub use opts::Opts;
15 | pub use privatebin::{DecryptedPaste, PasteFormat};
16 | pub use util::check_filesize;
17 |
18 | #[cfg(feature = "uniffi")]
19 | uniffi::setup_scaffolding!();
20 |
--------------------------------------------------------------------------------
/src/logger.rs:
--------------------------------------------------------------------------------
1 | use log::{Metadata, Record};
2 |
3 | pub(crate) struct SimpleLogger(());
4 | const LOGGER: &SimpleLogger = &SimpleLogger(());
5 |
6 | impl SimpleLogger {
7 | pub(crate) fn init() -> Result<(), log::SetLoggerError> {
8 | log::set_logger(LOGGER)
9 | }
10 | }
11 |
12 | impl log::Log for SimpleLogger {
13 | fn enabled(&self, _metadata: &Metadata) -> bool {
14 | true
15 | }
16 |
17 | fn log(&self, record: &Record) {
18 | if self.enabled(record.metadata()) {
19 | eprintln!("{} {}: {}", record.level(), record.target(), record.args());
20 | }
21 | }
22 |
23 | fn flush(&self) {}
24 | }
25 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | use clap::Parser;
2 | use data_url::DataUrl;
3 | use pbcli::api::API;
4 | use pbcli::error::{PasteError, PbResult};
5 | use pbcli::opts::Opts;
6 | use pbcli::privatebin::{DecryptedComment, DecryptedCommentsMap, DecryptedPaste};
7 | use pbcli::util::check_filesize;
8 | use serde_json::Value;
9 | use std::ffi::OsString;
10 | use std::io::IsTerminal;
11 | use std::io::{Read, Write};
12 |
13 | mod logger;
14 |
15 | fn get_stdin() -> std::io::Result {
16 | if std::io::stdin().is_terminal() {
17 | return Ok("".into());
18 | }
19 | let mut buffer = String::new();
20 | std::io::stdin().read_to_string(&mut buffer)?;
21 | Ok(buffer)
22 | }
23 |
24 | fn create_dataurl(path: &std::ffi::OsStr, data: String) -> String {
25 | let mime = mime_guess::from_path(path)
26 | .first()
27 | .unwrap_or(mime_guess::mime::APPLICATION_OCTET_STREAM);
28 | format!("data:{};base64,{}", mime.essence_str(), data)
29 | }
30 |
31 | fn handle_get(opts: &Opts) -> PbResult<()> {
32 | let url = opts.get_url();
33 | let paste_id = opts.get_url().query().unwrap();
34 | let fragment = opts
35 | .get_url()
36 | .fragment()
37 | .ok_or(PasteError::MissingDecryptionKey)?;
38 | // '-' character may be found at start of fragment. This should be stripped.
39 | // It is used to activate "warn before read" feature for burn on read pastes.
40 | let key = fragment.strip_prefix('-').unwrap_or(fragment);
41 |
42 | let api = API::new(url.clone(), opts.clone());
43 | let paste = api.get_paste(paste_id)?;
44 |
45 | let content: DecryptedPaste;
46 | let comments: DecryptedCommentsMap;
47 |
48 | if let Some(pass) = &opts.password {
49 | content = paste.decrypt_with_password(key, pass)?;
50 | comments = paste.decrypt_comments_with_password(key, pass)?;
51 | } else {
52 | match paste.decrypt(key) {
53 | Ok(c) => {
54 | content = c;
55 | comments = paste.decrypt_comments(key)?;
56 | }
57 | Err(err) => {
58 | if !std::io::stdin().is_terminal() {
59 | return Err(err);
60 | }
61 |
62 | let password = dialoguer::Password::new()
63 | .with_prompt("Enter password")
64 | .interact()?;
65 | content = paste.decrypt_with_password(key, &password)?;
66 | comments = paste.decrypt_comments_with_password(key, &password)?;
67 | }
68 | }
69 | }
70 |
71 | if content.attachment.is_some() && opts.download.is_some() {
72 | let attachment = content.attachment.as_ref().unwrap();
73 | let outfile = opts.download.as_ref().unwrap();
74 |
75 | let url = DataUrl::process(attachment)?;
76 | let (body, _) = url.decode_to_vec().unwrap();
77 |
78 | if outfile.exists() && !opts.overwrite {
79 | return Err(PasteError::FileExists);
80 | }
81 |
82 | let mut handle = std::fs::File::create(outfile)?;
83 |
84 | handle.write_all(&body)?;
85 | }
86 |
87 | if !opts.json {
88 | std::io::stdout().write_all(content.paste.as_bytes())?;
89 | } else {
90 | let mut output: Value = serde_json::to_value(content)?;
91 | if !comments.is_empty() {
92 | let comments_trees =
93 | paste.comments_formatted_json_trees(&comments, &paste.comments_adjacency_map()?)?;
94 | output["comments"] = serde_json::from_str(&comments_trees)?;
95 | }
96 | std::io::stdout().write_all(serde_json::to_string_pretty(&output)?.as_bytes())?;
97 | }
98 |
99 | Ok(())
100 | }
101 |
102 | fn handle_post(opts: &Opts) -> PbResult<()> {
103 | let url = opts.get_url();
104 | let stdin = get_stdin()?;
105 | let api = API::new(url.clone(), opts.clone());
106 |
107 | let password = &opts.password.clone().unwrap_or_default();
108 |
109 | let mut paste = DecryptedPaste {
110 | paste: stdin,
111 | attachment: None,
112 | attachment_name: None,
113 | };
114 |
115 | if let Some(path) = &opts.upload {
116 | if !path.is_file() {
117 | return Err(PasteError::NotAFile);
118 | }
119 |
120 | let mut handle = std::fs::File::open(path)?;
121 | let metadata = handle.metadata()?;
122 | check_filesize(metadata.len(), opts.size_limit);
123 |
124 | let mut data = Vec::new();
125 | handle.read_to_end(&mut data)?;
126 | let b64_data = base64::encode(data);
127 |
128 | paste.attachment = Some(create_dataurl(path.as_os_str(), b64_data));
129 | paste.attachment_name = Some(
130 | path.file_name()
131 | .ok_or(PasteError::NotAFile)?
132 | .to_string_lossy()
133 | .to_string(),
134 | );
135 | }
136 |
137 | let res = api.post_paste(&paste, password, opts)?;
138 |
139 | if opts.json {
140 | let mut output: Value = serde_json::to_value(res.clone())?;
141 | output["pasteurl"] = Value::String(res.to_paste_url().to_string());
142 | output["deleteurl"] = Value::String(res.to_delete_url().to_string());
143 | std::io::stdout().write_all(serde_json::to_string_pretty(&output)?.as_bytes())?;
144 | } else {
145 | std::io::stdout().write_all(res.to_paste_url().as_str().as_bytes())?;
146 | writeln!(std::io::stdout())?;
147 | }
148 |
149 | Ok(())
150 | }
151 |
152 | fn handle_comment(opts: &Opts) -> PbResult<()> {
153 | let url = opts.get_url();
154 | let paste_id = url.query().unwrap();
155 | let fragment = url.fragment().ok_or(PasteError::MissingDecryptionKey)?;
156 | // '-' character may be found at start of fragment. This should be stripped.
157 | // It is used to activate "warn before read" feature for burn on read pastes.
158 | let key = fragment.strip_prefix('-').unwrap_or(fragment);
159 |
160 | let stdin = get_stdin()?;
161 | let api = API::new(url.clone(), opts.clone());
162 | let content = DecryptedComment {
163 | comment: stdin,
164 | nickname: opts.comment_as.clone(),
165 | };
166 | let parent_id = &opts.comment_to.clone().unwrap_or(paste_id.into());
167 | let password = &opts.password.clone().unwrap_or_default();
168 |
169 | api.post_comment(&content, paste_id, parent_id, key, password, opts)?;
170 |
171 | Ok(())
172 | }
173 |
174 | fn handle_scrape(opts: &Opts) -> PbResult<()> {
175 | let url = opts.get_url();
176 | let api = API::new(url.clone(), opts.clone());
177 | let expiries = api.scrape_expiries()?;
178 | std::io::stdout().write_all(format!("{:?}", expiries).as_bytes())?;
179 | writeln!(std::io::stdout())?;
180 | Ok(())
181 | }
182 |
183 | fn main() -> PbResult<()> {
184 | crate::logger::SimpleLogger::init()?;
185 |
186 | if pbcli::config::has_debug_flag() {
187 | log::set_max_level(log::LevelFilter::Debug);
188 | }
189 |
190 | let config_args = pbcli::config::get_config_args(pbcli::config::has_skip_default_config_flag());
191 | let mut env_args = pbcli::config::get_cli_args();
192 | let mut merged_args: Vec = vec![];
193 | merged_args.extend(env_args.drain(0..1));
194 | merged_args.extend(config_args);
195 | merged_args.extend(env_args);
196 |
197 | let opts: Opts = Opts::parse_from(&merged_args);
198 |
199 | if opts.scrape_expiries {
200 | return handle_scrape(&opts);
201 | }
202 |
203 | let url_has_query = opts.get_url().query().is_some();
204 | if url_has_query {
205 | if opts.comment {
206 | handle_comment(&opts)?;
207 | // show paste with comments after commenting
208 | if opts.json {
209 | handle_get(&opts)?;
210 | }
211 | return Ok(());
212 | }
213 | handle_get(&opts)?;
214 | } else {
215 | handle_post(&opts)?;
216 | }
217 |
218 | Ok(())
219 | }
220 |
--------------------------------------------------------------------------------
/src/opts.rs:
--------------------------------------------------------------------------------
1 | use crate::PasteFormat;
2 | use clap::Parser;
3 | use parse_size::parse_size;
4 | use url::Url;
5 |
6 | const ABOUT: &str = "pbcli is a command line client which allows to upload and download
7 | pastes from privatebin directly from the command line.
8 |
9 | Project home page: https://github.com/Mydayyy/pbcli";
10 |
11 | #[derive(Debug, Parser, Clone)]
12 | #[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
13 | #[clap( version = env ! ("CARGO_PKG_VERSION"), author = "Mydayyy ", about = ABOUT)]
14 | #[clap(term_width(if let Some((terminal_size::Width(w), _)) = terminal_size::terminal_size() { w as usize } else { 120 }))]
15 | #[clap(rename_all = "kebab-case")]
16 | #[command(args_override_self = true)]
17 | pub struct Opts {
18 | #[clap(required_unless_present("host"))]
19 | pub url: Option,
20 |
21 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
22 | #[clap(long)]
23 | pub host: Option,
24 |
25 | #[clap(long, short = 'f', value_enum, default_value = "plaintext")]
26 | pub format: PasteFormat,
27 |
28 | #[cfg_attr(feature = "uniffi", uniffi(default = "1week"))]
29 | #[clap(long, short = 'e', default_value = "1week")]
30 | pub expire: String,
31 |
32 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
33 | #[clap(long)]
34 | #[arg(value_parser = |x: &str| parse_size(x))] // closure: https://github.com/clap-rs/clap/issues/4939
35 | #[clap(help(
36 | "Prompt if the paste exceeds the given size. Fail in non-interactive environments."
37 | ))]
38 | pub size_limit: Option,
39 |
40 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
41 | #[clap(long, help("richer output: for delete_url, comments, etc"))]
42 | pub json: bool,
43 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
44 | #[clap(long, short = 'b', conflicts_with = "discussion")]
45 | #[clap(overrides_with = "no_burn")]
46 | #[clap(help("enable burn on read for new paste"))]
47 | pub burn: bool,
48 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
49 | #[clap(long, short = 'B')]
50 | #[clap(help("disable burn if set"))]
51 | pub no_burn: bool,
52 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
53 | #[clap(long, short = 'd')]
54 | #[clap(overrides_with = "no_discussion")]
55 | #[clap(help("enable discussion for new paste"))]
56 | pub discussion: bool,
57 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
58 | #[clap(long, short = 'D')]
59 | #[clap(help("disable burn if set"))]
60 | pub no_discussion: bool,
61 |
62 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
63 | #[clap(long, requires("url"))]
64 | #[clap(help("make new comment on existing paste"))]
65 | pub comment: bool,
66 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
67 | #[clap(long, requires("comment"), value_name = "nickname")]
68 | #[clap(help("use this nick for comment"))]
69 | pub comment_as: Option,
70 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
71 | #[clap(long, requires("comment"), value_name = "parentid")]
72 | #[clap(help("reply to this parent comment"))]
73 | pub comment_to: Option,
74 |
75 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
76 | #[clap(long, short = 'o', value_name = "FILE")]
77 | pub download: Option,
78 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
79 | #[clap(long, short = 'w')]
80 | #[clap(help("overwrite the file given with --download if it already exists"))]
81 | pub overwrite: bool,
82 |
83 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
84 | #[clap(long, short = 'u', value_name = "FILE")]
85 | pub upload: Option,
86 |
87 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
88 | #[clap(long, short = 'p')]
89 | pub password: Option,
90 |
91 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
92 | #[clap(long, requires_all(& ["oidc_client_id", "oidc_username", "oidc_password"]))]
93 | #[clap(help("oidc token endpoint from which to obtain an access token"))]
94 | pub oidc_token_url: Option,
95 |
96 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
97 | #[clap(long)]
98 | #[clap(help("client id to send to the token endpoint"))]
99 | pub oidc_client_id: Option,
100 |
101 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
102 | #[clap(long)]
103 | #[clap(help("username to send to the token endpoint"))]
104 | pub oidc_username: Option,
105 |
106 | #[cfg_attr(feature = "uniffi", uniffi(default = None))]
107 | #[clap(long)]
108 | #[clap(help("password to send to the token endpoint"))]
109 | pub oidc_password: Option,
110 |
111 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
112 | #[clap(long)]
113 | #[clap(help("print debug output to stderr"))]
114 | pub debug: bool,
115 |
116 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
117 | #[clap(long)]
118 | #[clap(help("do not look for config in default locations"))]
119 | pub no_default_config: bool,
120 |
121 | #[cfg_attr(feature = "uniffi", uniffi(default = false))]
122 | #[clap(long)]
123 | #[clap(help("attempt scraping supported expiries of given host and exit"))]
124 | pub scrape_expiries: bool,
125 | }
126 |
127 | impl Opts {
128 | pub fn get_url(&self) -> &Url {
129 | self.url
130 | .as_ref()
131 | .unwrap_or_else(|| self.host.as_ref().unwrap())
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/privatebin.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use crate::crypto::Decryptable;
4 | use crate::error::PbResult;
5 | use rand_core::{RngCore, SeedableRng};
6 | use serde::ser::{SerializeTuple, Serializer};
7 | use serde::Deserialize;
8 | use serde::Serialize;
9 | use serde_json::json;
10 | use serde_with::skip_serializing_none;
11 | use url::Url;
12 |
13 | #[derive(Default, Deserialize, Debug, Serialize)]
14 | pub enum CompressionType {
15 | #[serde(rename = "none")]
16 | None,
17 |
18 | #[default]
19 | #[serde(rename = "zlib")]
20 | Zlib,
21 | }
22 |
23 | #[derive(Default, clap::ValueEnum, Deserialize, Debug, Serialize, Clone, Copy)]
24 | #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
25 | pub enum PasteFormat {
26 | #[default]
27 | #[serde(rename = "plaintext")]
28 | Plaintext,
29 |
30 | #[serde(rename = "syntaxhighlighting")]
31 | Syntax,
32 |
33 | #[serde(rename = "markdown")]
34 | Markdown,
35 | }
36 |
37 | #[skip_serializing_none]
38 | #[derive(Default, Deserialize, Debug, Serialize)]
39 | #[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
40 | pub struct Paste {
41 | pub status: Option,
42 | pub id: String,
43 | pub url: Option,
44 | pub v: i32,
45 | pub ct: String,
46 | pub meta: Meta,
47 | pub adata: Data,
48 | pub comments: Option>,
49 | }
50 |
51 | impl Decryptable for Paste {
52 | fn get_ct(&self) -> &str {
53 | &self.ct
54 | }
55 | fn get_cipher(&self) -> &Cipher {
56 | &self.adata.cipher
57 | }
58 | fn get_adata_str(&self) -> String {
59 | serde_json::to_string(&self.adata).unwrap()
60 | }
61 | }
62 |
63 | #[derive(Default, Deserialize, Debug, Serialize)]
64 | pub struct Comment {
65 | pub id: String,
66 | pub pasteid: String,
67 | pub parentid: String,
68 | pub v: i32,
69 | pub ct: String,
70 | pub meta: Meta,
71 | pub adata: Cipher,
72 | }
73 |
74 | impl Decryptable for Comment {
75 | fn get_ct(&self) -> &str {
76 | &self.ct
77 | }
78 | fn get_cipher(&self) -> &Cipher {
79 | &self.adata
80 | }
81 | fn get_adata_str(&self) -> String {
82 | serde_json::to_string(&self.adata).unwrap()
83 | }
84 | }
85 |
86 | #[skip_serializing_none]
87 | #[derive(Default, Deserialize, Debug, Serialize)]
88 | pub struct Meta {
89 | pub created: Option,
90 | pub expire: Option,
91 | pub time_to_live: Option,
92 | pub icon: Option,
93 | }
94 |
95 | #[derive(Default, Deserialize, Debug)]
96 | pub struct Data {
97 | pub cipher: Cipher,
98 | pub format: PasteFormat,
99 | pub discuss: u8,
100 | pub burn: u8,
101 | }
102 |
103 | #[derive(Deserialize, Debug)]
104 | pub struct Cipher {
105 | pub cipher_iv: String,
106 | pub kdf_salt: String,
107 | pub kdf_iterations: u32,
108 | pub kdf_keysize: u32,
109 | pub cipher_tag_size: u32,
110 | pub cipher_algo: String,
111 | pub cipher_mode: String,
112 | pub compression_type: CompressionType,
113 | // test: String,
114 | }
115 |
116 | impl Default for Cipher {
117 | fn default() -> Self {
118 | let mut rng = rand_chacha::ChaCha20Rng::from_entropy();
119 | let mut kdf_salt = [0u8; 8];
120 | let mut nonce = [0u8; 16];
121 | rng.fill_bytes(&mut kdf_salt);
122 | rng.fill_bytes(&mut nonce);
123 |
124 | Cipher {
125 | cipher_iv: base64::encode(nonce),
126 | kdf_salt: base64::encode(kdf_salt),
127 | kdf_iterations: 100000,
128 | kdf_keysize: 256,
129 | cipher_tag_size: 128,
130 | cipher_algo: "aes".to_string(),
131 | cipher_mode: "gcm".to_string(),
132 | compression_type: CompressionType::Zlib,
133 | }
134 | }
135 | }
136 |
137 | impl Cipher {
138 | /// get vector of bytes representation
139 | pub fn vec_cipher_iv(&self) -> PbResult> {
140 | base64::decode(&self.cipher_iv).map_err(|e| e.into())
141 | }
142 | /// get vector of bytes representation
143 | pub fn vec_kdf_salt(&self) -> PbResult> {
144 | base64::decode(&self.kdf_salt).map_err(|e| e.into())
145 | }
146 | }
147 |
148 | #[skip_serializing_none]
149 | #[derive(Deserialize, Debug, Serialize)]
150 | #[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
151 | pub struct DecryptedPaste {
152 | pub paste: String,
153 | pub attachment: Option,
154 | pub attachment_name: Option,
155 | }
156 |
157 | #[skip_serializing_none]
158 | #[derive(Default, Deserialize, Debug, Serialize)]
159 | #[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
160 | pub struct DecryptedComment {
161 | pub comment: String,
162 | pub nickname: Option,
163 | }
164 |
165 | /// comment.id -> decrypted_comment
166 | pub type DecryptedCommentsMap = HashMap;
167 |
168 | /// comment.id -> [children comment.id]
169 | pub type CommentsAdjacencyMap = HashMap>;
170 |
171 | #[derive(Deserialize, Debug, Serialize, Clone)]
172 | #[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
173 | pub struct PostCommentResponse {
174 | pub id: String,
175 | pub status: u32,
176 | pub url: String,
177 | }
178 |
179 | #[derive(Deserialize, Debug, Serialize, Clone)]
180 | #[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
181 | pub struct PostPasteResponse {
182 | pub deletetoken: String,
183 | pub id: String,
184 | pub status: u32,
185 | pub url: String,
186 | pub baseurl: Url,
187 | pub bs58key: String,
188 | }
189 |
190 | #[cfg_attr(feature = "uniffi", uniffi::export)]
191 | impl PostPasteResponse {
192 | /// Return full paste url, i.e (base + ?id + #bs58key)
193 | pub fn to_paste_url(&self) -> url::Url {
194 | let mut paste_url: url::Url = self.baseurl.clone();
195 | paste_url.set_query(Some(&self.id));
196 | paste_url.set_fragment(Some(&self.bs58key));
197 | paste_url
198 | }
199 | /// Return url that can be used to delete paste
200 | pub fn to_delete_url(&self) -> url::Url {
201 | let mut delete_url: url::Url = self.baseurl.clone();
202 | delete_url
203 | .query_pairs_mut()
204 | .append_pair("pasteid", &self.id)
205 | .append_pair("deletetoken", &self.deletetoken);
206 | delete_url
207 | }
208 | pub fn to_json_string(&self) -> String {
209 | serde_json::to_string(&self).unwrap()
210 | }
211 | pub fn is_success(&self) -> bool {
212 | self.status == 0
213 | }
214 | }
215 |
216 | #[cfg_attr(feature = "uniffi", uniffi::export)]
217 | impl Paste {
218 | pub fn decrypt(&self, bs58_key: &str) -> PbResult {
219 | self.decrypt_with_password(bs58_key, "")
220 | }
221 |
222 | pub fn decrypt_with_password(
223 | &self,
224 | bs58_key: &str,
225 | password: &str,
226 | ) -> PbResult {
227 | let key = bs58::decode(bs58_key).into_vec()?;
228 | crate::crypto::decrypt_with_password(self, &key, password)
229 | }
230 |
231 | /// Returns a mapping: comment.id -> decrypted_comment
232 | pub fn decrypt_comments(&self, bs58_key: &str) -> PbResult {
233 | self.decrypt_comments_with_password(bs58_key, "")
234 | }
235 |
236 | /// Returns a mapping: comment.id -> decrypted_comment
237 | pub fn decrypt_comments_with_password(
238 | &self,
239 | bs58_key: &str,
240 | password: &str,
241 | ) -> PbResult {
242 | let mut decrypted_comments = HashMap::new();
243 | if let Some(comments) = &self.comments {
244 | for comment in comments {
245 | let id = comment.id.clone();
246 | decrypted_comments.insert(id, comment.decrypt_with_password(bs58_key, password)?);
247 | }
248 | };
249 | Ok(decrypted_comments)
250 | }
251 |
252 | /// Returns a mapping: comment.id -> [children comment.id]
253 | pub fn comments_adjacency_map(&self) -> PbResult {
254 | let mut comment_adjacency: CommentsAdjacencyMap = HashMap::new();
255 | if let Some(comments) = &self.comments {
256 | for c in comments {
257 | let id = c.id.clone();
258 | let parentid = c.parentid.clone();
259 | comment_adjacency.entry(parentid).or_default().push(id);
260 | }
261 | }
262 | Ok(comment_adjacency)
263 | }
264 |
265 | /// Returns formatted json trees (forest) of decrypted comments
266 | pub fn comments_formatted_json_trees(
267 | &self,
268 | decrypted_comments: &DecryptedCommentsMap,
269 | comment_adjacency: &CommentsAdjacencyMap,
270 | ) -> PbResult {
271 | fn format_comments_below_id(
272 | id: &str,
273 | decrypted_comments: &DecryptedCommentsMap,
274 | comment_adjacency: &CommentsAdjacencyMap,
275 | ) -> serde_json::Value {
276 | let formatted_children: Vec = comment_adjacency
277 | .get(id)
278 | .unwrap_or(&Vec::new())
279 | .iter()
280 | .map(|child_id| {
281 | format_comments_below_id(child_id, decrypted_comments, comment_adjacency)
282 | })
283 | .collect();
284 | json!({
285 | "id": id,
286 | "comment": decrypted_comments.get(id).unwrap_or(&DecryptedComment::default()).comment,
287 | "nickname": decrypted_comments.get(id).unwrap_or(&DecryptedComment::default()).nickname,
288 | "replies": formatted_children
289 | })
290 | }
291 | let top_level = format_comments_below_id(&self.id, decrypted_comments, comment_adjacency);
292 | serde_json::to_string_pretty(&top_level["replies"]).map_err(|e| e.into())
293 | }
294 | }
295 |
296 | impl Comment {
297 | pub fn decrypt(&self, bs58_key: &str) -> PbResult {
298 | self.decrypt_with_password(bs58_key, "")
299 | }
300 |
301 | pub fn decrypt_with_password(
302 | &self,
303 | bs58_key: &str,
304 | password: &str,
305 | ) -> PbResult {
306 | let key = bs58::decode(bs58_key).into_vec()?;
307 | crate::crypto::decrypt_with_password(self, &key, password)
308 | }
309 | }
310 |
311 | /// Data struct needs to be serialized as an ordered array (not object),
312 | /// so we implement custom serialization.
313 | impl Serialize for Data {
314 | fn serialize(&self, serializer: S) -> Result
315 | where
316 | S: Serializer,
317 | {
318 | let mut s = serializer.serialize_tuple(4)?;
319 | s.serialize_element(&self.cipher)?;
320 | s.serialize_element(&self.format)?;
321 | s.serialize_element(&self.discuss)?;
322 | s.serialize_element(&self.burn)?;
323 | s.end()
324 | }
325 | }
326 |
327 | /// Cipher struct needs to be serialized as an ordered array (not object),
328 | /// so we implement custom serialization.
329 | impl Serialize for Cipher {
330 | fn serialize(&self, serializer: S) -> Result
331 | where
332 | S: Serializer,
333 | {
334 | let mut s = serializer.serialize_tuple(8)?;
335 | s.serialize_element(&self.cipher_iv)?;
336 | s.serialize_element(&self.kdf_salt)?;
337 | s.serialize_element(&self.kdf_iterations)?;
338 | s.serialize_element(&self.kdf_keysize)?;
339 | s.serialize_element(&self.cipher_tag_size)?;
340 | s.serialize_element(&self.cipher_algo)?;
341 | s.serialize_element(&self.cipher_mode)?;
342 | s.serialize_element(&self.compression_type)?;
343 | s.end()
344 | }
345 | }
346 |
--------------------------------------------------------------------------------
/src/uniffi_custom_types.rs:
--------------------------------------------------------------------------------
1 | use reqwest::Url;
2 | use std::path::PathBuf;
3 |
4 | use crate::UniffiCustomTypeConverter;
5 | // Custom UniFFI types
6 |
7 | // `Url` as a custom type, with `String` as the Builtin
8 | uniffi::custom_type!(Url, String);
9 |
10 | impl UniffiCustomTypeConverter for Url {
11 | type Builtin = String;
12 |
13 | fn into_custom(val: Self::Builtin) -> uniffi::Result {
14 | val.parse::().map_err(|e| e.into())
15 | }
16 |
17 | fn from_custom(obj: Self) -> Self::Builtin {
18 | obj.as_str().to_owned()
19 | }
20 | }
21 |
22 | // `PathBuf` as a custom type, with `String` as the Builtin
23 | uniffi::custom_type!(PathBuf, String);
24 |
25 | impl UniffiCustomTypeConverter for PathBuf {
26 | type Builtin = String;
27 |
28 | fn into_custom(val: Self::Builtin) -> uniffi::Result {
29 | Ok(PathBuf::from(val))
30 | }
31 |
32 | fn from_custom(obj: Self) -> Self::Builtin {
33 | format!("{:?}", obj.display())
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/util.rs:
--------------------------------------------------------------------------------
1 | use std::io::IsTerminal;
2 | use std::process::exit;
3 | use std::sync::Mutex;
4 |
5 | pub fn check_filesize(len: u64, opts_size_limt: Option) {
6 | static MUTEX_IS_CONFIRMED: Mutex = Mutex::new(false);
7 | let mut user_confirmed_size = MUTEX_IS_CONFIRMED.lock().unwrap();
8 |
9 | if *user_confirmed_size {
10 | return;
11 | }
12 |
13 | if let Some(size_limit) = opts_size_limt {
14 | if len > size_limit {
15 | if !std::io::stdin().is_terminal() {
16 | exit(1)
17 | }
18 |
19 | let confirmation = dialoguer::Confirm::new()
20 | .with_prompt("This paste exceeds your defined size limit. Continue?")
21 | .interact()
22 | .unwrap();
23 |
24 | if !confirmation {
25 | exit(1)
26 | }
27 | *user_confirmed_size = true;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------