pazz / alot

Terminal-based Mail User Agent
GNU General Public License v3.0
703 stars 163 forks source link

Some emails fail to open with `unknown encoding: unknown-8bit` #1399

Open eeeeeta opened 5 years ago

eeeeeta commented 5 years ago

Describe the bug Opening some emails fails with unknown encoding: unknown-8bit (check the log for details). The emails causing this problem seem to all have been sent from Microsoft Outlook. It also looks like they're base64 encoded (meaning you can't read the email in vim either, quite annoyingly)

Rather frustratingly, alot completely fails to display the email, instead of gracefully only displaying parts of it; this makes using alot unusable for these emails.

Software Versions

To Reproduce Steps to reproduce the behaviour:

  1. open a strangely-encoded email
  2. see error

Error Log


DEBUG:utils:Content-Transfer-Encoding: "base64"                                                                                        
DEBUG:utils:assuming Content-Transfer-Encoding: base64                                                                                 
DEBUG:utils:Decoding failure: 'utf-8' codec can't decode byte 0x92 in position 4662: invalid start byte                                
ERROR:ui:Traceback (most recent call last):                                                                                            
  File "/usr/lib/python3.7/site-packages/alot/db/utils.py", line 442, in remove_cte                                                    
    sp = bp.decode(enc)                                                                                                                
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x92 in position 4662: invalid start byte                                          

During handling of the above exception, another exception occurred:                                                                    

Traceback (most recent call last):                                                                                                     
  File "/usr/lib/python3.7/site-packages/alot/ui.py", line 711, in apply_command                                                       
    cmd.apply(self)                                                                                                                    
  File "/usr/lib/python3.7/site-packages/alot/commands/search.py", line 41, in apply                                                   
    sb = buffers.ThreadBuffer(ui, self.thread)                                                                                         
  File "/usr/lib/python3.7/site-packages/alot/buffers/thread.py", line 37, in __init__
    self.rebuild()
  File "/usr/lib/python3.7/site-packages/alot/buffers/thread.py", line 73, in rebuild
    self._tree = ThreadTree(self.thread)
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 352, in __init__                                        
    accumulate(msg)
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 343, in accumulate                                             
    odd = accumulate(reply, odd)
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 343, in accumulate                                             
    odd = accumulate(reply, odd)
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 343, in accumulate                                             
    odd = accumulate(reply, odd)
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 331, in accumulate                                             
    self._message[mid] = MessageTree(msg, odd)
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 172, in __init__                                               
    self._maintree = SimpleTree(self._assemble_structure())
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 205, in _assemble_structure                                    
    bodytree = self._get_body()
  File "/usr/lib/python3.7/site-packages/alot/widgets/thread.py", line 238, in _get_body                                              
    bodytxt = self._message.accumulate_body()
  File "/usr/lib/python3.7/site-packages/alot/db/message.py", line 275, in accumulate_body                                            
    bodytext = extract_body(eml)
  File "/usr/lib/python3.7/site-packages/alot/db/utils.py", line 502, in extract_body                                                 
    body_parts.append(string_sanitize(remove_cte(part, as_string=True)))                                                              
  File "/usr/lib/python3.7/site-packages/alot/db/utils.py", line 451, in remove_cte                                                   
    sp = helper.try_decode(bp)
  File "/usr/lib/python3.7/site-packages/alot/helper.py", line 413, in try_decode                                                     
    return blob.decode(guess_encoding(blob))
LookupError: unknown encoding: unknown-8bit
pazz commented 5 years ago

I cannot reproduce nor trace this: the stack trace ends in a line that seems to have no relation to the exception! Does your mail contain "unknown-8bit" as content encoding header?

eeeeeta commented 5 years ago

@pazz Doesn't look like it:

Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64

