aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2024-06-23 13:43:59 -0400
committerXe Iaso <me@xeiaso.net>2024-06-23 13:43:59 -0400
commit6502d63af188750dbc4ff4b8d0b59199a52e03c8 (patch)
tree5f7bf4dfdd5204b17a5edf2f0dcb69a575d452b3
parentf3f7c1f36d22cb19d38317c414ef33e59c9cfa01 (diff)
downloadxesite-6502d63af188750dbc4ff4b8d0b59199a52e03c8.tar.xz
xesite-6502d63af188750dbc4ff4b8d0b59199a52e03c8.zip
blog: fixing RSS with mailcap
Signed-off-by: Xe Iaso <me@xeiaso.net>
-rw-r--r--Brewfile.lock.json8
-rw-r--r--lume/src/blog/2024/fixing-rss-mailcap.mdx170
-rw-r--r--lume/src/static/blog/fixing-rss-mailcap/how-it-broke.excalidraw.svg21
-rw-r--r--lume/src/static/blog/fixing-rss-mailcap/how-it-should-work.excalidraw.svg21
-rw-r--r--lume/src/static/blog/fixing-rss-mailcap/mime-registry.excalidraw.svg21
-rw-r--r--lume/src/static/blog/fixing-rss-mailcap/serveContent-flow.excalidraw.svg21
6 files changed, 261 insertions, 1 deletions
diff --git a/Brewfile.lock.json b/Brewfile.lock.json
index 30e2112..33db291 100644
--- a/Brewfile.lock.json
+++ b/Brewfile.lock.json
@@ -641,7 +641,13 @@
"HOMEBREW_PREFIX": "/home/linuxbrew/.linuxbrew",
"Homebrew/homebrew-core": "api",
"GCC": "11.4.0"
+ },
+ "Ubuntu 22.04.3 LTS (jammy)": {
+ "HOMEBREW_VERSION": "4.3.6",
+ "HOMEBREW_PREFIX": "/home/linuxbrew/.linuxbrew",
+ "Homebrew/homebrew-core": "api",
+ "GCC": "11.4.0"
}
}
}
-} \ No newline at end of file
+}
diff --git a/lume/src/blog/2024/fixing-rss-mailcap.mdx b/lume/src/blog/2024/fixing-rss-mailcap.mdx
new file mode 100644
index 0000000..dbcb9f7
--- /dev/null
+++ b/lume/src/blog/2024/fixing-rss-mailcap.mdx
@@ -0,0 +1,170 @@
+---
+title: "MIME, RSS, and existential torment"
+date: 2024-06-23
+desc: "TL;DR: how I fixed my RSS feed by installing mailcap so I don't get tormented by mimes"
+hero:
+ social: true
+ ai: "Photo by Xe Iaso, Canon EOS R6 mark ii, Helios 44-2 58mm at f/8"
+ file: "spring-peace"
+ prompt: "Greenery next to a retaining pond, with a path and a trashcan. The sky is reflecting off of the water."
+---
+
+This morning, I woke up with a flurry of emails in my inbox. When people tried to read my blog's RSS feed, they got an error like this:
+
+```
+$ curl https://xeiaso.net
+seeker can't seek
+```
+
+This should not happen. When I first encountered this, I had to do a double-take. When I remade my website for [version 4](/blog/xesite-v4/) I did make some weird technical decisions and I figured one of those was coming back to bite me. One of the weirdest things my website does is that it serves everything from a .zip file. As far as I understand my blog, here's what I expect to happen when somebody requests a file:
+
+![](/static/blog/fixing-rss-mailcap/how-it-should-work.excalidraw.svg)
+
+When someone fetches a file I expect it to interact with the lume FileSystem component, pass it to the zip file, get a file back, and then serve it back to the user with happy puppies and HTTP 200 responses. This was not happening, and the error that I got was initially very confusing.
+
+The actual reason why this was happening trolled me so hard that I felt the need to write about it so that y'all are able to understand all of the moving parts and why it failed in this way in particular.
+
+## Go interfaces
+
+In Go, interfaces are used to describe abstract behaviors that apply between types. As an absurd example, let's imagine something that has the behavior of quacking. In Go you'd probably write an interface like this to represent this behavior:
+
+```go
+type Quacker interface {
+ Quack()
+}
+```
+
+So, for some type `Duck`, you could make it quack like this:
+
+```go
+type Duck struct{}
+
+func (Duck) Quack() { fmt.Println("Quack!") }
+```
+
+And then you can pass a `Duck` value anywhere that takes a `Quacker`, even if the underlying implementation is something absurd:
+
+```go
+type Sheep struct{}
+
+func (Sheep) Quack() { fmt.Println("Baaaaa") }
+```
+
+Interfaces are used all over the standard library and they make a lot of things really damn convenient in practice. Want to override how a HTTP request works? Define your own [`net/http#RoundTripper`](https://pkg.go.dev/net/http#RoundTripper). When you define HTTP handlers, you're dealing with the [`net/http#Handler`](https://pkg.go.dev/net/http#Handler) interface. Interfaces are everywhere and they are lovely.
+
+One of the more recent and exciting interfaces is [`io/fs.FS`](https://pkg.go.dev/io/fs#FS), which represents an abstract "filesystem". This allows you to make filesystem logic pluggable so that you can [embed filesystems into your code](https://pkg.go.dev/embed#hdr-File_Systems), or read stuff out of anything that implements the `io/fs#FS` interface. One of these things is a .zip file reader, AKA [`archive/zip#Reader`](https://pkg.go.dev/archive/zip#Reader).
+
+This is the core of how my website works. Every time you read anything from my site, you're actually looking at the contents of a zipfile full of gzip streams.
+
+So anyways, you go to the RSS feed and then you get a HTTP 500 back. The flow looks like this:
+
+![](/static/blog/fixing-rss-mailcap/how-it-broke.excalidraw.svg)
+
+The Go HTTP package [has had its own filesystem logic](https://pkg.go.dev/net/http#FileSystem) for a while, since Go 1.0. Here's its view of what a `File` should be:
+
+```go
+// imagine this is in net/http
+package http
+
+import "io/fs"
+
+type File interface {
+ io.Closer
+ io.Reader
+ io.Seeker
+ Readdir(count int) ([]fs.FileInfo, error)
+ Stat() (fs.FileInfo, error)
+}
+```
+
+Here's what `io/fs` thinks a file should be:
+
+```go
+package fs
+
+type File interface {
+ Stat() (FileInfo, error)
+ Read([]byte) (int, error)
+ Close() error
+}
+```
+
+A `net/http#File` is a _more specific_ interface than a `io/fs#File`, which means that not all things that can be represented as an `io/fs#File` can work as a `net/http#File`.
+
+<Conv name="Mara" mood="hacker">
+In Go, you generally call interfaces with more methods "more specific" than ones that have less methods. When you are making interfaces in Go, it's generally seen that a smaller interface is better than a bigger one because those are more easy to compose. A file can be read from, but so can a network socket or a HTTP response body. If you make your interfaces vague, then they can apply many other places.
+
+Consider this [Go proverb](https://go-proverbs.github.io/):
+
+<BlockQuote>
+The bigger the interface, the weaker the abstraction.
+</BlockQuote>
+</Conv>
+
+This all matters because when the standard library HTTP fileserver tries to serve a file, it has to figure out the `Content-Type` of that file. The code is [in a function imaginatively named `serveContent`](https://github.com/golang/go/blob/2073b35e07ce9cea47ee1fbe763b304d2371954f/src/net/http/fs.go#L242-L254), but the overall flow looks kinda like this:
+
+![](/static/blog/fixing-rss-mailcap/serveContent-flow.excalidraw.svg)
+
+Whenever you try to serve a file that doesn't already have a `Content-Type` header defined, it tries to detect it from the extension. If it can't, it'll try to read the first 512 bytes of the file to detect what kind of file it is, and then rewind the file back so that it can be served to the user.
+
+Unless that file doesn't have a working `.Seek` method.
+
+As it turns out, when you read `io/fs#File`s from a zipfile, they don't have a `.Seek` method defined. This makes sense because any file in a zipfile exists in a superposition of both being compressed and not being compressed that only gets resolved when the file is read from. It doesn't make sense to be able to rewind a compressed stream and then get back data from earlier in it. You'd have to put everything in memory and then you could run out of memory and crash.
+
+The reason we got this `seeker can't seek` error is because they added a "type shim" to allow an `io/fs#File` to act as a `net/http#File`. Here's the codepath I hit:
+
+```go
+var errMissingSeek = errors.New("seeker can't seek")
+
+func (f ioFile) Seek(offset int64, whence int) (int64, error) {
+ s, ok := f.file.(io.Seeker)
+ if !ok {
+ return 0, errMissingSeek
+ }
+ return s.Seek(offset, whence)
+}
+```
+
+A zipfile's `io/fs#File` isn't an [`io.Seeker`](https://pkg.go.dev/io#Seeker). This means that any time the `net/http#FileSystem` logic tried to seek, it instantly got that `seeker can't seek` error and blew up.
+
+## Getting trolled by MIMEs
+
+However, we don't have to fix this problem today. We can work around it with the power of the MIME registry.
+
+<Conv name="Aoi" mood="wut">
+ I don't get it, if this is broken now, then how did it ever work in the first
+ place?
+</Conv>
+
+That first step of the diagram is the relevant bit. If the file extension is in the MIME registry, then it'll be returned to the user:
+
+![](/static/blog/fixing-rss-mailcap/mime-registry.excalidraw.svg)
+
+Go has a [minimal subset](https://github.com/golang/go/blob/2073b35e07ce9cea47ee1fbe763b304d2371954f/src/mime/type.go#L60-L77) of very very commonly used MIME types so that things will Just Work™️, but when the program starts, it tries to read all of the other common MIME-extension pairs out of `/etc/mime.types` (and a few other places).
+
+Guess what file wasn't present in the Docker image I made with Earthly?
+
+In Alpine Linux, this file is [in the `mailcap` package](https://pkgs.alpinelinux.org/contents?file=mime.types&path=&name=&branch=edge&repo=main&arch=ppc64le). Fixing this was as easy as changing a single line in my Earthly configuration:
+
+```diff
+- RUN apk add -U ca-certificates deno typst
++ RUN apk add -U ca-certificates deno typst mailcap
+```
+
+<Conv name="Cadey" mood="coffee">
+ God, I feel like a buffoon. How the hell am I employable???
+</Conv>
+<Conv name="Numa" mood="happy">
+ Don't worry, this is why we get paid the big bucks. The more you fuck around
+ like this, the weirder it is when you find out why.
+</Conv>
+
+## Conclusion
+
+This is why the RSS feed was broken. It was broken because I got trolled by a bunch of MIMEs. No (mail)cap, fr fr.
+
+<Conv name="Aoi" mood="coffee">
+ Please don't.
+</Conv>
+
+If you want to watch me suffer through explaining things like this, [follow me on Twitch](https://twitch.tv/princessxen). We'll all learn together.
diff --git a/lume/src/static/blog/fixing-rss-mailcap/how-it-broke.excalidraw.svg b/lume/src/static/blog/fixing-rss-mailcap/how-it-broke.excalidraw.svg
new file mode 100644
index 0000000..9daef0d
--- /dev/null
+++ b/lume/src/static/blog/fixing-rss-mailcap/how-it-broke.excalidraw.svg
@@ -0,0 +1,21 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 803 667.5" width="1606" height="1335">
+ <!-- svg-source:excalidraw -->
+ <!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1dW1Piylx1MDAxNn6fX2G5XHUwMDFmzjlVm0zfL/vNXHUwMDBiKjreXHUwMDA2ddAzp6xcdTAwMDBRUCCYXHUwMDA0RXft/346qOTWXHRcdTAwMDGCgzpYNaMhSXc6a33rW5fu/vvLysqq99i3Vv9aWbWGXHKz02465sPqn/7xe8tx23ZPfYVGf7v2wGmMzmx5Xt/96+vX4Fxuo2F3n6+yOlbX6nmuOu+/6u+Vlb9H/4bacayGZ/auO9bogtFXQVOEy/jRXHUwMDAzuzdqXHUwMDE2XHUwMDAyylx0lJBcdTAwMDRntHtNa+jf0zxcYm7WdjdVJzyrqb64MjuuXHUwMDE1fONcdTAwMWZaPXFOh4dcdTAwMTeNzbN+e7h9XdrsOccnPLj8qt3pVL3Hzqivrq2eL/jO9Vx1MDAxY/vW+tFueq3XYVx0XHUwMDFkT7vKsVx1MDAwN9etnuX6Y1x1MDAwMsdH7b7ZaHuPo1x1MDAwN1x1MDAwM+Ojz1x1MDAwM/PXSnDEfz7EqEHHR/xrJCCx1jfsju34rf9cdTAwMDElh1xyXHUwMDE0tF83XHUwMDFit9eqXHUwMDEzvWZwjkmb4uoqOOfh5ZkgZIaMfMantKz2dcuL9de1RuNcZrnAhFx0XHSC0/1cdTAwMTb7leZIXHUwMDEw/lx1MDAxN4yuY3atin9Jb9DphIeo13xcdTAwMTmiV4FcdERcdTAwMDa/XHUwMDFj+Sd4JP/8clxc1MLiXHUwMDE2XHUwMDExOc9cdTAwMWF642dcconC2ebFKXLLtZtvjY6E1mnlad2+X1x1MDAxZJ/3z5/62z5fLE+fnqpnl+B2c3/vgrNvXHUwMDE2sFx1MDAwZm+irby2bzqO/ZD3vi3r5uT+sN1slftybYNDm3Xx93z3ffktXHUwMDE47kG/aXovb0ipXHUwMDBlXHUwMDE1nFx1MDAwMCTE+PtOu3dcdTAwMWJ/XHUwMDE3XHUwMDFku3FcdTAwMWIoz5dQh1x1MDAxM6pcdTAwMWNcdTAwMTnXsFx1MDAxNkORqsVcdTAwMTBhgriAUKPFh/m1WP/qlluLJTZcdTAwMTiBjKl/XHUwMDEwpjim0UguRKNcdTAwMTkwuN8mh5xcItVcYk8qNE3os1BdlFx1MDAwMkg8vzpHvkjobYaoXG6MXHUwMDAxxlOIatAru+dV20/+XHUwMDFiQCBydMvstjuPkTc4kmE1gKeu5az87HXMvmf3VyNfr3Xa175YrzZUty0nXCLxXlvZwPFcdN12s1x1MDAxOTZsXHLVptnuWU4lj+mxnfZ1u2d2TsJdinfIXHUwMDFjePZ3y31+PM9cdTAwMTlY4Vx1MDAxMbJ2xiBtIJqpu9lmXHUwMDE48fjRsVx1MDAwMqu3wjBmUmeGj/Ir8O5lyYZr/W97XHUwMDA3N939vd1LsN+5cJZbgZkyjlGlXHUwMDE1LENpLf8nW2ktaTUsjdJcdTAwMTJcdTAwMWM8VaCmMmj8RU9cdTAwMTFQMFwiXHSkwet6W7ubrr+cScAlXHRL51wiTFxylCBdUplEXHUwMDFjccA1knqcX1LpRve4NahcdTAwMWNv7Hv3d6WyVbHMI3e5JZVcdTAwMGJkKCXFmEKIKaIkKrVcXCxEaiHAXHUwMDA2V40qI8ORJFx1MDAxMmmEXHUwMDE4JWRcdTAwMThcdTAwMTLKXHUwMDA1XHUwMDEzXHUwMDA0XHUwMDE1wFx1MDAxZN+LsWl0m1+HXG7EPWtWS1x1MDAxM7FcdFEzXHUwMDEz6XXcpuhaLsqkPNNRjZJKhuNHX5VcdTAwMTRcdESZxFSno7X8OppNxpdSR7EgcaeOzKWXnmP23L7pKNFJ6iZiXHUwMDFhT45cdTAwMDY9f1FGXGa4z1x1MDAxNXFcdTAwMDHEL2lP0Pz2hIZFM6+Kup7peOtKrtq962jHXqJcdTAwMTV52NlIqVx1MDAxYlx1MDAwM7+XwFCWxcdcZikwl1DQYLj8XHUwMDAxM/vaZ7V6zcl9qPGmpJX1M3xcdTAwMDNcdTAwMWZcdTAwMWGPW26V3po9XVx1MDAxZkrAIJhwglx1MDAxMFx1MDAwMmpwJOQk0Vx1MDAwN5LoQ8d0vVxyu9tte2poj+x2z4tcdTAwMGbhaKzWfEVuWWbi/apnXGJ/XHUwMDE31/i+f8eoP1x1MDAxZfy2XHUwMDEyyP/oj/Hv//tTe7aA4dNLXHUwMDE0TrogJOKjK6ShyFx1MDAxMYVgJD9QYlx1MDAxMdzgS/j/aSlcdTAwMDdCLFxyzZTx44Rcblx1MDAxMIhpgGbn+dHsybrbKlxyb9vOsOI13e1cdTAwMWS+Uz/fWm40I1x1MDAxMFx1MDAxYYxcdTAwMDKghFx1MDAxMVFFMFx1MDAwMrQpgCdnXCJcdTAwMWLE3GB+pIop/EQkL+kgXGIwJj5cdTAwMTPp2C6frHytd+xrw3Hdt+ZcdTAwMWQpjb+JN8tRKv2gXHUwMDEySEgw10WjevlcdTAwMTX2tlu+WS9tfCt32c5T01x1MDAxYjaHpzWy3FxuK0E8plxmXHUwMDExo7Hmi9NSoVFLXHUwMDFjXHUwMDAyhVx1MDAxN7VkWPlcdTAwMDJcdTAwMTFcdTAwMDB9XHUwMDBmceSrXHLvaWu9dm5urpkn91x1MDAxYtueU346y1x1MDAxYu818YF1Wf1cdTAwMDGc4yGGcu/KdfZ6h9FWZooj1/dPK9DbtGvejjwv9b+JvertVVx1MDAwMfetXFzh3oE4R1x1MDAxN42Kfb+7f/njZmhcdTAwMGVcbrhvt/79m1x1MDAwYmq89n3LXHUwMDExN7uHzbN660dBce/pyeNMzIBcdTAwMDNcdTAwMTQ/OmZcdTAwMDZcZlLFXHUwMDFhiVx1MDAwZWjs/ECjl7TlXHUwMDA2XHUwMDFhKFxm36nQh70h4mE3qGjYodQgLDv6jVx1MDAxMtFvxahcdTAwMDVcdTAwMTWEvP/wN2SRo1x1MDAxOeSgM+haxlZ1QYHvXHT2MU5cdTAwMTZcdTAwMTKdeVx1MDAxM5pASSpNUKRWXHRcdTAwMTBE2qB3P7/6bp+d0tLNxe5BfbtcdTAwMDaPz1x1MDAxZrdv26XycquvQs44T8BcdTAwMGJV2XCXXHUwMDAyqlx1MDAxMFxi8itVXHUwMDAwmDEgJVpIqGJhVEHuts5qllfu4o51NFx1MDAwMPXeWVx1MDAxNTy9Y5O+LKaXiFTTq9SWU6qsL9Yo791cdTAwMTQxRu2rW3LllVx1MDAwNlSWXHUwMDA0XHUwMDEzTFx1MDAwMVx1MDAxNVTGXHUwMDE0WaBcdTAwMDUq8mtcdTAwMGVCjb9cdTAwMTBIQJ1jnrC9nEqOhHz3bnl+y2s6jVb73vr61F5U2nmC1YlbX22H5rXAzyq0tVdex/iBn8Pv5abcq7Q2rlx1MDAwZWnoqfWJhFFGi8di5aE3XHUwMDE0WFx1MDAwZU2Mm2fpSFFcIv9rdX8qXHUwMDE1XHSgz1nV6k2euP3YXHUwMDA2U0RcdTAwMDFCXGKGZfNcdTAwMDWRcXrURSmaIJJcdTAwMDFcdTAwMWXK+qSCb1xcdSNPU2CWoNDgNYucjsik80Oi6394qIGEhc1cdTAwMTnELzbZwFn0J3TWS7LBoFx0McmV8qiebdLL2uD05qLskY4t8eHmzlZKL7DEypZcYshcYkCK/NFEL2CiXHUwMDBmsyQ0ZmIgXHUwMDE4pFZcIozy21KfXHUwMDE2cPNcdTAwMTOQ4WH/QtZbnb0+3Ohgp4XK+9bDsoCQnoBcYkJccunXvFFG1P+h8McziPNYT1xudCMgMKBf+CY4gD7gXHUwMDA0udVcZvohXHUwMDE5XCJcdTAwMTihXCLij++Ff3zEtMBLXHUwMDFhbehVNr5cdTAwMWTdPNytO9W1g8bxyaBv5WJcdTAwMWJcdTAwMTJFK2YgICghYVx1MDAxMiYlXG5cdTAwMDKRoVx1MDAxMZ+abnhz01xyodhcdTAwMDaEiNCwXHUwMDFjvqIvTGVcdTAwMWJSMuVQXGJcdTAwMWFy/z5cdTAwMTbZKMFcYnlgky+Qkdy6XHUwMDEy2regXHUwMDFiuVxyvVx1MDAwMm7MIFx1MDAwN1xiXCLOqKQ8UL5cZkOfi2w8VStcdTAwMDNYbpy522Z1+Hh98uOAlqG+XHUwMDBmXHUwMDFjSF/cXHUwMDAwxEiBMlx1MDAxNYkuJGNEhXGNZ/xyjm1yYm22THQnvYt9XHUwMDE3iuN7nMSvKCF5XHUwMDBluWND+sl4wFx1MDAxOVKUKVx1MDAxNr9TXHUwMDBmljSXiFx1MDAxOMDPolx1MDAwYsJcdERQg23ktyeVXHUwMDAybfd6aIsqyTOGMUJcdFx1MDAxN+GEcy5cdTAwMDbpV3FCiVlcYvtcblx1MDAwMrE56MYrgzjsW71//1xcXHUwMDFk2/Gfq//52etZ3ld/opix1Vx1MDAwZYcmpqYoi+cg03S/XHUwMDE4YpKd8s1cIiZcdTAwMDJcdTAwMDdcIjJcdTAwMWErXHUwMDE4qqxcdHRZo70hXHUwMDEw+K29XHUwMDEx7X2Ym5j4Tlx1MDAwNsJcdTAwMTIkJk34So3SlZop/8T3jT4sM1x1MDAxMSx8OuaTzlx1MDAwZkmu/5E0uGBxvCQ3J/BcdTAwMDNcdTAwMTDKOFKKIWdcdTAwMDBQgVxu4yXZXHTSXGIvwf5sMOlX2jGs7IhMhmJ+ZVx1MDAxMISk1kYq5lx1MDAwZVx0XHUwMDAxROjSMMP8UZDBbXXXdZtcblx0z71Dq/d4eHPswmWBoPRaK05FkFxuiWE4j3elwDBcYlx1MDAxMlx1MDAwNlx1MDAxMaO6VIAwwaEwuo7Yjeuw/PlcdTAwMThEXHT6bOD6XHUwMDFl4yCGllx1MDAwN7Ttr1dujFx1MDAwNLxcci3J359iSEl2cjkzWoJFVKDDznioTDcpefx3tCSFlDzOTUqQpERcYq71NJBMxFDGMC39+m1cdTAwMGXxhyUlJVx1MDAxMjmfoolcdTAwMTeEZNf/8DdcdJfkplx1MDAwNIqWKPLJJFx1MDAxN0D5iP6/SVpcImejJdmZ41xiLSFMMKKMXGYjilx1MDAwMyjzoaElQJNcInozZlx1MDAxMp5SXHUwMDFiXHUwMDE3eYKxXHUwMDFhQa6dhPaUn5nUt+3de690VJLiae3gyvP2XHUwMDE0t19cdTAwMTZcdTAwMWNKyc9ImMVMMGOxrvxqZuJP8FDU4DOVZn52YpJdnZZZNFx1MDAwMuLyzJPEXHUwMDA0XHUwMDAxTbQkSHDnICboSlqEfFx1MDAwZWJSXHUwMDA3YP6yXHUwMDExSVx1MDAxMWVcdTAwMTDrmFx0IakwTST0pzrSXHUwMDBmWzRcIlD49DwzXHUwMDFlQSRcXFLi7C2ISW5SoIiJUFaVXHUwMDAwKTBcdTAwMDOMUp6cJ1x1MDAwYmctXHUwMDFimYZcdTAwMWVBiIBcdTAwMDSC+cBNJcbJqbJ4kdQkz/yWTP9cbsTqNlHILI9hLORzjWEsNFxy8zeMRWFcZs5cdTAwMGZjgFxiSKRk2nx0hodFXHUwMDE4hVxcSvhhgaxcdTAwMDRF5IJcdTAwMTKZ7GOF5Hf0t5DBJYvDsmnirphcdTAwMTJMOZdcdTAwMDKq94eT+eDFp6RcdTAwMTWAIVx1MDAwMVx1MDAxOJSEXHUwMDBixn9BRvrx6uxk79Zzvv8wa+VcdTAwMWZb9NIqmznrd0Nm+znoqSvg1U3eXHUwMDE2QSnOb1xmi2JcdTAwMTiaXHUwMDFmw1x1MDAwNFx1MDAwMVx1MDAwMDFBp4xcdTAwMTIxJJW/XHUwMDFmLvz9YFx1MDAxMEZI+PRcdTAwMTJcdTAwMTGTLoAoyt5EqOZ3cfg1Te5cblxiKlx1MDAxMeFcdTAwMTBTQZBcdTAwMTBAQ8ZmQ7ApXG57gPKcXHRcdTAwMTNcYlxioPpcIihNUjGe6ETBINZcdTAwMWY+lXeQQN2LJ7dcdTAwMDO2XHUwMDA3l7v7W3YuXHUwMDEwXHUwMDEzPOZPXHUwMDAypMm+XHUwMDEzXHKIsWlcdTAwMDLdXHUwMDE2wMo5+iwghudcdTAwMDYxglx1MDAxOcWAscTSwb5JXHUwMDA06TyMXHUwMDAyXHUwMDAwlSX9uOn3UjT/XkJ04lx1MDAxNZBEYYwtV2mggjHGXHUwMDA0XGb/XHUwMDE0hWK5Z0Mof5JjKiFcdTAwMDNQubWYYJCMty/cm1xcq6CH3XvPXHUwMDE1W8292qaEXHJ4sXWfXHUwMDA0sWRtIIfK5eY0rTZQ6VFoSuB4XHUwMDExWWZcYpJZXHUwMDFjiKYpXHUwMDBl/FxcLI3oXHUwMDAxTltcdTAwMWTIqFx1MDAxYWOWnIg+gpbUNVmpwFC5XHUwMDA1obXTl6c4UFx1MDAxN1x1MDAxN17CXCLARYSvJy4khlNcdTAwMTe7p1x1MDAwMEpcdTAwMDS5plSmXHUwMDBlQlx1MDAwZdekjNRNw/F20PF+v2dtXHUwMDFmnuKbXff6VC6LPqUsXVxuUVx1MDAxNj6hkG5cdTAwMTRcdTAwMDUrM6Hcq1x1MDAwM4VcdTAwMTFgQIRcdTAwMTd2+fBcdKlfl3r6XHUwMDE1WopZalx1MDAwMadCaoG4xJpVQeqA5VfTrYrZZ0eiPrzvmY/SvVx1MDAwM8PH06Uxe2krXHUwMDBiQIOkTuyDgKfvTzGvmko+w8Q+TJWJVLr6ifLGKSXsb6OpXHUwMDBirZ+Hx62j+uHajn1QqXnfLrdcdTAwMWZuq3chdUsnv4xcIkOBu1x1MDAwNuJH01FlMq1cdTAwMDKxNIBvjZQjXHQ55Vx1MDAxYWGbal7M5/Lt+epkXHJ6NaRIvVx1MDAwZcQ41WVToEzNXG5cdTAwMGJcdTAwMDCQUM7YMk6M2Tk5OVJUXHUwMDBl/Oyph7y1nJWG2fuXt+L/sdRkOFe/XHUwMDE3zo5hXCImPY4+XHUwMDBiorwhLLR2V+a3u6S23T8/4ZWLaue2f7e3UV3fXHUwMDA1a8uic3q7S6lcdTAwMWZcdTAwMDFcdFx1MDAxNtNcdTAwMGJaXHUwMDFlrbNcdTAwMWLZoaLwii0mjFx0i+mFVvdcdTAwMWLrtWLyyptcdTAwMTFcdTAwMDVsUfGLV9pcdTAwMTWRo1x1MDAxOZZ3x35YaXsrdX/439rw6tsuxu5mb02VXHUwMDE1OWexpafCS92PK1x1MDAxOLgmcFx1MDAxZXprhVx1MDAxONc/rkafZVHyWVxyq6U3rFNcdTAwMDTNXHUwMDE1dHDFgoQu8SdT59JzgFx1MDAxOSRMXHUwMDE2nvdcdTAwMTOKj3E0zc5k48NcdTAwMDWXLuBI5lx1MDAwZuOJV4Tk1v/ANylcXJgmWk1cdTAwMTT+KmaFKfA3btKs3TNjxHyKXHJcdTAwMTMgXHUwMDE0o3SLJFx1MDAxOFEmZLJ2Qbd+0JtcdTAwMTWHI5Lu46tcdTAwMTFDklx1MDAxMG0o7io/11x1MDAxOO5v0ma7tH+yXm+Z22eHcv375pJvO0kgNiBcdTAwMTDBfj5RXGJcdTAwMTfpu5XM6uWMmVx1MDAwNsdcdTAwMDZXRptcdTAwMDBCiV/1XHUwMDE5XHUwMDEw44xd69RcdTAwMTNcdTAwMTHiO2nvPlx1MDAxNpd/Uf9cXFT9XHUwMDAzelxy2dvXpS9cdTAwMDZcdTAwMDNcdJZcboxcdTAwMTjWzPWog+v8+pxdebGU+sxCK6C+1GBl7FwiO7ezwFxyXHUwMDEw/mjKU5PTOzjBXHUwMDFjICne1z6y2/RxWL7gtSt+2uH7d9Zwu12y8y6+m71KVaT9qVx1MDAxNvVd1L5cdTAwMDJzrNOfed/s2sLM+yZoVpJdUlx1MDAwNlig8lx1MDAwYlqEXHUwMDE4h/Y7TKz1wLiyZUho1lx1MDAwMKyDVn7c0cvacuNcdTAwMGVcdTAwMTeGelx1MDAwYmm5XHUwMDAySFx1MDAxNohCmFx1MDAxOWzqZFx1MDAwMWFcdTAwMDDwyE7j75RH5E9cdTAwMTY8x+qrfrS++uh6VndW9jBhLeJcdGYzzikyuvU2TFwifUdcdTAwMGZlPZHgjOk9g3Z+jc525ZZToymP712IXHUwMDE2uIaFbmpLmLq8XHUwMDE2zzDkRydcbmD/b8hcdTAwMWSuj7rbNmjdXHUwMDFmndVcdTAwMGa+OyeNLbF+k5s7LGpcdTAwMGb67HW6Z79vdunt7PfNXHUwMDBlTGbeN1x1MDAwN3fwZWqayNRM3Fx1MDAwMfHUXHUwMDEwXHUwMDA0lFL4XHUwMDAxf6nlXHUwMDBlN/mRRi9ry400XHUwMDFjXHUwMDE4XGKkLWUo0eL2XHUwMDE1XHUwMDE0XG7islx1MDAxN0TULFx1MDAxZkzoaCPCT1RlMLLQVcu5XHUwMDBms4JCKcNcdTAwMDT7qKVcZvFcdTAwMGVcdTAwMTWT/8guU85iXHUwMDE0o9lcdTAwMDMsNo1cdTAwMTOEyEUwe4AkXHUwMDA17ffKm6mJkNtVrfbkMeDjqCFcdTAwMDdcdTAwMDQxKLTTXHUwMDA3gnVfk9NcdTAwMDcgXHUwMDE01J9cdTAwMTCYXHUwMDAzf1x1MDAwYlwiXHUwMDBi+31vUN68QzXyXGI7pWMgL0x29KuN+qJcdTAwMDJcdTAwMThzXHUwMDA0XHUwMDA0XHUwMDE2RUJykFx1MDAwNX/7yrnJQtbbTsBNssxJXGJkwNTNeCGAXHUwMDFh3IHRXXShZiuVqWr8P1x1MDAxN1xmdfJcdTAwMTc6KfNcZiREyWr+0XepNf7Q3/VCIdVSrlx1MDAwMDyu9Is76Vx1MDAwYixumsBcdTAwMWEm2Gp9oKGIMMOXXHUwMDE3fFg1+/2qp0Z6bI5W79vWw3p6TcKXXHUwMDE3IPB1wFx1MDAxYVmxf77883/UiETbIn0=<!-- payload-end -->
+ <defs>
+ <style class="style-fonts">
+ @font-face {
+ font-family: "Virgil";
+ src: url("https://excalidraw.com/Virgil.woff2");
+ }
+ @font-face {
+ font-family: "Cascadia";
+ src: url("https://excalidraw.com/Cascadia.woff2");
+ }
+ @font-face {
+ font-family: "Assistant";
+ src: url("https://excalidraw.com/Assistant-Regular.woff2");
+ }
+ </style>
+
+ </defs>
+ <rect x="0" y="0" width="803" height="667.5" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(10 97.5) rotate(0 58.5 50)"><path d="M25 0 C46.39 -1.6, 61.07 0.41, 92 0 C107.46 -2.04, 115.12 11.37, 117 25 C119.19 44.74, 117.63 63.9, 117 75 C113.82 91.25, 106.73 100.13, 92 100 C71.9 96.31, 57.33 98.53, 25 100 C9.2 100.92, -3.52 90.44, 0 75 C-2.66 67.34, -2.69 55.49, 0 25 C2.25 8.57, 8.32 0.13, 25 0" stroke="none" stroke-width="0" fill="#a5d8ff"></path><path d="M25 0 C49.61 0.38, 71.28 1.64, 92 0 M25 0 C41.8 -0.31, 60.62 -0.74, 92 0 M92 0 C108.04 0.85, 115.57 6.86, 117 25 M92 0 C107.65 -1.64, 117.98 9.12, 117 25 M117 25 C118.74 43.25, 118.32 56.76, 117 75 M117 25 C117.52 42.48, 115.93 58.09, 117 75 M117 75 C117.38 93.59, 106.81 101.66, 92 100 M117 75 C115.51 92.37, 106.41 98.44, 92 100 M92 100 C68.36 101.19, 44.39 99.78, 25 100 M92 100 C70.34 98.75, 48.03 99.86, 25 100 M25 100 C10.18 100.49, -1.18 93.11, 0 75 M25 100 C8.35 98.38, -1.34 91.25, 0 75 M0 75 C0.57 61.79, 1.81 48.22, 0 25 M0 75 C0.14 64.95, 1.29 54.82, 0 25 M0 25 C1.26 7.44, 8.18 -1.28, 25 0 M0 25 C0.53 6.28, 9.78 -1.35, 25 0" stroke="#1971c2" stroke-width="2" fill="none"></path></g><g transform="translate(38.141666412353516 122.5) rotate(0 30.358333587646484 25)"><text x="30.358333587646484" y="17.52" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#1971c2" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">User </text><text x="30.358333587646484" y="42.519999999999996" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#1971c2" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">laptop</text></g><g stroke-linecap="round" transform="translate(361 62.5) rotate(0 216 297.5)"><path d="M32 0 C128.62 -2.09, 225.56 1.05, 400 0 C424.06 -0.58, 434.67 13, 432 32 C431.55 205.11, 432.05 378.6, 432 563 C431.29 584.43, 417.85 593.68, 400 595 C315.9 595.22, 228.53 593.9, 32 595 C7.63 596.28, -2.87 581.99, 0 563 C3.42 357.86, 2.51 152.58, 0 32 C2.4 13.05, 7.62 -2.76, 32 0" stroke="none" stroke-width="0" fill="#e9ecef"></path><path d="M32 0 C146.2 -1.42, 261.19 -2.64, 400 0 M32 0 C127.99 2.13, 223.92 1.41, 400 0 M400 0 C420.45 -1.43, 432.85 11.35, 432 32 M400 0 C422.19 0.32, 432.8 12.58, 432 32 M432 32 C433.61 227.44, 432.6 425.02, 432 563 M432 32 C430.72 229.98, 430.27 427.52, 432 563 M432 563 C430.7 584.95, 419.37 593.64, 400 595 M432 563 C433.35 582.46, 421.35 595.45, 400 595 M400 595 C268.27 594.26, 134.85 595.41, 32 595 M400 595 C318.03 595.96, 234.55 596.25, 32 595 M32 595 C10.68 593.59, -1.17 583.97, 0 563 M32 595 C10.3 595.14, 2.05 585.02, 0 563 M0 563 C-2.75 376.71, -1.99 191.6, 0 32 M0 563 C-1.53 402.97, -1.81 243.04, 0 32 M0 32 C0.46 8.88, 11.92 -1.18, 32 0 M0 32 C-0.77 11.43, 11.28 2.26, 32 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(527.1333351135254 71.5) rotate(0 51.86666488647461 12.5)"><text x="51.86666488647461" y="17.52" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">cmd/xesite</text></g><g stroke-linecap="round"><g transform="translate(129 141.5) rotate(0 134.5 -25.5)"><path d="M0.45 0.17 C13.93 -8.23, 36.52 -48.51, 81.42 -50 C126.32 -51.49, 238.76 -15.6, 269.83 -8.79 M-0.78 -0.79 C12.54 -9.55, 35.65 -49.94, 80.69 -51.6 C125.74 -53.26, 238.38 -18.04, 269.5 -10.73" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(129 141.5) rotate(0 134.5 -25.5)"><path d="M244.6 -8.57 C253.4 -8.71, 263.32 -8.76, 269.5 -10.73 M244.6 -8.57 C252.78 -10.36, 263.62 -9.51, 269.5 -10.73" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(129 141.5) rotate(0 134.5 -25.5)"><path d="M249.03 -25.09 C256.38 -19.55, 264.78 -13.94, 269.5 -10.73 M249.03 -25.09 C255.45 -20.87, 264.68 -14.03, 269.5 -10.73" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(156.1500015258789 62.5) rotate(0 68.8499984741211 12.5)"><text x="68.8499984741211" y="17.52" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">GET /blog.rss</text></g><g stroke-linecap="round" transform="translate(650 458.5) rotate(0 41 19.5)"><path d="M9.75 0 C31.68 -1.84, 57.8 -0.54, 72.25 0 M9.75 0 C33.56 -0.02, 58.48 0.5, 72.25 0 M72.25 0 C77.05 -0.71, 83.95 5.03, 82 9.75 M72.25 0 C80.03 -0.4, 82.06 4.26, 82 9.75 M82 9.75 C83.76 12.92, 83.43 16.87, 82 29.25 M82 9.75 C81.68 17.09, 82.46 22.02, 82 29.25 M82 29.25 C81.33 36.74, 80.26 39.92, 72.25 39 M82 29.25 C83.01 35.47, 77.06 38.94, 72.25 39 M72.25 39 C53.36 40.33, 32.55 37.74, 9.75 39 M72.25 39 C52.92 39.55, 33.34 39.45, 9.75 39 M9.75 39 C1.69 37.21, -1.87 37.12, 0 29.25 M9.75 39 C1.2 37.32, -0.1 36.12, 0 29.25 M0 29.25 C1.16 21.6, -1.83 15.07, 0 9.75 M0 29.25 C-0.57 24.17, -0.09 17.48, 0 9.75 M0 9.75 C-1.34 4.88, 3.02 -0.06, 9.75 0 M0 9.75 C0.5 2.66, 2.45 -1.47, 9.75 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(663.2666664123535 468) rotate(0 27.733333587646484 10)"><text x="27.733333587646484" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">lume.FS</text></g><g stroke-linecap="round" transform="translate(435 568) rotate(0 50 18)"><path d="M9 0 C39.89 0.94, 71.06 1.59, 91 0 M9 0 C29.14 0.57, 51.07 0.14, 91 0 M91 0 C97.95 -0.7, 101.36 1.79, 100 9 M91 0 C96.22 1.18, 98.96 4.19, 100 9 M100 9 C100.18 15.14, 100.35 22.07, 100 27 M100 9 C99.82 12.75, 100.68 17.05, 100 27 M100 27 C99.51 33.25, 98.15 37.71, 91 36 M100 27 C98.81 32.91, 97.52 35.93, 91 36 M91 36 C70.96 36.38, 47.75 36.68, 9 36 M91 36 C61.78 36.41, 32.6 36.55, 9 36 M9 36 C4.64 35.56, 1.69 33.98, 0 27 M9 36 C3.4 38.04, -2.25 31.03, 0 27 M0 27 C-1 23.14, 0.03 15.96, 0 9 M0 27 C0.67 20.53, -0.17 15.29, 0 9 M0 9 C0.85 2.99, 4.31 0.01, 9 0 M0 9 C-0.88 1.87, 2.56 -0.01, 9 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(443.68333435058594 576) rotate(0 41.31666564941406 10)"><text x="41.31666564941406" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">archive/zip</text></g><g stroke-linecap="round"><g transform="translate(519.5 126.5) rotate(0 54.5 35)"><path d="M1.01 -0.78 C11.25 3.23, 42.66 11.31, 60.48 22.97 C78.3 34.62, 99.92 61.17, 107.93 69.16 M0.07 1.43 C10.3 5.65, 41.42 12.53, 59.79 23.96 C78.15 35.39, 102.14 62.57, 110.27 70.03" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(519.5 126.5) rotate(0 54.5 35)"><path d="M87.64 59.4 C91.13 62.3, 95.57 62.02, 110.27 70.03 M87.64 59.4 C92.65 62.62, 97.92 63.83, 110.27 70.03" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(519.5 126.5) rotate(0 54.5 35)"><path d="M99.77 47.34 C100.53 52.95, 102.37 55.26, 110.27 70.03 M99.77 47.34 C101.94 53.42, 104.42 57.4, 110.27 70.03" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(590.4416656494141 130.5) rotate(0 55.05833435058594 10)"><text x="55.05833435058594" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">GET /blog.rss</text></g><g stroke-linecap="round"><g transform="translate(668.5 235.5) rotate(0 -45.5 54)"><path d="M-0.96 0.66 C-4.3 10.76, -4.43 43.05, -19.57 60.95 C-34.7 78.84, -80.01 100.27, -91.75 108.04 M0.73 -0.03 C-2.85 9.71, -5.81 41.08, -20.81 59.32 C-35.81 77.56, -77.84 101.19, -89.26 109.38" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(668.5 235.5) rotate(0 -45.5 54)"><path d="M-74.17 89.45 C-78.11 95.13, -82.75 101.57, -89.26 109.38 M-74.17 89.45 C-78.78 95.49, -83.81 101.49, -89.26 109.38" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(668.5 235.5) rotate(0 -45.5 54)"><path d="M-64.89 103.81 C-72.01 104.56, -79.8 106.13, -89.26 109.38 M-64.89 103.81 C-72.42 105.46, -80.28 107.1, -89.26 109.38" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(658.4500007629395 285.5) rotate(0 62.04999923706055 20)"><text x="62.04999923706055" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Open("/blog.rss")</text><text x="62.04999923706055" y="34.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">net/http.File</text></g><g stroke-linecap="round"><g transform="translate(574.5 362.5) rotate(0 60.5 47.5)"><path d="M-1.17 -1.15 C13.22 5.27, 65.93 21.96, 86.42 38 C106.91 54.05, 115.91 85.55, 121.77 95.12 M0.41 0.86 C14.67 7.02, 65.52 20.46, 85.69 36.4 C105.86 52.34, 115.34 86.44, 121.41 96.5" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(574.5 362.5) rotate(0 60.5 47.5)"><path d="M103.87 78.69 C107.26 85.02, 116.22 91.07, 121.41 96.5 M103.87 78.69 C108.42 84.54, 114.41 89.8, 121.41 96.5" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(574.5 362.5) rotate(0 60.5 47.5)"><path d="M119.43 71.58 C118.01 79.94, 122.2 88.17, 121.41 96.5 M119.43 71.58 C119.18 79.69, 120.35 87.15, 121.41 96.5" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(650.2583312988281 365.5) rotate(0 64.24166870117188 20)"><text x="64.24166870117188" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">.Open("/blog.rss")</text><text x="64.24166870117188" y="34.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">io/fs.File</text></g><g stroke-linecap="round"><g transform="translate(682.5 506.5) rotate(0 -68.5 39)"><path d="M0.05 -0.85 C-6.71 7.68, -16.77 38.79, -39.42 51.75 C-62.06 64.7, -119.68 72.68, -135.81 76.89 M-1.38 1.32 C-8.35 9.98, -17.63 40.44, -40.06 53.16 C-62.49 65.87, -120.04 73.56, -135.95 77.62" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(682.5 506.5) rotate(0 -68.5 39)"><path d="M-114.57 64.65 C-124.38 70.76, -131.84 76.9, -135.95 77.62 M-114.57 64.65 C-119.19 66.96, -122.52 70.47, -135.95 77.62" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(682.5 506.5) rotate(0 -68.5 39)"><path d="M-111.24 81.42 C-122.44 80.9, -131.22 80.41, -135.95 77.62 M-111.24 81.42 C-116.67 80.23, -120.68 80.26, -135.95 77.62" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(636.2583312988281 559.5) rotate(0 64.24166870117188 20)"><text x="64.24166870117188" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">.Open("/blog.rss")</text><text x="64.24166870117188" y="34.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">io/fs.File</text></g><g stroke-linecap="round"><g transform="translate(445.5 566.5) rotate(0 100.5 -38)"><path d="M1.01 0.03 C14.59 -8.49, 49.23 -37.57, 82.54 -50.1 C115.86 -62.64, 181.11 -71.06, 200.91 -75.2 M0.09 -1 C13.46 -9.33, 48.55 -39.07, 81.88 -51.76 C115.22 -64.44, 180.11 -72.93, 200.1 -77.13" stroke="#2f9e44" stroke-width="2" fill="none"></path></g><g transform="translate(445.5 566.5) rotate(0 100.5 -38)"><path d="M178.45 -64.64 C186.85 -68.79, 196.76 -74.73, 200.1 -77.13 M178.45 -64.64 C186.47 -68.49, 195.18 -73.47, 200.1 -77.13" stroke="#2f9e44" stroke-width="2" fill="none"></path></g><g transform="translate(445.5 566.5) rotate(0 100.5 -38)"><path d="M175.49 -81.48 C185.2 -79.08, 196.26 -78.43, 200.1 -77.13 M175.49 -81.48 C184.65 -79.18, 194.45 -77.99, 200.1 -77.13" stroke="#2f9e44" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(653.5 459.5) rotate(0 -106.5 -44.5)"><path d="M0.2 0.43 C-29.73 -6.32, -144.58 -26.66, -180.2 -41.54 C-215.82 -56.42, -208.07 -81, -213.52 -88.85 M-1.16 -0.39 C-31.21 -7.41, -145.69 -28.9, -181.26 -43.41 C-216.82 -57.93, -209.33 -80.13, -214.56 -87.46" stroke="#2f9e44" stroke-width="2" fill="none"></path></g><g transform="translate(653.5 459.5) rotate(0 -106.5 -44.5)"><path d="M-200.04 -67.11 C-202.77 -72.5, -206.34 -78.11, -214.56 -87.46 M-200.04 -67.11 C-205.02 -73.48, -208.37 -79.57, -214.56 -87.46" stroke="#2f9e44" stroke-width="2" fill="none"></path></g><g transform="translate(653.5 459.5) rotate(0 -106.5 -44.5)"><path d="M-216.52 -62.53 C-215.09 -69.1, -214.55 -75.85, -214.56 -87.46 M-216.52 -62.53 C-216.35 -70.38, -214.56 -77.9, -214.56 -87.46" stroke="#2f9e44" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(501.5 326.5) rotate(0 61 -42)"><path d="M0.61 -1.09 C8.28 -9.32, 24.8 -35.15, 44.84 -48.9 C64.89 -62.66, 108.22 -77.7, 120.88 -83.62 M-0.53 0.95 C7.16 -7.2, 23.72 -33.39, 44.34 -47.84 C64.96 -62.29, 110.5 -79.81, 123.19 -85.77" stroke="#2f9e44" stroke-width="2" fill="none"></path></g><g transform="translate(501.5 326.5) rotate(0 61 -42)"><path d="M105.01 -68.6 C106.78 -70.74, 110.75 -77.47, 123.19 -85.77 M105.01 -68.6 C110.74 -74, 116.93 -79.95, 123.19 -85.77" stroke="#2f9e44" stroke-width="2" fill="none"></path></g><g transform="translate(501.5 326.5) rotate(0 61 -42)"><path d="M98.23 -84.3 C101.42 -83.32, 106.76 -86.89, 123.19 -85.77 M98.23 -84.3 C106.05 -84.47, 114.49 -85.22, 123.19 -85.77" stroke="#2f9e44" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(615.5 222.5) rotate(0 -71 -34)"><path d="M-0.17 -1 C-14.62 -5.1, -63.55 -12.92, -87.17 -24.17 C-110.8 -35.42, -132.89 -61.36, -141.91 -68.49 M-1.71 1.1 C-15.77 -3.38, -61.59 -14.44, -85.08 -25.86 C-108.56 -37.28, -133.36 -60.24, -142.63 -67.44" stroke="#e03131" stroke-width="2" fill="none"></path></g><g transform="translate(615.5 222.5) rotate(0 -71 -34)"><path d="M-119.08 -59.05 C-126.93 -63.23, -130.05 -63.32, -142.63 -67.44 M-119.08 -59.05 C-125.55 -61.69, -131.53 -62.71, -142.63 -67.44" stroke="#e03131" stroke-width="2" fill="none"></path></g><g transform="translate(615.5 222.5) rotate(0 -71 -34)"><path d="M-129.98 -45.87 C-135.03 -53.49, -135.3 -57.02, -142.63 -67.44 M-129.98 -45.87 C-133.71 -52.01, -136.87 -56.45, -142.63 -67.44" stroke="#e03131" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(456.07500076293945 500) rotate(0 33.42499923706055 10)"><text x="33.42499923706055" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#2f9e44" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">io/fs.File</text></g><g transform="translate(457.07500076293945 436.5) rotate(0 33.42499923706055 10)"><text x="33.42499923706055" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#2f9e44" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">io/fs.File</text></g><g transform="translate(435.94166564941406 267.5) rotate(0 48.55833435058594 10)"><text x="48.55833435058594" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#2f9e44" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">net/http.File</text></g><g transform="translate(396.9749984741211 189.5) rotate(0 69.5250015258789 20)"><text x="69.5250015258789" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#e03131" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">HTTP 500</text><text x="69.5250015258789" y="34.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#e03131" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">seeker can't seek</text></g><g transform="translate(295.16666412353516 10) rotate(0 84.33333587646484 17.5)"><text x="84.33333587646484" y="24.528" font-family="Virgil, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">How it broke</text></g><g stroke-linecap="round"><g transform="translate(403.5 141.5) rotate(0 -136 16.5)"><path d="M-1.2 1 C-23.82 6.52, -89.5 30.96, -134.82 33.78 C-180.14 36.59, -250.23 20.47, -273.13 17.9 M0.37 0.48 C-21.95 5.6, -87.34 29.04, -132.54 32.06 C-177.74 35.09, -247.56 20.8, -270.83 18.64" stroke="#e03131" stroke-width="2" fill="none"></path></g><g transform="translate(403.5 141.5) rotate(0 -136 16.5)"><path d="M-246.38 13.43 C-253.85 13.76, -263.38 15.2, -270.83 18.64 M-246.38 13.43 C-252.33 14.28, -256.75 16.45, -270.83 18.64" stroke="#e03131" stroke-width="2" fill="none"></path></g><g transform="translate(403.5 141.5) rotate(0 -136 16.5)"><path d="M-248.75 30.36 C-255.43 24.38, -264.07 19.47, -270.83 18.64 M-248.75 30.36 C-254.17 27.7, -258.1 26.35, -270.83 18.64" stroke="#e03131" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(157.60832977294922 181.5) rotate(0 86.89167022705078 25)"><text x="86.89167022705078" y="17.52" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#e03131" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">HTTP 500</text><text x="86.89167022705078" y="42.519999999999996" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#e03131" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">seeker can't seek</text></g><g stroke-linecap="round" transform="translate(407.5 327.5) rotate(0 83.5 20)"><path d="M10 0 C66.53 1.22, 123.7 -1.83, 157 0 M10 0 C61.31 -0.5, 110.82 -2.08, 157 0 M157 0 C163.24 0.72, 166.39 5, 167 10 M157 0 C163.61 1.84, 167.88 1.46, 167 10 M167 10 C166.61 17.44, 167.96 22.98, 167 30 M167 10 C167.02 17.06, 167.57 24.29, 167 30 M167 30 C167.96 35.39, 162.4 40.79, 157 40 M167 30 C168.15 36.3, 165.24 38.2, 157 40 M157 40 C126.17 40.32, 94.85 39.81, 10 40 M157 40 C118.74 41.76, 79.4 40.9, 10 40 M10 40 C2.35 40.52, 1.42 38.62, 0 30 M10 40 C2.59 39.81, -0.23 36.82, 0 30 M0 30 C-1.78 24.52, 1.8 19.72, 0 10 M0 30 C0.68 23.2, -0.16 17.5, 0 10 M0 10 C1.67 4.63, 2.88 -0.83, 10 0 M0 10 C1.96 2.79, 5.42 -1.25, 10 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(422.69166564941406 337.5) rotate(0 68.30833435058594 10)"><text x="68.30833435058594" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">http.FSFileSystem</text></g><g stroke-linecap="round" transform="translate(402 115.5) rotate(0 56.5 17)"><path d="M8.5 0 C38.7 1.75, 68.81 0.1, 104.5 0 M8.5 0 C40.93 -0.01, 74.67 1.05, 104.5 0 M104.5 0 C110.91 0.28, 113.7 4.5, 113 8.5 M104.5 0 C111.76 1.44, 110.75 3.64, 113 8.5 M113 8.5 C114.07 11.04, 112.12 16.09, 113 25.5 M113 8.5 C112.29 15.5, 112.01 21.4, 113 25.5 M113 25.5 C114.17 29.53, 110.18 34.39, 104.5 34 M113 25.5 C114.36 31.68, 109.9 34.72, 104.5 34 M104.5 34 C77.93 35.39, 55.1 36.36, 8.5 34 M104.5 34 C73.34 33.99, 41.58 34.51, 8.5 34 M8.5 34 C2.51 34.12, 1.78 31.77, 0 25.5 M8.5 34 C3.97 36.12, 1.86 28.89, 0 25.5 M0 25.5 C0.03 23.35, -0.1 19.42, 0 8.5 M0 25.5 C0.21 20.4, 0.55 16.31, 0 8.5 M0 8.5 C-0.67 3.5, 3.37 1.96, 8.5 0 M0 8.5 C-0.81 3.06, 3.3 -0.77, 8.5 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(414.70000076293945 122.5) rotate(0 43.79999923706055 10)"><text x="43.79999923706055" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">http.Server</text></g><g stroke-linecap="round" transform="translate(613.5 195.5) rotate(0 72 20)"><path d="M10 0 C60.2 -0.28, 108.75 -1.64, 134 0 M10 0 C45.54 -0.94, 80.73 -1.01, 134 0 M134 0 C139.16 1.18, 145.54 4.55, 144 10 M134 0 C139.69 -2.15, 144.68 4.12, 144 10 M144 10 C143.6 15.52, 142.99 18.69, 144 30 M144 10 C144.94 14.83, 143.94 17.85, 144 30 M144 30 C144.73 36.74, 141.31 41.73, 134 40 M144 30 C143.01 37.5, 140.41 38.59, 134 40 M134 40 C98.37 40.73, 64.17 39.47, 10 40 M134 40 C101.22 39.73, 69.67 39.21, 10 40 M10 40 C1.61 39.77, -1.86 37.16, 0 30 M10 40 C1.75 37.79, 1.04 37.69, 0 30 M0 30 C-1.72 23.21, -0.31 17.5, 0 10 M0 30 C0.74 23.91, -0.97 16.78, 0 10 M0 10 C-1.15 2.85, 3.52 1.36, 10 0 M0 10 C0.71 2.43, 3.66 -0.24, 10 0" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(626.6500015258789 205.5) rotate(0 58.849998474121094 10)"><text x="58.849998474121094" y="14.016" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">http.FileSystem</text></g></svg> \ No newline at end of file
diff --git a/lume/src/static/blog/fixing-rss-mailcap/how-it-should-work.excalidraw.svg b/lume/src/static/blog/fixing-rss-mailcap/how-it-should-work.excalidraw.svg
new file mode 100644
index 0000000..12b6d3a
--- /dev/null
+++ b/lume/src/static/blog/fixing-rss-mailcap/how-it-should-work.excalidraw.svg
@@ -0,0 +1,21 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 803 665.5" width="1606" height="1331">
+ <!-- svg-source:excalidraw -->
+ <!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO2cWXPayFx1MDAxNoDf8ytcXMzLvVWD0vuSN7zbie3EK/HNlEtcdTAwMDZcdTAwMTlkhISFMMZT+e+3XHUwMDFi20hCLVx1MDAxMIuXJGaqJkZ0i0P3Wb4+p1v/flhZKUWDjlP6tFJy7mq259ZDu1/6W1+/dcKuXHUwMDFi+OojNHzfXHJ6YW3Yslx1MDAxOUWd7qePXHUwMDFm41x1MDAxZVYtaD/0cjyn7fhRV7X7n3q/svLv8P/qXHUwMDEzt6770nZcclWJXHUwMDAwJ0H120Xt8KRP7+97w67DRk/ChE4tsv2G58RcdTAwMWbdaUkoXHUwMDFkvVx1MDAxZqj3XHUwMDEw8tH7vluPmsNrzJKp16hJ03FcdTAwMWLNSLdcdTAwMDFgdPHhaz6txFe6UVx1MDAxOLSctcBcdTAwMGJCLctfUHJYQ7Ekl3at1Vxig55fj9vYtC6uruI2V67nXHUwMDFkRYPhndXQqWEqjd3/7FFeNHY9r5f6wkbTd7p6aOHoatCxa240XHUwMDE4+01aus5OfThcdTAwMGL/xDKFdtvZ0dPg9zxvdNn1645cdTAwMWXcklxyUt/m11x1MDAxZr/taVxu4/nBj1d+xrI7jr4xZEJcYk45j1x1MDAwNz3WI4zp+NX9wFx1MDAxZupcdTAwMTTklHJARGKy3O66UqZoeNsr2+s68fhr2TbGXHUwMDE1LalsKV2KnLto9MOSqlx1MDAxOJ66XHUwMDE3e/1W99tpVLFcdTAwMDdcdTAwMTd7m9dfnNKo3c+/zbd96DzYqN5EJ8FncNDZuPFqm5/ZqkTpb3n6fjtcZoN+0ft6+OyaXZcv1m/u+NqA+ts3wWlU7L6Pf8Xz3evU7Yfxg1x1MDAxY0pIOVx1MDAwNlx1MDAwNIt4hD3Xb40rg1x1MDAxN9Ra8ZB/SFxiPG7IxtHLXHUwMDE4cmrwXHUwMDFmbFhgXHUwMDBiXHUwMDEyyFx1MDAxOCNcdTAwMTBhiscsmqCMRTNgcd2eKy1BXHUwMDEySZ41aPpuz1x1MDAwNnuGZntOtX4yXFyiRpchXHUwMDA2Miaqf1x1MDAxMid5hktcdTAwMTmXXHUwMDA0XHUwMDExxuew25RcdTAwMWNcdTAwMTllXHUwMDA16l/OZ1DWWPe0zqnff9J1wpVcdTAwMWa+Z3eioJOYysCPjtx7LT1cdTAwMDKpq5t22/VcdTAwMDap+dD3qnhuQ1x1MDAwZkOpplx1MDAwNHfCUnIsXCJXxcBRg7ZbrydjVk3d1HZ9J9wpXHUwMDEy/ILQbbi+7Vx1MDAxZCflXHUwMDFml97uRcGh032QP1xue05yhJztUYSzXHUwMDEwnWC97fJcdKls8a3m1/tbsXtTrnknjS+FwzBcdTAwMDMsZbRcImuzXHUwMDA0x9diK5Wxdlx1MDAxNTBTR/832UxcdTAwMWTp1Jxf3UzR4mFcdTAwMTdcdTAwMTBGOeFcdNeYsF6B86yXYNVcdTAwMDWyeFZmXGK6XHUwMDEz4lxm4FBAnFTM+eNcZm5vXHUwMDFjV9fWqpeX57jlXHUwMDFj3Ja979/OisRcdTAwMTnOkVx1MDAwNbF6UVxiMUWUpFRWwozKQoAtrtqrXHUwMDAww5EkXHUwMDEyXHUwMDE5NFx1MDAxOL0rsEGBcfE4g4BAQkBATYBIWJ6iXCKosJ6SZHhaWpxR4YuiXHUwMDE5lDVcdTAwMTNnau36xzvlkiPnRYJMKlx1MDAxY6QjTErq8XBiXHUwMDEycznRxDs5isqsXHUwMDE1fb2+6G3eN53NnW6/XzyakNhrXHLHJYGEI9vEsWrE4SQ26aVcdTAwMThjXHUwMDE02n63Y4dqXHUwMDAyfnGDJFx1MDAwYkdcdTAwMTTMXHUwMDE1p1x1MDAxMMXppoCCMsY7WsepXHUwMDA1IFx1MDAxMlxi87jfs6/jnFx1MDAwM1k7P1x1MDAxZlx1MDAxYzhcdTAwMTFa2ztcdTAwMDe9bW/nvPna6zhaXHUwMDE5+Fx1MDAxNVpvbN1/aVx1MDAxZfm972dcdTAwMTKzvSXcd93ud/ZcdTAwMWFcdTAwMDfHq/vnh194uFx1MDAxYl34sreE+/4y607zbFx1MDAxN+BcdTAwMDGmlpFcYlx1MDAwZoFAcEbY+LpTWlx1MDAwNrdcdTAwMDPUVd1F6TRRWFx1MDAwM2KoeTYk+H28XHUwMDEwLY5cdTAwMDWUUsRcdTAwMTXCmqhA5ntcdTAwMWJBXHUwMDAxgFxiz1x1MDAwNbBTqEAyXHUwMDA0ZkHYXGZcdTAwMTXoLKl15IS3yWD+emvPKTF6XHUwMDFjXHUwMDE2jNIvh1x1MDAxNlx1MDAwZZ022+t2No5cdTAwMGW2vd1cdTAwMDN6Sn1bhsVpgafXnlhcdTAwMWFSwMCQ82XvtJBjp2zx9SdV4VxygGx+tzQxeVx1MDAwNFx1MDAxOZZcdTAwMTRJIF+QXHUwMDE2vq9cdTAwMGZu3IN+uyztbu+8f3gqL85vXzuqr/lnoN1qbZ/5XHUwMDFkp2HvfblxjuHGXHUwMDEy7tus9q9qwN/p9k73XHUwMDAzeSCYs1ptvS6FTKdcdTAwMDWCgULP5dCCebaL0IKkltBJZ8qITHGwNjpcdTAwMDKZgVx1MDAxNpi0sOrBXHUwMDA0XHUwMDA3UP1cdTAwMTYh3mGhuFx1MDAxM+IzwFx1MDAwMlx1MDAxN4JCSUywgGh+sotTrJxccp2nxDRcdTAwMTlcdTAwMTZm1thcZix4vbZjbVx1MDAxZb1cdTAwMDVQmFx1MDAxMp7HQSEj+XIg4Wb/mtFcdTAwMDOIXHUwMDA3p6uudy2r55vfXHQoXGZcdGKsTkxcdTAwMTOTXHUwMDFlp1x1MDAxNEx1pHhQ3+0zZZ9iYUhAQGJcYoQgRkpAuXZcdTAwMGKpoGrxlSxcdTAwMWU8OyWcXe6RY2FcdTAwMWbAb7J/Ulx1MDAwMZtcdTAwMTe73WphSniD0bxI1JUw4WlcdTAwMTaKuubRK1x1MDAxMHVcdTAwMDWHltC14YdSL05cdTAwMWIxz5aZdM5cdTAwMWUnwjQwpFx032Nunk3LXHUwMDE56sOYSKyW29KUXHUwMDEwhFxm5Fx1MDAxOS9cdTAwMDI6JVxiXHUwMDA1Wn6BeGaNzURdO6w13Vvn4737JsrDU2LeeOQ1Sr+c6Ds5KzrmZVJcdTAwMTaMebrOXHUwMDA2WbbQhphheU6RXHUwMDA1kq/Y9t+NNmW0laKBXHUwMDE45Vx1MDAwN2KFwlBSalxuxCRr4aNAjDCnVHBcdTAwMWPPzXLqxZAjJOfi507gjsf5+K+VWGWGb0Z///O3sbWAyeZlXG6ndUgosn7BtFx1MDAwNiNB4lx1MDAxYmRcdTAwMDKwZ3ejtaDddiM1XHUwMDE0X/XPyHjeyFx1MDAwZaNVNfGu30hP8OMmy1wim0qGrqvW00NcdTAwMDTU6lRSIbBcdTAwMTSYSyhoPI9aXHUwMDFi7Y5RZ1x1MDAxY78+XYbJycWEXGZlYFx1MDAxMUw4QUhcdTAwMDVcdTAwMDaqpJAoI1x1MDAwM8nIMFx1MDAxY4mKdjZNx86YhpIw+VmSfczerXx3XHUwMDA2vd5ccq03aFvsX3tcdTAwMTVaXHUwMDA1rFxinlx1MDAxMFx1MDAwMC1I1dRCipRcdTAwMWQkSlx1MDAxYdq2uXGNYTG9XHUwMDA1lUlcIlx1MDAxMHmJXHUwMDFkXHUwMDA1v4+jW5tl91x1MDAxYVx1MDAwMEzZXHUwMDFiNKVcdTAwMDRY/q5TgChcdTAwMDaMkOXXXHUwMDBmoFDgM0vJK1x1MDAwMydbXHUwMDFixytcdTAwMWYvvaBhhep3v1x1MDAwNJ7Mu7EgR9LloMjklOskXHUwMDE04YldXHUwMDFkw2GRhlx1MDAwMp8hXHUwMDA3oDzTu0maTXJ9YfbAPDdzXHUwMDA3cnf/KDuVQjlR+EypO5rUzFdBj1hcdTAwMGb1S8rZ2iuNfVx00pgtyqvYhyiRXHUwMDAwSlx1MDAwNrhItHqI8mw+0picnUzRXHUwMDBlV55dY4bARDCEs1wiwIxcYktcdTAwMDaNekDFNa52XHUwMDBm92F4f713Vqeb1a/F9i5cdTAwMTKLUTHad5DyY8lU2ciPMWAx1Vx1MDAxZVx1MDAxM0xcdTAwMDFcdTAwMTU0QdNz7pH/k9zaxlxmpKFcdTAwMTRJoVx1MDAxZs1ChfpQ5lc6JSaMS/pcZjtcdTAwMTVcdTAwMTBT6r1Q8UExgPfDt1x1MDAwZTqO/59cdTAwMWalUST/Ufrvm8aOXCJiL4dBJid0JzKIIFx1MDAxNmXKXHRcdTAwMDLJpYAoTSSEmTKawqJYQECUYlx1MDAwMzWzhoymjK+9W3LKkjdcdTAwMTdcdTAwMDZcdTAwMTTIXHUwMDExXHUwMDA0THLjzkeRiyhYrauRssW3lOZcXCqhMKFiOlBcdTAwMThcdTAwMDZ0SOXJiK5cdTAwMDBETFx1MDAwNZZcXLXWL8ni/s/HLzOwXHUwMDAzXHUwMDAyXHUwMDAwXHUwMDAzwlxiXHUwMDE1RKJEMnJcdTAwMDI7XHUwMDE0wpfJKd40QkHOOGSIIaBAStHAi1x1MDAwMoyZTVx1MDAxMin/7FGTeFdcdTAwMWWQjMqULYxcZnSrVMBAXHUwMDFly139rcPd08+1oG+H5dU9fy9YrbO34p+yfndYv1wiPJ/bSGJduSwnXHUwMDFk81x1MDAxZkzzn/GMpIWh3phcdTAwMDKwwFxc0NiXPeWFXHUwMDExXHUwMDExXHUwMDEwJ5dDM3nhXFx0miVcdTAwMTWMsOR8LppJXHUwMDExilx1MDAwNVx1MDAxMSFMXHUwMDEwSDGFXHUwMDA0p1x1MDAxYeVcdTAwMDBLUaT43eBmclV5XHUwMDEy3FxipVHJhHd6j5TyXHUwMDAwXHUwMDE2xIQonZJcdTAwMTJIYjqpjy2lhmqxXCKGfi5xaCA+qY946i5sXHUwMDE29EFX0iHkXHUwMDBmQZ/txdGHMaTWKchIPrlVIYmllJizeYpCv1x1MDAwNPmUuUir+ViZiIwp6NT75ev9w8dcdTAwMTmVf1x0OJqFTFx1MDAwNEBcdTAwMTJiqbhEXHUwMDA1PCaydETno6NcdTAwMTlcdTAwMDBNqVxioUytxok+rylcclx0pmcvI234a+1ypVx1MDAxNl1cdTAwMGZWXHUwMDA3iG2Vry4ujlxulZGY8oxoqEpcXFx1MDAxYpxcdTAwMWPfq1x1MDAxNqv8k6dcdTAwMTTYorqMpIabQFx1MDAwNFxyfnKmMtJcdTAwMWblXHUwMDE3d4ond1xih1DS5LmPxMNLck+hXHUwMDEwIaimruU7QES5IFx1MDAwYj1cdTAwMDLBXHI+XnWtTdd720dTTWIuh24m71SfmLqB1GJcZittIFx1MDAwNOPkk2lcdTAwMWWOncQgMuJcdTAwMTmR6iB4bJOJ4tIsWdg/ylB3XHUwMDE3XHUwMDA2XHUwMDE4xohcdTAwMGVcdTAwMDbC+Fx1MDAxNFx1MDAwNJi7wVQwrJzws1WXWFJxX4dg8jVz+LGczixk4lxylFa/XHUwMDA0o1x1MDAxNOZcdTAwMDOdPcGCXHTB1PirlSCSNJFvWiyFM0tcdTAwMTVcZujiXCJmXG5jOYWMK2+ekYI/XHUwMDFmpkzN4fD8rV6K71TwXHUwMDAxiUeHxIb6uXhcdTAwMGWnUt3qnpaPrlx1MDAxZFLd73xvtZzo81bjrfgpc1x1MDAwZYdcdTAwMDE5gc6QQImTP8vy13NxXrytXrk9xl43baPWjYnzTvOmbYrQSFx1MDAxZS/86qQy+Vx1MDAwNP4kUsk8QMPwcFx1MDAxYsRcckfXXHUwMDEzXHUwMDFiZN5ZJOXivizMXCJQXHUwMDAxhZpcYkFMi4nkcyvHN8xjqlx1MDAwZryA5cNcYlx1MDAwNlxmwdffZVuGJNWBoqk9XHUwMDEyyqtfkMY9nlx1MDAwZjZmivO6UINcdTAwMDXW+Vx1MDAxY4lcdTAwMDFN0NFiXHUwMDFia2fZ3IuJWoQyQiBQwVvgLPBcdTAwMTh0dblcdTAwMTmR2/5RtH5UaZY32KBcdTAwMWbd7X+/3Fx1MDAxMpdFMlwimFEr8WhcdTAwMGVcItKHXGJcdTAwMTA1ODTArSlP5phpw8tcdTAwMWbl3vbM7s244UVcdTAwMDBAoFx1MDAxMNLox0AuQVx1MDAxMiQ4ps9RXHUwMDEwx4hcdTAwMTE416LqXHRcdTAwMWa2j4+/6pX4XHUwMDBmX0d+/aUrwdUvstm2sOzLoZL6nj/or4e84a/Zld1GJbg/lYbtt4a98lx1MDAxY1vAbKDD/Fx0NFx1MDAxY6BHXHUwMDE0W1x1MDAxMk/exYbf98ubjfpcdTAwMTLkXHUwMDFj0TVcdTAwMWbnY1xcYCCYqdaTwMIxo+ZcdTAwM