diff --git a/.github/workflows/docker-arm.yml b/.github/workflows/docker-arm.yml index 941dce2..6e34e79 100644 --- a/.github/workflows/docker-arm.yml +++ b/.github/workflows/docker-arm.yml @@ -34,3 +34,5 @@ jobs: platforms: linux/arm64 push: true tags: spikecodes/libreddit:arm + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker-armv7.yml b/.github/workflows/docker-armv7.yml index 3229418..7c51db2 100644 --- a/.github/workflows/docker-armv7.yml +++ b/.github/workflows/docker-armv7.yml @@ -37,3 +37,5 @@ jobs: platforms: linux/arm/v7 push: true tags: spikecodes/libreddit:armv7 + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7fe2374..ed1bf73 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -34,4 +34,5 @@ jobs: platforms: linux/amd64 push: true tags: spikecodes/libreddit:latest - + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Cargo.lock b/Cargo.lock index c6fb582..f138b37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.9.1" @@ -123,7 +132,7 @@ dependencies = [ "cached_proc_macro", "cached_proc_macro_types", "futures", - "hashbrown 0.12.0", + "hashbrown 0.12.1", "lazy_static", "once_cell", "thiserror", @@ -162,16 +171,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.1.8" +version = "3.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" dependencies = [ "bitflags", + "clap_lex", "indexmap", - "os_str_bytes", "textwrap", ] +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cookie" version = "0.16.0" @@ -199,10 +217,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] -name = "darling" -version = "0.13.2" +name = "cpufeatures" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e92cb285610dd935f60ee8b4d62dd1988bd12b7ea50579bd6a138201525318e" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ "darling_core", "darling_macro", @@ -210,9 +237,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c29e95ab498b18131ea460b2c0baa18cbf041231d122b0b7bfebef8c8e88989" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", @@ -224,15 +251,24 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b21dd6b221dd547528bd6fb15f1a3b7ab03b9a06f76bff288a8c629bcfbe7f0e" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", "syn", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "fastrand" version = "1.7.0" @@ -362,6 +398,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "h2" version = "0.3.13" @@ -389,9 +435,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "hashbrown" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" [[package]] name = "hermit-abi" @@ -404,9 +450,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ "bytes", "fnv", @@ -415,9 +461,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -426,9 +472,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -513,15 +559,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "js-sys" -version = "0.3.56" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ "wasm-bindgen", ] @@ -534,13 +580,13 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "libreddit" -version = "0.22.6" +version = "0.22.8" dependencies = [ "askama", "async-recursion", @@ -550,8 +596,10 @@ dependencies = [ "futures-lite", "hyper", "hyper-rustls", + "percent-encoding", "regex", "route-recognizer", + "rust-embed", "serde", "serde_json", "time", @@ -571,9 +619,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -586,9 +634,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mime" @@ -614,25 +662,14 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", - "miow", - "ntapi", "wasi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -645,15 +682,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - [[package]] name = "num_cpus" version = "1.13.1" @@ -666,18 +694,24 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" dependencies = [ "libc", ] [[package]] name = "once_cell" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl-probe" @@ -687,12 +721,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] +checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435" [[package]] name = "parking" @@ -712,9 +743,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ "cfg-if", "libc", @@ -731,9 +762,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -743,18 +774,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] @@ -770,9 +801,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" dependencies = [ "aho-corasick", "memchr", @@ -781,9 +812,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] name = "ring" @@ -807,10 +838,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] -name = "rustls" -version = "0.20.4" +name = "rust-embed" +version = "6.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +checksum = "9a17e5ac65b318f397182ae94e532da0ba56b88dd1200b774715d36c4943b1c3" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94e763e24ba2bf0c72bc6be883f967f794a019fafd1b86ba1daff9c91a7edd30" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756feca3afcbb1487a1d01f4ecd94cf8ec98ea074c55a69e7136d29fb6166029" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" dependencies = [ "log", "ring", @@ -820,9 +885,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -832,27 +897,36 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "0.2.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" dependencies = [ "base64", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi", + "windows-sys", ] [[package]] @@ -896,18 +970,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -916,15 +990,28 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -970,13 +1057,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.90" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -987,18 +1074,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", @@ -1025,9 +1112,9 @@ checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -1040,9 +1127,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.17.0" +version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" dependencies = [ "bytes", "libc", @@ -1071,9 +1158,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls", "tokio", @@ -1082,9 +1169,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ "bytes", "futures-core", @@ -1102,9 +1189,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if", "pin-project-lite", @@ -1114,9 +1201,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ "proc-macro2", "quote", @@ -1125,9 +1212,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", ] @@ -1138,6 +1225,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicase" version = "2.6.0" @@ -1149,9 +1242,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" [[package]] name = "unicode-normalization" @@ -1162,12 +1261,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "untrusted" version = "0.7.1" @@ -1198,6 +1291,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -1216,9 +1320,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1226,9 +1330,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" dependencies = [ "bumpalo", "lazy_static", @@ -1241,9 +1345,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1251,9 +1355,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ "proc-macro2", "quote", @@ -1264,15 +1368,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" [[package]] name = "web-sys" -version = "0.3.56" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" dependencies = [ "js-sys", "wasm-bindgen", @@ -1304,6 +1408,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1312,9 +1425,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ "windows_aarch64_msvc", "windows_i686_gnu", @@ -1325,30 +1438,30 @@ dependencies = [ [[package]] name = "windows_aarch64_msvc" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_i686_gnu" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_msvc" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_x86_64_gnu" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_msvc" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml index 9f28a62..5c856cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "libreddit" description = " Alternative private front-end to Reddit" license = "AGPL-3.0" repository = "https://github.com/spikecodes/libreddit" -version = "0.22.6" +version = "0.22.8" authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"] edition = "2021" @@ -11,15 +11,17 @@ edition = "2021" askama = { version = "0.11.1", default-features = false } async-recursion = "1.0.0" cached = "0.34.0" -clap = { version = "3.1.6", default-features = false, features = ["std"] } -regex = "1.5.5" -serde = { version = "1.0.136", features = ["derive"] } +clap = { version = "3.1.18", default-features = false, features = ["std"] } +regex = "1.5.6" +serde = { version = "1.0.137", features = ["derive"] } cookie = "0.16.0" futures-lite = "1.12.0" hyper = { version = "0.14.18", features = ["full"] } hyper-rustls = "0.23.0" +percent-encoding = "2.1.0" route-recognizer = "0.3.1" -serde_json = "1.0.79" -tokio = { version = "1.17.0", features = ["full"] } +serde_json = "1.0.81" +tokio = { version = "1.18.2", features = ["full"] } time = "0.3.9" url = "2.2.2" +rust-embed = "6.4.0" diff --git a/README.md b/README.md index fc7930f..48dea6b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,6 @@ Feel free to [open an issue](https://github.com/spikecodes/libreddit/issues/new) | [reddit.invak.id](https://reddit.invak.id) | 🇧🇬 BG | | | [reddit.phii.me](https://reddit.phii.me) | 🇺🇸 US | | | [lr.riverside.rocks](https://lr.riverside.rocks) | 🇺🇸 US | | -| [libreddit.silkky.cloud](https://libreddit.silkky.cloud) | 🇫🇮 FI | ✅ | | [libreddit.strongthany.cc](https://libreddit.strongthany.cc) | 🇺🇸 US | | | [libreddit.database.red](https://libreddit.database.red) | 🇺🇸 US | ✅ | | [libreddit.privacy.com.de](https://libreddit.privacy.com.de) | 🇩🇪 DE | | @@ -72,18 +71,27 @@ Feel free to [open an issue](https://github.com/spikecodes/libreddit/issues/new) | [libreddit.hu](https://libreddit.hu) | 🇫🇮 FI | ✅ | | [libreddit.totaldarkness.net](https://libreddit.totaldarkness.net) | 🇨🇦 CA | | | [libreddit.esmailelbob.xyz](https://libreddit.esmailelbob.xyz) | 🇨🇦 CA | | +| [lr.vern.cc](https://lr.vern.cc) | 🇵🇱 PL | | | [libreddit.nl](https://libreddit.nl) | 🇳🇱 NL | | | [lr.stilic.ml](https://lr.stilic.ml) | 🇫🇷 FR | ✅ | | [reddi.tk](https://reddi.tk) | 🇺🇸 US | ✅ | | [libreddit.bus-hit.me](https://libreddit.bus-hit.me) | 🇨🇦 CA | | | [libreddit.datatunnel.xyz](https://libreddit.datatunnel.xyz) | 🇫🇮 FI | | | [libreddit.crewz.me](https://libreddit.crewz.me) | 🇳🇱 NL | ✅ | -| [r.walkx.org](https://r.walkx.org) | 🇩🇪 DE | ✅ | +| [r.walkx.org](https://r.walkx.org) | 🇳🇱 NL | ✅ | | [libreddit.kylrth.com](https://libreddit.kylrth.com) | 🇨🇦 CA | | | [libreddit.yonalee.eu](https://libreddit.yonalee.eu) | 🇱🇺 LU | ✅ | | [libreddit.winscloud.net](https://libreddit.winscloud.net) | 🇹🇭 TH | ✅ | | [libreddit.tiekoetter.com](https://libreddit.tiekoetter.com) | 🇩🇪 DE | | | [reddit.rtrace.io](https://reddit.rtrace.io) | 🇩🇪 DE | | +| [libreddit.lunar.icu](https://libreddit.lunar.icu) | 🇩🇪 DE | ✅ | +| [libreddit.privacydev.net](https://libreddit.privacydev.net) | 🇺🇸 US | | +| [libreddit.notyourcomputer.net](https://libreddit.notyourcomputer.net) | 🇺🇸 US | | +| [r.ahwx.org](https://r.ahwx.org) | 🇳🇱 NL | ✅ | +| [bob.fr.to](https://bob.fr.to) | 🇺🇸 US | | +| [reddit.beparanoid.de](https://reddit.beparanoid.de) | 🇨🇭 CH | | +| [libreddit.dcs0.hu](https://libreddit.dcs0.hu) | 🇭🇺 HU | | +| [reddit.dr460nf1r3.org](https://reddit.dr460nf1r3.org) | 🇩🇪 DE | ✅ | | [spjmllawtheisznfs7uryhxumin26ssv2draj7oope3ok3wuhy43eoyd.onion](http://spjmllawtheisznfs7uryhxumin26ssv2draj7oope3ok3wuhy43eoyd.onion) | 🇮🇳 IN | | | [fwhhsbrbltmrct5hshrnqlqygqvcgmnek3cnka55zj4y7nuus5muwyyd.onion](http://fwhhsbrbltmrct5hshrnqlqygqvcgmnek3cnka55zj4y7nuus5muwyyd.onion) | 🇩🇪 DE | | | [kphht2jcflojtqte4b4kyx7p2ahagv4debjj32nre67dxz7y57seqwyd.onion](http://kphht2jcflojtqte4b4kyx7p2ahagv4debjj32nre67dxz7y57seqwyd.onion) | 🇳🇱 NL | | @@ -96,10 +104,10 @@ Feel free to [open an issue](https://github.com/spikecodes/libreddit/issues/new) | [libreddit.2syis2nnyytz6jnusnjurva4swlaizlnleiks5mjp46phuwjbdjqwgqd.onion](http://libreddit.2syis2nnyytz6jnusnjurva4swlaizlnleiks5mjp46phuwjbdjqwgqd.onion) | 🇪🇬 EG | | | [ol5begilptoou34emq2sshf3may3hlblvipdjtybbovpb7c7zodxmtqd.onion](http://ol5begilptoou34emq2sshf3may3hlblvipdjtybbovpb7c7zodxmtqd.onion) | 🇩🇪 DE | | | [lbrdtjaj7567ptdd4rv74lv27qhxfkraabnyphgcvptl64ijx2tijwid.onion](http://lbrdtjaj7567ptdd4rv74lv27qhxfkraabnyphgcvptl64ijx2tijwid.onion) | 🇨🇦 CA | | -| [libreddit.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion](http://libreddit.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion/) | 🇨🇦 CA | | -| [libreddit.lunar.icu](https://libreddit.lunar.icu) | 🇩🇪 DE | ✅ | +| [libreddit.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion](http://libreddit.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion) | 🇨🇦 CA | | +| [reddit.prnoid54e44a4bduq5due64jkk7wcnkxcp5kv3juncm7veptjcqudgyd.onion](http://reddit.prnoid54e44a4bduq5due64jkk7wcnkxcp5kv3juncm7veptjcqudgyd.onion) | 🇨🇭 CH | | -A checkmark in the "Cloudflare" category here refers to the use of the reverse proxy, [Cloudflare](https://cloudflare). The checkmark will not be listed for a site that uses Cloudflare DNS but rather the proxying service which grants Cloudflare the ability to monitor traffic to the website. +A checkmark in the "Cloudflare" category here refers to the use of the reverse proxy, [Cloudflare](https://cloudflare.com). The checkmark will not be listed for a site that uses Cloudflare DNS but rather the proxying service which grants Cloudflare the ability to monitor traffic to the website. --- diff --git a/contrib/libreddit.conf b/contrib/libreddit.conf index 18b8193..dd91e3b 100644 --- a/contrib/libreddit.conf +++ b/contrib/libreddit.conf @@ -1,2 +1,2 @@ -ADDRESS=localhost +ADDRESS=0.0.0.0 PORT=12345 diff --git a/contrib/libreddit.service b/contrib/libreddit.service index b6e6fef..8ed5da7 100644 --- a/contrib/libreddit.service +++ b/contrib/libreddit.service @@ -11,5 +11,27 @@ Environment=PORT=8080 EnvironmentFile=-/etc/libreddit.conf ExecStart=/usr/bin/libreddit -a ${ADDRESS} -p ${PORT} +# Hardening +DeviceAllow= +LockPersonality=yes +MemoryDenyWriteExecute=yes +PrivateDevices=yes +ProcSubset=pid +ProtectClock=yes +ProtectControlGroups=yes +ProtectHome=yes +ProtectHostname=yes +ProtectKernelLogs=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +ProtectProc=invisible +RestrictAddressFamilies=AF_INET AF_INET6 +RestrictNamespaces=yes +RestrictRealtime=yes +RestrictSUIDSGID=yes +SystemCallArchitectures=native +SystemCallFilter=@system-service ~@privileged ~@resources +UMask=0077 + [Install] WantedBy=default.target diff --git a/src/client.rs b/src/client.rs index 864a6c6..da271dd 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,7 @@ use cached::proc_macro::cached; use futures_lite::{future::Boxed, FutureExt}; use hyper::{body::Buf, client, Body, Request, Response, Uri}; +use percent_encoding::{percent_encode, CONTROLS}; use serde_json::Value; use std::result::Result; @@ -90,7 +91,7 @@ fn request(url: String, quarantine: bool) -> Boxed, String .headers() .get("Location") .map(|val| { - let new_url = val.to_str().unwrap_or_default(); + let new_url = percent_encode(val.as_bytes(), CONTROLS).to_string(); format!("{}{}raw_json=1", new_url, if new_url.contains('?') { "&" } else { "?" }) }) .unwrap_or_default() diff --git a/src/main.rs b/src/main.rs index 7efa558..b6f7889 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ mod user; mod utils; // Import Crates -use clap::{Command, Arg}; +use clap::{Arg, Command}; use futures_lite::FutureExt; use hyper::{header::HeaderValue, Body, Request, Response}; @@ -19,7 +19,7 @@ use hyper::{header::HeaderValue, Body, Request, Response}; mod client; use client::proxy; use server::RequestExt; -use utils::{error, redirect}; +use utils::{error, redirect, ThemeAssets}; mod server; @@ -85,6 +85,23 @@ async fn resource(body: &str, content_type: &str, cache: bool) -> Result Result, String> { + let mut res = include_str!("../static/style.css").to_string(); + for file in ThemeAssets::iter() { + res.push('\n'); + let theme = ThemeAssets::get(file.as_ref()).unwrap(); + res.push_str(std::str::from_utf8(theme.data.as_ref()).unwrap()); + } + Ok( + Response::builder() + .status(200) + .header("content-type", "text/css") + .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") + .body(res.to_string().into()) + .unwrap_or_default(), + ) +} + #[tokio::main] async fn main() { let matches = Command::new("Libreddit") @@ -152,7 +169,7 @@ async fn main() { } // Read static files - app.at("/style.css").get(|_| resource(include_str!("../static/style.css"), "text/css", false).boxed()); + app.at("/style.css").get(|_| style().boxed()); app .at("/manifest.json") .get(|_| resource(include_str!("../static/manifest.json"), "application/json", false).boxed()); diff --git a/src/post.rs b/src/post.rs index 2ebc313..02ca380 100644 --- a/src/post.rs +++ b/src/post.rs @@ -1,6 +1,5 @@ // CRATES use crate::client::json; -use crate::esc; use crate::server::RequestExt; use crate::subreddit::{can_access_quarantine, quarantine}; use crate::utils::{ @@ -13,7 +12,7 @@ use std::collections::HashSet; // STRUCTS #[derive(Template)] -#[template(path = "post.html", escape = "none")] +#[template(path = "post.html")] struct PostTemplate { comments: Vec, post: Post, @@ -100,7 +99,10 @@ async fn parse_post(json: &serde_json::Value) -> Post { let permalink = val(post, "permalink"); let body = if val(post, "removed_by_category") == "moderator" { - format!("

[removed] — view removed post

", permalink) + format!( + "

[removed] — view removed post

", + permalink + ) } else { rewrite_urls(&val(post, "selftext_html")) }; @@ -108,7 +110,7 @@ async fn parse_post(json: &serde_json::Value) -> Post { // Build a post using data parsed from Reddit post API Post { id: val(post, "id"), - title: esc!(post, "title"), + title: val(post, "title"), community: val(post, "subreddit"), body, author: Author { @@ -119,7 +121,7 @@ async fn parse_post(json: &serde_json::Value) -> Post { post["data"]["author_flair_richtext"].as_array(), post["data"]["author_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "author_flair_background_color"), foreground_color: val(post, "author_flair_text_color"), }, @@ -143,7 +145,7 @@ async fn parse_post(json: &serde_json::Value) -> Post { post["data"]["link_flair_richtext"].as_array(), post["data"]["link_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "link_flair_background_color"), foreground_color: if val(post, "link_flair_text_color") == "dark" { "black".to_string() @@ -199,7 +201,10 @@ fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: &str, let highlighted = id == highlighted_comment; let body = if val(&comment, "author") == "[deleted]" && val(&comment, "body") == "[removed]" { - format!("

[removed] — view removed comment

", post_link, id) + format!( + "

[removed] — view removed comment

", + post_link, id + ) } else { rewrite_urls(&val(&comment, "body_html")) }; @@ -212,7 +217,7 @@ fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: &str, data["author_flair_richtext"].as_array(), data["author_flair_text"].as_str(), ), - text: esc!(&comment, "link_flair_text"), + text: val(&comment, "link_flair_text"), background_color: val(&comment, "author_flair_background_color"), foreground_color: val(&comment, "author_flair_text_color"), }, diff --git a/src/search.rs b/src/search.rs index 3547679..4dd3b5f 100644 --- a/src/search.rs +++ b/src/search.rs @@ -29,7 +29,7 @@ struct Subreddit { } #[derive(Template)] -#[template(path = "search.html", escape = "none")] +#[template(path = "search.html")] struct SearchTemplate { posts: Vec, subreddits: Vec, diff --git a/src/subreddit.rs b/src/subreddit.rs index 141c011..b03e7e9 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -1,5 +1,4 @@ // CRATES -use crate::esc; use crate::utils::{ catch_random, error, filter_posts, format_num, format_url, get_filters, param, redirect, rewrite_urls, setting, template, val, Post, Preferences, Subreddit, }; @@ -11,7 +10,7 @@ use time::{Duration, OffsetDateTime}; // STRUCTS #[derive(Template)] -#[template(path = "subreddit.html", escape = "none")] +#[template(path = "subreddit.html")] struct SubredditTemplate { sub: Subreddit, posts: Vec, @@ -28,7 +27,7 @@ struct SubredditTemplate { } #[derive(Template)] -#[template(path = "wiki.html", escape = "none")] +#[template(path = "wiki.html")] struct WikiTemplate { sub: String, wiki: String, @@ -38,7 +37,7 @@ struct WikiTemplate { } #[derive(Template)] -#[template(path = "wall.html", escape = "none")] +#[template(path = "wall.html")] struct WallTemplate { title: String, sub: String, @@ -97,7 +96,7 @@ pub async fn community(req: Request) -> Result, String> { let path = format!("/r/{}/{}.json?{}&raw_json=1", sub_name.clone(), sort, req.uri().query().unwrap_or_default()); let url = String::from(req.uri().path_and_query().map_or("", |val| val.as_str())); - let redirect_url = url[1..].replace('?', "%3F").replace('&', "%26"); + let redirect_url = url[1..].replace('?', "%3F").replace('&', "%26").replace('+', "%2B"); let filters = get_filters(&req); // If all requested subs are filtered, we don't need to fetch posts. @@ -408,9 +407,9 @@ async fn subreddit(sub: &str, quarantined: bool) -> Result { let icon = if community_icon.is_empty() { val(&res, "icon_img") } else { community_icon.to_string() }; Ok(Subreddit { - name: esc!(&res, "display_name"), - title: esc!(&res, "title"), - description: esc!(&res, "public_description"), + name: val(&res, "display_name"), + title: val(&res, "title"), + description: val(&res, "public_description"), info: rewrite_urls(&val(&res, "description_html")), // moderators: moderators_list(sub, quarantined).await.unwrap_or_default(), icon: format_url(&icon), diff --git a/src/user.rs b/src/user.rs index a5a11d0..69c4ae9 100644 --- a/src/user.rs +++ b/src/user.rs @@ -1,15 +1,14 @@ // CRATES use crate::client::json; -use crate::esc; use crate::server::RequestExt; use crate::utils::{error, filter_posts, format_url, get_filters, param, template, Post, Preferences, User}; use askama::Template; use hyper::{Body, Request, Response}; -use time::{OffsetDateTime, macros::format_description}; +use time::{macros::format_description, OffsetDateTime}; // STRUCTS #[derive(Template)] -#[template(path = "user.html", escape = "none")] +#[template(path = "user.html")] struct UserTemplate { user: User, posts: Vec, @@ -102,11 +101,11 @@ async fn user(name: &str) -> Result { // Parse the JSON output into a User struct User { name: res["data"]["name"].as_str().unwrap_or(name).to_owned(), - title: esc!(about("title")), + title: about("title"), icon: format_url(&about("icon_img")), karma: res["data"]["total_karma"].as_i64().unwrap_or(0), created: created.format(format_description!("[month repr:short] [day] '[year repr:last_two]")).unwrap_or_default(), - banner: esc!(about("banner_img")), + banner: about("banner_img"), description: about("public_description"), } }) diff --git a/src/utils.rs b/src/utils.rs index b7c5285..6058f1d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,15 +1,16 @@ // // CRATES // -use crate::{client::json, esc, server::RequestExt}; +use crate::{client::json, server::RequestExt}; use askama::Template; use cookie::Cookie; use hyper::{Body, Request, Response}; use regex::Regex; +use rust_embed::RustEmbed; use serde_json::Value; use std::collections::{HashMap, HashSet}; use std::str::FromStr; -use time::{Duration, OffsetDateTime, macros::format_description}; +use time::{macros::format_description, Duration, OffsetDateTime}; use url::Url; // Post flair with content, background color and foreground color @@ -41,7 +42,7 @@ impl FlairPart { Self { flair_part_type: value("e").to_string(), value: match value("e") { - "text" => esc!(value("t")), + "text" => value("t").to_string(), "emoji" => format_url(value("u")), _ => String::new(), }, @@ -54,7 +55,7 @@ impl FlairPart { "text" => match text_flair { Some(text) => vec![Self { flair_part_type: "text".to_string(), - value: esc!(text), + value: text.to_string(), }], None => Vec::new(), }, @@ -217,24 +218,19 @@ pub struct Post { impl Post { // Fetch posts of a user or subreddit and return a vector of posts and the "after" value pub async fn fetch(path: &str, quarantine: bool) -> Result<(Vec, String), String> { - let res; - let post_list; - // Send a request to the url - match json(path.to_string(), quarantine).await { + let res = match json(path.to_string(), quarantine).await { // If success, receive JSON in response - Ok(response) => { - res = response; - } + Ok(response) => response, // If the Reddit API returns an error, exit this function Err(msg) => return Err(msg), - } + }; // Fetch the list of posts from the JSON response - match res["data"]["children"].as_array() { - Some(list) => post_list = list, + let post_list = match res["data"]["children"].as_array() { + Some(list) => list, None => return Err("No posts found".to_string()), - } + }; let mut posts: Vec = Vec::new(); @@ -245,7 +241,7 @@ impl Post { let (rel_time, created) = time(data["created_utc"].as_f64().unwrap_or_default()); let score = data["score"].as_i64().unwrap_or_default(); let ratio: f64 = data["upvote_ratio"].as_f64().unwrap_or(1.0) * 100.0; - let title = esc!(post, "title"); + let title = val(post, "title"); // Determine the type of media along with the media URL let (post_type, media, gallery) = Media::parse(data).await; @@ -270,7 +266,7 @@ impl Post { data["author_flair_richtext"].as_array(), data["author_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "author_flair_background_color"), foreground_color: val(post, "author_flair_text_color"), }, @@ -298,7 +294,7 @@ impl Post { data["link_flair_richtext"].as_array(), data["link_flair_text"].as_str(), ), - text: esc!(post, "link_flair_text"), + text: val(post, "link_flair_text"), background_color: val(post, "link_flair_background_color"), foreground_color: if val(post, "link_flair_text_color") == "dark" { "black".to_string() @@ -324,7 +320,7 @@ impl Post { } #[derive(Template)] -#[template(path = "comment.html", escape = "none")] +#[template(path = "comment.html")] // Comment with content, post, score and data/time that it was posted pub struct Comment { pub id: String, @@ -400,7 +396,7 @@ impl Awards { } #[derive(Template)] -#[template(path = "error.html", escape = "none")] +#[template(path = "error.html")] pub struct ErrorTemplate { pub msg: String, pub prefs: Preferences, @@ -445,6 +441,7 @@ pub struct Params { #[derive(Default)] pub struct Preferences { + pub available_themes: Vec, pub theme: String, pub front_page: String, pub layout: String, @@ -459,10 +456,23 @@ pub struct Preferences { pub filters: Vec, } +#[derive(RustEmbed)] +#[folder = "static/themes/"] +#[include = "*.css"] +pub struct ThemeAssets; + impl Preferences { // Build preferences from cookies pub fn new(req: Request) -> Self { + // Read available theme names from embedded css files. + // Always make the default "system" theme available. + let mut themes = vec!["system".to_string()]; + for file in ThemeAssets::iter() { + let chunks: Vec<&str> = file.as_ref().split(".css").collect(); + themes.push(chunks[0].to_owned()) + } Self { + available_themes: themes, theme: setting(&req, "theme"), front_page: setting(&req, "front_page"), layout: setting(&req, "layout"), @@ -608,8 +618,7 @@ pub fn format_url(url: &str) -> String { // Rewrite Reddit links to Libreddit in body of text. // Also fix superfluous backslashes and underscores in links. pub fn rewrite_urls(input_text: &str) -> String { - let text1 = - Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|new\.)(reddit\.com|redd\.it)/"#) + let text1 = Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|new\.)(reddit\.com|redd\.it)/"#) // Replace reddit-prefix in href with "/" (i.e. point to our local instance). .map_or(String::new(), |re| re.replace_all(input_text, r#"href="/"#).to_string()) // Remove (html-encoded) "\" from URLs. These seem to occur inside the href-attribute only. @@ -659,7 +668,12 @@ pub fn time(created: f64) -> (String, String) { format!("{}m ago", time_delta.whole_minutes()) }; - (rel_time, time.format(format_description!("[month repr:short] [day] [year], [hour]:[minute]:[second] UTC")).unwrap_or_default()) + ( + rel_time, + time + .format(format_description!("[month repr:short] [day] [year], [hour]:[minute]:[second] UTC")) + .unwrap_or_default(), + ) } // val() function used to parse JSON from Reddit APIs @@ -667,17 +681,6 @@ pub fn val(j: &Value, k: &str) -> String { j["data"][k].as_str().unwrap_or_default().to_string() } -// Escape < and > to accurately render HTML -#[macro_export] -macro_rules! esc { - ($f:expr) => { - $f.replace('&', "&").replace('<', "<").replace('>', ">") - }; - ($j:expr, $k:expr) => { - $j["data"][$k].as_str().unwrap_or_default().to_string().replace('<', "<").replace('>', ">") - }; -} - // // NETWORKING // diff --git a/static/style.css b/static/style.css index 90d849c..3e0d64d 100644 --- a/static/style.css +++ b/static/style.css @@ -45,124 +45,7 @@ } } -/* Light theme setting */ -.light { - --accent: #009a9a; - --green: #00a229; - --text: black; - --foreground: #f5f5f5; - --background: #ddd; - --outside: #ececec; - --post: #eee; - --panel-border: 1px solid #ccc; - --highlighted: white; - --visited: #555; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Black theme setting */ -.black { - --accent: #009a9a; - --green: #00a229; - --text: white; - --foreground: #0f0f0f; - --background: black; - --outside: black; - --post: black; - --panel-border: 2px solid #0f0f0f; - --highlighted: #0f0f0f; - --visited: #aaa; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Dracula theme setting */ -.dracula { - --accent: #bd93f9; - --green: #50fa7b; - --text: #f8f8f2; - --foreground: #3d4051; - --background: #282a36; - --outside: #393c4d; - --post: #333544; - --panel-border: 2px solid #44475a; - --highlighted: #4e5267; - --visited: #969692; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Nord theme setting */ -.nord { - --accent: #8fbcbb; - --green: #a3be8c; - --text: #eceff4; - --foreground: #3b4252; - --background: #2e3440; - --outside: #434c5e; - --post: #434c5e; - --panel-border: 2px solid #4c566a; - --highlighted: #3b4252; - --visited: #a3a5aa; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Laserwave theme setting */ -.laserwave { - --accent: #eb64b9; - --green: #74dfc4; - --text: #e0dfe1; - --foreground: #302a36; - --background: #27212e; - --outside: #3e3647; - --post: #3e3647; - --panel-border: 2px solid #2f2738; - --highlighted: #302a36; - --visited: #91889b; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -/* Violet theme setting */ -.violet { - --accent: #7c71dd; - --green: #5cff85; - --text: white; - --foreground: #1F2347; - --background: #12152b; - --outside: #181c3a; - --post: #181c3a; - --panel-border: 1px solid #1F2347; - --highlighted: #1F2347; - --visited: #aaa; - --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); -} - -/* Gold theme setting */ -.gold { - --accent: #f2aa4c; - --green: #5cff85; - --text: white; - --foreground: #234; - --background: #101820; - --outside: #1b2936; - --post: #1b2936; - --panel-border: 0px solid black; - --highlighted: #234; - --visited: #aaa; - --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); -} - -/* Rosebox theme setting */ -.rosebox { - --accent: #a57562; - --green: #a3be8c; - --text: white; - --foreground: #222; - --background: #262626; - --outside: #222; - --post: #222; - --panel-border: 1px solid #222; - --highlighted: #262626; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.5); -} +/* Other themes are located in the "themes" folder */ /* General */ @@ -177,6 +60,7 @@ html, body, div, h1, h2, h3, h4, h5, h6, ul, ol, dl, li, dt, dd, p, blockquote, pre, form, fieldset, table, th, td, select, input { + accent-color: var(--accent); margin: 0; color: var(--text); font-family: "Inter", sans-serif; @@ -893,6 +777,7 @@ a.search_subreddit:hover { padding: 5px 15px 5px 12px; grid-area: post_body; width: calc(100% - 30px); + overflow-wrap: anywhere; } /* Used only for text post preview */ diff --git a/static/themes/black.css b/static/themes/black.css new file mode 100644 index 0000000..5906b5b --- /dev/null +++ b/static/themes/black.css @@ -0,0 +1,14 @@ +/* Black theme setting */ +.black { + --accent: #009a9a; + --green: #00a229; + --text: white; + --foreground: #0f0f0f; + --background: black; + --outside: black; + --post: black; + --panel-border: 2px solid #0f0f0f; + --highlighted: #0f0f0f; + --visited: #aaa; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/dracula.css b/static/themes/dracula.css new file mode 100644 index 0000000..0e36e2b --- /dev/null +++ b/static/themes/dracula.css @@ -0,0 +1,14 @@ +/* Dracula theme setting */ +.dracula { + --accent: #bd93f9; + --green: #50fa7b; + --text: #f8f8f2; + --foreground: #3d4051; + --background: #282a36; + --outside: #393c4d; + --post: #333544; + --panel-border: 2px solid #44475a; + --highlighted: #4e5267; + --visited: #969692; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/gold.css b/static/themes/gold.css new file mode 100644 index 0000000..4ff7d6e --- /dev/null +++ b/static/themes/gold.css @@ -0,0 +1,14 @@ +/* Gold theme setting */ +.gold { + --accent: #f2aa4c; + --green: #5cff85; + --text: white; + --foreground: #234; + --background: #101820; + --outside: #1b2936; + --post: #1b2936; + --panel-border: 0px solid black; + --highlighted: #234; + --visited: #aaa; + --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/static/themes/laserwave.css b/static/themes/laserwave.css new file mode 100644 index 0000000..dde21f3 --- /dev/null +++ b/static/themes/laserwave.css @@ -0,0 +1,14 @@ +/* Laserwave theme setting */ +.laserwave { + --accent: #eb64b9; + --green: #74dfc4; + --text: #e0dfe1; + --foreground: #302a36; + --background: #27212e; + --outside: #3e3647; + --post: #3e3647; + --panel-border: 2px solid #2f2738; + --highlighted: #302a36; + --visited: #91889b; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/light.css b/static/themes/light.css new file mode 100644 index 0000000..1fe0387 --- /dev/null +++ b/static/themes/light.css @@ -0,0 +1,14 @@ +/* Light theme setting */ +.light { + --accent: #009a9a; + --green: #00a229; + --text: black; + --foreground: #f5f5f5; + --background: #ddd; + --outside: #ececec; + --post: #eee; + --panel-border: 1px solid #ccc; + --highlighted: white; + --visited: #555; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/static/themes/nord.css b/static/themes/nord.css new file mode 100644 index 0000000..d75fd11 --- /dev/null +++ b/static/themes/nord.css @@ -0,0 +1,14 @@ +/* Nord theme setting */ +.nord { + --accent: #8fbcbb; + --green: #a3be8c; + --text: #eceff4; + --foreground: #3b4252; + --background: #2e3440; + --outside: #434c5e; + --post: #434c5e; + --panel-border: 2px solid #4c566a; + --highlighted: #3b4252; + --visited: #a3a5aa; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} diff --git a/static/themes/rosebox.css b/static/themes/rosebox.css new file mode 100644 index 0000000..903931d --- /dev/null +++ b/static/themes/rosebox.css @@ -0,0 +1,13 @@ +/* Rosebox theme setting */ +.rosebox { + --accent: #a57562; + --green: #a3be8c; + --text: white; + --foreground: #222; + --background: #262626; + --outside: #222; + --post: #222; + --panel-border: 1px solid #222; + --highlighted: #262626; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/static/themes/violet.css b/static/themes/violet.css new file mode 100644 index 0000000..0d836ee --- /dev/null +++ b/static/themes/violet.css @@ -0,0 +1,14 @@ +/* Violet theme setting */ +.violet { + --accent: #7c71dd; + --green: #5cff85; + --text: white; + --foreground: #1F2347; + --background: #12152b; + --outside: #181c3a; + --post: #181c3a; + --panel-border: 1px solid #1F2347; + --highlighted: #1F2347; + --visited: #aaa; + --shadow: 0 2px 5px rgba(0, 0, 0, 0.5); +} \ No newline at end of file diff --git a/templates/comment.html b/templates/comment.html index 3014192..61c44f5 100644 --- a/templates/comment.html +++ b/templates/comment.html @@ -32,9 +32,9 @@ {% if is_filtered %}
(Filtered content)
{% else %} -
{{ body }}
+
{{ body|safe }}
{% endif %} -
{% for c in replies -%}{{ c.render().unwrap() }}{%- endfor %} +
{% for c in replies -%}{{ c.render().unwrap()|safe }}{%- endfor %}
diff --git a/templates/post.html b/templates/post.html index add5881..97715ec 100644 --- a/templates/post.html +++ b/templates/post.html @@ -110,7 +110,7 @@ {% endif %} -
{{ post.body }}
+
{{ post.body|safe }}
{{ post.score.0 }} Upvotes
{%- endfor %} diff --git a/templates/search.html b/templates/search.html index 0218c35..c5cff86 100644 --- a/templates/search.html +++ b/templates/search.html @@ -39,7 +39,7 @@ {% endif %} {% for subreddit in subreddits %} -
{% if subreddit.icon != "" %}r/{{ subreddit.name }} icon{% endif %}
+
{% if subreddit.icon != "" %}r/{{ subreddit.name }} icon{% endif %}
diff --git a/templates/subreddit.html b/templates/subreddit.html index 61f78db..3ef318e 100644 --- a/templates/subreddit.html +++ b/templates/subreddit.html @@ -127,7 +127,7 @@ {% endif %} diff --git a/templates/utils.html b/templates/utils.html index a11583f..e4c6f75 100644 --- a/templates/utils.html +++ b/templates/utils.html @@ -38,7 +38,6 @@ {%- endmacro %} {% macro sub_list(current) -%} -{% if prefs.subscriptions.len() > 0 %}
Feeds
@@ -46,13 +45,14 @@ Home Popular All -

REDDIT FEEDS

- {% for sub in prefs.subscriptions %} - {{ sub }} - {% endfor %} + {% if prefs.subscriptions.len() > 0 %} +

REDDIT FEEDS

+ {% for sub in prefs.subscriptions %} + {{ sub }} + {% endfor %} + {% endif %}
-{% endif %} {%- endmacro %} {% macro render_hls_notification(redirect_url) -%} @@ -138,7 +138,7 @@
{{ post.score.0 }} Upvotes
- {{ post.body }} + {{ post.body|safe }}
- {{ wiki }} + {{ wiki|safe }}
-{% endblock %} \ No newline at end of file +{% endblock %}