I think the exception may be a python thing, instead of something alot itself throws? (I googled and found, e.g.
https://gitlab.com/mailman/mailman/issues/445). That would make sense, seeing as alot calls blob.decode(), maybe?

Quoting Patrick Totzke (2019-05-16 16:22:20)

I cannot reproduce nor trace this: the stack trace ends in a line that seems to have no relation to the exception! Does your mail contain "unknown-8bit" as content encoding header?

— You are receiving this because you authored the thread. Reply to this email directly, [1]view it on GitHub, or [2]mute the thread.

References

Visible links

  1. https://github.com/pazz/alot/issues/1399?email_source=notifications&email_token=ACHXT5SLYG5FW6FJ42DLKPTPVV32ZA5CNFSM4HNL6HXKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVSFADA#issuecomment-493113356
  2. https://github.com/notifications/unsubscribe-auth/ACHXT5SZPFXIDL65NKQGBE3PVV32ZANCNFSM4HNL6HXA
arjunkc commented 4 years ago

I get a similar error on alot version 0.8.1 on debian buster python 3.7.3, notmuch 0.28.4. Note that the email opens fine inside alot when I use w3m to dump output but I get the same error above when calling

:pipeto myprogram

However, on alot version 0.7.1 using python2, I do not get the same error!

Here is the error log from the alot version 0.8.1 python 3.7.3

bindings: bufferlist
bindings: search
bindings: envelope
bindings: taglist
bindings: namedqueries
bindings: thread
ERROR:manager:unable to load hooks file:/home/arjun/.config/alot/hooks.py
Traceback (most recent call last):
  File "/usr/share/alot/alot/settings/manager.py", line 84, in read_config
    spec.loader.exec_module(self.hooks)
  File "<frozen importlib._bootstrap_external>", line 724, in exec_module
  File "<frozen importlib._bootstrap_external>", line 859, in get_code
  File "<frozen importlib._bootstrap_external>", line 916, in get_data
FileNotFoundError: [Errno 2] No such file or directory: '/home/arjun/.config/alot/hooks.py'
INFO:ui:setup gui in 256 colours
INFO:search:open thread view for thread:0000000000006421: Dan Geba, MTH 165
ERROR:ui:Traceback (most recent call last):
  File "/usr/share/alot/alot/ui.py", line 709, in apply_command
    await cmd.apply(self)
  File "/usr/share/alot/alot/commands/thread.py", line 752, in apply
    encoded_mail = mail.encode(urwid.util.detected_encoding)
LookupError: unknown encoding: 

So it seems to be a problem with urwid, but I have it installed and working fine on both python3 and python2.

Should I start a new bug, or is it the same error?

josch commented 4 years ago

Hi, I'm on alot 0.9-1 and I'm getting the same error log as OP:

DEBUG:utils:unquoted header: |"Maria Elisa"<admin@boom4anyrea.gq>|
DEBUG:utils:Content-Transfer-Encoding: "quoted-printable"
DEBUG:utils:assuming Content-Transfer-Encoding: quoted-printable
DEBUG:utils:Decoding failure: 'utf-8' codec can't decode byte 0x80 in position 52: invalid start byte
ERROR:ui:Traceback (most recent call last):
  File "/usr/share/alot/alot/db/utils.py", line 446, in remove_cte
    sp = bp.decode(enc)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 52: invalid start byte

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/share/alot/alot/ui.py", line 718, in apply_command
    cmd.apply(self)
  File "/usr/share/alot/alot/commands/globals.py", line 126, in apply
    sort_order=self.order))
  File "/usr/share/alot/alot/ui.py", line 412, in buffer_open
    self.buffer_focus(buf)
  File "/usr/share/alot/alot/ui.py", line 472, in buffer_focus
    self.update()
  File "/usr/share/alot/alot/ui.py", line 663, in update
    self.mainloop.draw_screen()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 586, in draw_screen
    canvas = self._topmost_widget.render(self.screen_size, focus=True)
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 144, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 226, in render
    canv = self._original_widget.render(size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 144, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 1086, in render
    focus and self.focus_part == 'body')
  File "/usr/share/alot/alot/buffers/buffer.py", line 19, in render
    return self.body.render(size, focus)
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 144, in cached_render
    canv = fn(self, size, focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 471, in render
    (maxcol, maxrow), focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 353, in calculate_visible
    self._set_focus_complete( (maxcol, maxrow), focus )
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 718, in _set_focus_complete
    (maxcol,maxrow), focus)
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 688, in _set_focus_first_selectable
    (maxcol, maxrow), focus=focus)
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 356, in calculate_visible
    focus_widget, focus_pos = self._body.get_focus()
  File "/usr/share/alot/alot/walker.py", line 39, in get_focus
    return self._get_at_pos(self.focus)
  File "/usr/share/alot/alot/walker.py", line 72, in _get_at_pos
    widget = self._get_next_item()
  File "/usr/share/alot/alot/walker.py", line 85, in _get_next_item
    next_widget = self.containerclass(next_obj, **self.kwargs)
  File "/usr/share/alot/alot/widgets/search.py", line 26, in __init__
    self.rebuild()
  File "/usr/share/alot/alot/widgets/search.py", line 61, in rebuild
    self.structure[partname])
  File "/usr/share/alot/alot/widgets/search.py", line 145, in build_text_part
    content = prepare_string(name, thread, maxw)
  File "/usr/share/alot/alot/widgets/search.py", line 213, in prepare_string
    s = content(thread)
  File "/usr/share/alot/alot/widgets/search.py", line 188, in prepare_content_string
    lastcontent = ' '.join(m.get_body_text() for m in msgs)
  File "/usr/share/alot/alot/widgets/search.py", line 188, in <genexpr>
    lastcontent = ' '.join(m.get_body_text() for m in msgs)
  File "/usr/share/alot/alot/db/message.py", line 266, in get_body_text
    return extract_body(self.get_email())
  File "/usr/share/alot/alot/db/utils.py", line 491, in extract_body
    displaystring = string_sanitize(remove_cte(body_part, as_string=True))
  File "/usr/share/alot/alot/db/utils.py", line 455, in remove_cte
    sp = helper.try_decode(bp)
  File "/usr/share/alot/alot/helper.py", line 410, in try_decode
    return blob.decode(guess_encoding(blob))
LookupError: unknown encoding: unknown-8bit

Fortunately, the reason is a spam E-Mail so I can share the entire mail that triggers the problem with you guys so that you can reproduce the issue. I encoded it with base64 to make sure that github doesn't munge some bytes into something else:

UmV0dXJuLVBhdGg6IDxhZG1pbkBib29tNGFueXJlYS5ncT4KWC1PcmlnaW5hbC1Ubzogam9zY2hA
bWlzdGVyLW11ZmZpbi5kZQpEZWxpdmVyZWQtVG86IGpvc2NoQG1pc3Rlci1tdWZmaW4uZGUKUmVj
ZWl2ZWQ6IGZyb20gbWFpbC5ib29tNGFueXJlYS5ncSAodW5rbm93biBbNjguMTgzLjg4LjEzXSkK
CWJ5IG1pc3Rlci1tdWZmaW4uZGUgKFBvc3RmaXgpIHdpdGggRVNNVFAgaWQgMUE5NzcyMDEzNAoJ
Zm9yIDxqb3NjaEBtaXN0ZXItbXVmZmluLmRlPjsgVGh1LCAyNSBBcHIgMjAxOSAyMToyNjowMyAr
MDIwMCAoQ0VTVCkKUmVjZWl2ZWQ6IGZyb20gWzE5Mi4xNjguMC4xNDVdICh1bmtub3duIFsxMDIu
MTY1LjIwMi43NF0pCglieSBtYWlsLmJvb200YW55cmVhLmdxIChQb3N0Zml4KSB3aXRoIEVTTVRQ
QSBpZCBCRkIwRTUxQzM4QTsKCVRodSwgMjUgQXByIDIwMTkgMTU6NTQ6NDEgKzAwMDAgKFVUQykK
Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvYWx0ZXJuYXRpdmU7IGJvdW5kYXJ5PSI9PT09PT09PT09
PT09PT0xNTMyNTQyNzQ5PT0iCk1JTUUtVmVyc2lvbjogMS4wClN1YmplY3Q6ID0/dXRmLTg/Yj9S
Rzl1WVhScGIyNGdiMllnNG9Lc01TdzNNREFzTURBdz89ClRvOiBSZWNpcGllbnRzIDxhZG1pbkBi
b29tNGFueXJlYS5ncT4KRnJvbTogIk1hcmlhIEVsaXNhIjxhZG1pbkBib29tNGFueXJlYS5ncT4K
RGF0ZTogVGh1LCAyNSBBcHIgMjAxOSAwODo1NDoxMCAtMDcwMApSZXBseS1UbzogcGF0cmljaWFj
aGFuZGxlcjBAZ21haWwuY29tClgtQW50aXZpcnVzOiBBdmFzdCAoVlBTIDE5MDQyNS0wLCAwNC8y
NC8yMDE5KSwgT3V0Ym91bmQgbWVzc2FnZQpYLUFudGl2aXJ1cy1TdGF0dXM6IENsZWFuCgpZb3Ug
d2lsbCBub3Qgc2VlIHRoaXMgaW4gYSBNSU1FLWF3YXJlIG1haWwgcmVhZGVyLgotLT09PT09PT09
PT09PT09PTE1MzI1NDI3NDk9PQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9InV0
Zi04IgpNSU1FLVZlcnNpb246IDEuMApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBxdW90ZWQt
cHJpbnRhYmxlCkNvbnRlbnQtRGVzY3JpcHRpb246IE1haWwgbWVzc2FnZSBib2R5CgpZb3Ugd2Vy
ZSBjaG9zZW4gdG8gcmVjZWl2ZSBhIENhc2ggR3JhbnQgRG9uYXRpb24gb2YgPTgwMSw3MDAsMDAw
IGZyb20gTWFyaWE9Ci1FbGlzYWJldGgsIFJlc3BvbmQgYmFjayBmb3IgbW9yZSBkZXRhaWxzIGVt
YWlsIG1lIGF0OiBtZTMwNjk5NUBnbWFpbC5jb20gCgotLS0KVGhpcyBlbWFpbCBoYXMgYmVlbiBj
aGVja2VkIGZvciB2aXJ1c2VzIGJ5IEF2YXN0IGFudGl2aXJ1cyBzb2Z0d2FyZS4KaHR0cHM6Ly93
d3cuYXZhc3QuY29tL2FudGl2aXJ1cwoKLS09PT09PT09PT09PT09PT0xNTMyNTQyNzQ5PT0KQ29u
dGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9InV0Zi04IgpNSU1FLVZlcnNpb246IDEuMApD
b250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBxdW90ZWQtcHJpbnRhYmxlCkNvbnRlbnQtRGVzY3Jp
cHRpb246IE1haWwgbWVzc2FnZSBib2R5Cgo8aHRtbD48aGVhZD48bWV0YSBodHRwLWVxdWl2PTNE
IkNvbnRlbnQtVHlwZSIgY29udGVudD0zRCJ0ZXh0L2h0bWw7IGNoYXJzZXQ9Cj0zRHV0Zi04Ii8+
PC9oZWFkPllvdSB3ZXJlIGNob3NlbiB0byByZWNlaXZlIGEgQ2FzaCBHcmFudCBEb25hdGlvbiBv
ZiA9RTI9Cj04Mj1BQzEsNzAwLDAwMCBmcm9tIE1hcmlhLUVsaXNhYmV0aCwgUmVzcG9uZCBiYWNr
IGZvciBtb3JlIGRldGFpbHMgZW1haWwgbT0KZSBhdDogbWUzMDY5OTVAZ21haWwuY29tCgo8ZGl2
IGlkPTNEIkRBQjRGQUQ4LTJERDctNDBCQi1BMUI4LTRFMkFBMUY5RkRGMiI+PGJyIC8+Cjx0YWJs
ZSBzdHlsZT0zRCJib3JkZXItdG9wOiAxcHggc29saWQgI0QzRDRERTsiPgoJPHRyPgogICAgICAg
IDx0ZCBzdHlsZT0zRCJ3aWR0aDogNTVweDsgcGFkZGluZy10b3A6IDEzcHg7Ij48YSBocmVmPTNE
Imh0dHBzOi8vd3c9CncuYXZhc3QuY29tL3NpZy1lbWFpbD91dG1fbWVkaXVtPTNEZW1haWwmdXRt
X3NvdXJjZT0zRGxpbmsmdXRtX2NhbXBhaWduPTNEcz0KaWctZW1haWwmdXRtX2NvbnRlbnQ9M0Rl
bWFpbGNsaWVudCIgdGFyZ2V0PTNEIl9ibGFuayI+PGltZyBzcmM9M0QiaHR0cHM6Ly9pPQpwbWNk
bi5hdmFzdC5jb20vaW1hZ2VzL2ljb25zL2ljb24tZW52ZWxvcGUtdGljay1yb3VuZC1vcmFuZ2Ut
YW5pbWF0ZWQtbm8tcmU9CnBlYXQtdjEuZ2lmIiBhbHQ9M0QiIiB3aWR0aD0zRCI0NiIgaGVpZ2h0
PTNEIjI5IiBzdHlsZT0zRCJ3aWR0aDogNDZweDsgaGVpZz0KaHQ6IDI5cHg7IiAvPjwvYT48L3Rk
PgoJCTx0ZCBzdHlsZT0zRCJ3aWR0aDogNDcwcHg7IHBhZGRpbmctdG9wOiAxMnB4OyBjb2xvcjog
IzQxNDI0ZTsgZm9udC1zaXplOiA9CjEzcHg7IGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNh
LCBzYW5zLXNlcmlmOyBsaW5lLWhlaWdodDogMThweDsiPlZpcnVzLT0KZnJlZS4gPGEgaHJlZj0z
RCJodHRwczovL3d3dy5hdmFzdC5jb20vc2lnLWVtYWlsP3V0bV9tZWRpdW09M0RlbWFpbCZ1dG1f
c291PQpyY2U9M0RsaW5rJnV0bV9jYW1wYWlnbj0zRHNpZy1lbWFpbCZ1dG1fY29udGVudD0zRGVt
YWlsY2xpZW50IiB0YXJnZXQ9M0QiX2I9CmxhbmsiIHN0eWxlPTNEImNvbG9yOiAjNDQ1M2VhOyI+
d3d3LmF2YXN0LmNvbTwvYT4KCQk8L3RkPgoJPC90cj4KPC90YWJsZT48YSBocmVmPTNEIiNEQUI0
RkFEOC0yREQ3LTQwQkItQTFCOC00RTJBQTFGOUZERjIiIHdpZHRoPTNEIjEiIGhlaWdoPQp0PTNE
IjEiPiA8L2E+PC9kaXY+PC9odG1sPgotLT09PT09PT09PT09PT09PTE1MzI1NDI3NDk9PS0tCg==

Here is the md5sum and sha512sum to be sure:

e43f7a1c6479c42a5c7cd3e34dea8606
4a629fd1f20c6572e9e8350f8a8f272ed2a14b0e670a474cb32ec17801ea42da62a13501de1a0f92975dba442b0cc5bc35c0cc8506bfc9ebd38add277f943753

Thanks!

josch commented 4 years ago

And here another one where the traceback is the same, except that the final line is LookupError: unknown encoding: binary

UmV0dXJuLVBhdGg6IDx1bm9rb3QzQGdtYWlsLmNvbT4KWC1PcmlnaW5hbC1Ubzogam9zY2hAbWlz
dGVyLW11ZmZpbi5kZQpEZWxpdmVyZWQtVG86IGpvc2NoQG1pc3Rlci1tdWZmaW4uZGUKUmVjZWl2
ZWQ6IGZyb20gY2VudG9zLXMtMnZjcHUtNGdiLXNmbzItMDEgKHVua25vd24gWzE1OS44OS4xNDcu
MjMwXSkKCWJ5IG1pc3Rlci1tdWZmaW4uZGUgKFBvc3RmaXgpIHdpdGggRVNNVFBTIGlkIEUxMTI5
MjAwRUQKCWZvciA8am9zY2hAbWlzdGVyLW11ZmZpbi5kZT47IFdlZCwgMjcgRmViIDIwMTkgMDY6
Mzc6MzMgKzAxMDAgKENFVCkKUmVjZWl2ZWQ6IGZyb20gWzQwLjExNC4xMjcuMjIyXSAoaGVsbz1z
aGF3YW5kYWxheDMuNHlod2ViaGttcnl1M2QxZGhvaXJsaDJ2MmUuYnguaW50ZXJuYWwuY2xvdWRh
cHAubmV0KQoJYnkgY2VudG9zLXMtMnZjcHUtNGdiLXNmbzItMDEgd2l0aCBlc210cGEgKEV4aW0g
NC45MSkKCShlbnZlbG9wZS1mcm9tIDx1bm9rb3QzQGdtYWlsLmNvbT4pCglpZCAxZ3lyc3otMDAw
NEtxLTNECglmb3Igam9zY2hAbWlzdGVyLW11ZmZpbi5kZTsgV2VkLCAyNyBGZWIgMjAxOSAwNToz
NjowNSArMDAwMApDb250ZW50LVR5cGU6IG11bHRpcGFydC9hbHRlcm5hdGl2ZTsgYm91bmRhcnk9
Ij09PT09PT09PT09PT09PTIxMDU5MDg3ODI9PSIKTUlNRS1WZXJzaW9uOiAxLjAKU3ViamVjdDog
Y29sbGFib3JhdGlvbgpUbzogam9zY2hAbWlzdGVyLW11ZmZpbi5kZQpGcm9tOiAiTXIuIFBoYW4i
IDx1bm9rb3QzQGdtYWlsLmNvbT4KRGF0ZTogV2VkLCAyNyBGZWIgMjAxOSAwNTozNjowNCArMDAw
MApSZXBseS1UbzogcGhhdHJ1bmdAdm51dm4uY29tCk1lc3NhZ2UtSWQ6IDxFMWd5cnN6LTAwMDRL
cS0zREBjZW50b3Mtcy0ydmNwdS00Z2Itc2ZvMi0wMT4KCllvdSB3aWxsIG5vdCBzZWUgdGhpcyBp
biBhIE1JTUUtYXdhcmUgbWFpbCByZWFkZXIuCi0tPT09PT09PT09PT09PT09MjEwNTkwODc4Mj09
CkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD0idXRmLTgiCk1JTUUtVmVyc2lvbjog
MS4wCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1wcmludGFibGUKQ29udGVudC1E
ZXNjcmlwdGlvbjogTWFpbCBtZXNzYWdlIGJvZHkKCiBEZWFyIGNvbGxlYWd1ZSwKCkl0IGlzIG15
IHBsZWFzdXJlIHRvIGNvbW11bmljYXRlIHlvdSwgYnkgaW50cm9kdWN0aW9uOyBJIGFtIFBoYW4K
TmdvYyBUcnVuZyAtIEV4ZWN1dGl2ZSBCb2FyZCBNZW1iZXIgb2YgUGV0cm8tVmlldG5hbSBvaWwg
YW5kIEdhcwpHcm91cC4KCkkgYW0gbG9va2luZyBhdCBhIG11dHVhbCBidXNpbmVzcyBjb2xsYWJv
cmF0aW9uIHdpdGggeW91IG9yIHlvdXIKY29tcGFueS4gV2UgbWF5IGFsc28gbG9vayBhdCB0aGUg
aW1wb3J0YW5jZSBvZiBkaXNjdXNzaW5nIHByb3Blcmx5Cm9uIHRoZSBwb3NzaWJpbGl0eSBvZiBh
bnkgY29sbGFib3JhdGlvbiB3ZSBtYXkgZmluZCBzdWl0YWJsZSBpbiB0aGUKbmVhciBmdXR1cmUg
d2hlbiBJIHJlY2VpdmUgeW91ciBmZWVkYmFjay4KClRoYW5rIFlvdQoKTXIuIFBoYW4gTmdvYyBU
cnVuZwpNZW1iZXIgb2YgdGhlIE1lbWJlcnNoaXAgQ291bmNpbCBvZiBQZXRyb1ZpZXRuYW0gb2ls
IGFuZCBHYXMgR3JvdXAuCk5vOiAxIEw9RUEgRHU9MUVBOW4sIEI9MUVCRm4gTmdoPUU5LCBRdT0x
RUFEbiAxLCBIPTFFRDMgQ2g9RUQgTWluaCwgVmlldG5hbQoKLS09PT09PT09PT09PT09PT0yMTA1
OTA4NzgyPT0KQ29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9InV0Zi04IgpNSU1FLVZl
cnNpb246IDEuMApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBxdW90ZWQtcHJpbnRhYmxlCkNv
bnRlbnQtRGVzY3JpcHRpb246IE1haWwgbWVzc2FnZSBib2R5Cgo8SFRNTD48aGVhZD4KPG1ldGEg
aHR0cC1lcXVpdj0zRCJDb250ZW50LVR5cGUiIGNvbnRlbnQ9M0QidGV4dC9odG1sOyBjaGFyc2V0
PTNEdXRmLTgiPgo8dGl0bGU+TmV3IFBhZ2UgMTwvdGl0bGU+CjwvaGVhZD4KCjxib2R5PjxQPiZu
YnNwO0RlYXIgY29sbGVhZ3VlLDxCUj48QlI+SXQgaXMgbXkgcGxlYXN1cmUgdG8gY29tbXVuaWNh
dGUgeW91LD0KIGJ5IGludHJvZHVjdGlvbjsgSSBhbSBQaGFuPEJSPk5nb2MgVHJ1bmcgLSBFeGVj
dXRpdmUgQm9hcmQgTWVtYmVyIG9mIFBldHJvPQotVmlldG5hbSBvaWwgYW5kIEdhczxCUj5Hcm91
cC48QlI+PEJSPkkgYW0gbG9va2luZyBhdCBhIG11dHVhbCBidXNpbmVzcyBjb2w9CmxhYm9yYXRp
b24gd2l0aCB5b3Ugb3IgeW91cjxCUj5jb21wYW55LiBXZSBtYXkgYWxzbyBsb29rIGF0IHRoZSBp
bXBvcnRhbmNlID0Kb2YgZGlzY3Vzc2luZyBwcm9wZXJseTxCUj5vbiB0aGUgcG9zc2liaWxpdHkg
b2YgYW55IGNvbGxhYm9yYXRpb24gd2UgbWF5IGZpPQpuZCBzdWl0YWJsZSBpbiB0aGU8QlI+bmVh
ciBmdXR1cmUgd2hlbiBJIHJlY2VpdmUgeW91ciBmZWVkYmFjay48QlI+PEJSPlRoYW49CmsgWW91
PEJSPjxCUj5Nci4gUGhhbiBOZ29jIFRydW5nPEJSPk1lbWJlciBvZiB0aGUgTWVtYmVyc2hpcCBD
b3VuY2lsIG9mIFBldD0Kcm9WaWV0bmFtIG9pbCBhbmQgR2FzIEdyb3VwLjxCUj5ObzogMSBMPUMz
PUFBIER1PUUxPUJBPUE5biwgQj1FMT1CQT1CRm4gTmdoPQo9QzM9QTksIFF1PUUxPUJBPUFEbiAx
LCBIPUUxPUJCPTkzIENoPUMzPUFEIE1pbmgsIFZpZXRuYW08L1A+PC9CT0RZPjwvSFRNTD4KLS09
PT09PT09PT09PT09PT0yMTA1OTA4NzgyPT0tLQo=

hashes:

ec1824bd6cfe28ca26367f3233c5b065
426b7fd13da27c7492eb5070f1336d66b53380a99ba87899489ccd1514ff670672c7868306ae33656607505413f2a5494ae24f15ac10fb30c2cdd203bf3f1cec