Alyssa Smith revised this gist . Go to revision
1 file changed, 6 insertions, 2 deletions
txtrecord_encode.py
| @@ -11,8 +11,12 @@ def main(): | |||
| 11 | 11 | parser.add_argument("domain", help="Target domain") | |
| 12 | 12 | parser.add_argument("--format", help="DNS record format, where {0} is the target domain (without trailing dot), and {1} is the record text (defaults to bind/named \"{0}. IN TXT '{1}'\")", default="{0}. IN TXT '{1}'") | |
| 13 | 13 | args = parser.parse_args() | |
| 14 | - | with open(sys.stdin if args.input == "-" else args.input,"rb") as f: | |
| 15 | - | enc = base64.b64encode(f.read()).decode("utf-8") | |
| 14 | + | if args.input == "-": | |
| 15 | + | inp = sys.stdin.buffer.read() | |
| 16 | + | else: | |
| 17 | + | with open(args.input,"rb") as f: | |
| 18 | + | inp = f.read() | |
| 19 | + | enc = base64.b64encode(inp).decode("utf-8") | |
| 16 | 20 | tot = len(enc) | |
| 17 | 21 | tmp = 0 | |
| 18 | 22 | for n,block in enumerate(wrap(enc,65000)): | |
Alyssa Smith revised this gist . Go to revision
1 file changed, 7 insertions, 3 deletions
txtrecord_decode.py
| @@ -32,9 +32,13 @@ def main(): | |||
| 32 | 32 | out += next_out | |
| 33 | 33 | if not name: | |
| 34 | 34 | break | |
| 35 | - | ||
| 36 | - | with open(sys.stdout if args.output == "-" else args.output, "wb") as f: | |
| 37 | - | f.write(base64.b64decode(out)) | |
| 35 | + | ||
| 36 | + | if args.output == "-": | |
| 37 | + | sys.stdout.buffer.write(base64.b64decode(out)) | |
| 38 | + | sys.stdout.flush() | |
| 39 | + | else: | |
| 40 | + | with open(args.output, "wb") as f: | |
| 41 | + | f.write(base64.b64decode(out)) | |
| 38 | 42 | return 0 | |
| 39 | 43 | ||
| 40 | 44 | if __name__ == "__main__": | |
Suv Smith revised this gist . Go to revision
2 files changed, 23 insertions, 13 deletions
txtrecord_decode.py
| @@ -1,8 +1,9 @@ | |||
| 1 | 1 | #!/usr/bin/env python3 | |
| 2 | - | # txtrecord_decode.py output.png logo.example.com | |
| 2 | + | # txtrecord_decode.py [-h] output.png logo.example.com | |
| 3 | 3 | import dns.resolver # pip3 install dnspython | |
| 4 | 4 | import base64 | |
| 5 | 5 | import sys | |
| 6 | + | from argparse import ArgumentParser | |
| 6 | 7 | def parse_records(name): | |
| 7 | 8 | _next = "" | |
| 8 | 9 | print("{}".format(name), file=sys.stderr) | |
| @@ -19,13 +20,22 @@ def parse_records(name): | |||
| 19 | 20 | pass | |
| 20 | 21 | return out, _next | |
| 21 | 22 | ||
| 22 | - | out = b"" | |
| 23 | - | name = sys.argv[2] | |
| 24 | - | while True: | |
| 25 | - | next_out, name = parse_records(name) | |
| 26 | - | out += next_out | |
| 27 | - | if not name: | |
| 28 | - | break | |
| 23 | + | def main(): | |
| 24 | + | parser = ArgumentParser() | |
| 25 | + | parser.add_argument("output", help="Output filename (or - for stdout)") | |
| 26 | + | parser.add_argument("domain", help="Target domain") | |
| 27 | + | args = parser.parse_args() | |
| 28 | + | name = args.domain | |
| 29 | + | out = b"" | |
| 30 | + | while True: | |
| 31 | + | next_out, name = parse_records(name) | |
| 32 | + | out += next_out | |
| 33 | + | if not name: | |
| 34 | + | break | |
| 35 | + | ||
| 36 | + | with open(sys.stdout if args.output == "-" else args.output, "wb") as f: | |
| 37 | + | f.write(base64.b64decode(out)) | |
| 38 | + | return 0 | |
| 29 | 39 | ||
| 30 | - | with open(sys.argv[1],"wb") as f: | |
| 31 | - | f.write(base64.b64decode(out)) | |
| 40 | + | if __name__ == "__main__": | |
| 41 | + | sys.exit(main()) | |
txtrecord_encode.py
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | #!/usr/bin/env python3 | |
| 2 | - | # txtrecord_encode.py input.png logo.example.com [--format '{0} IN TXT "{1}"'] | |
| 2 | + | # txtrecord_encode.py [-h] [--format '{0} IN TXT "{1}"'] input.png logo.example.com | |
| 3 | 3 | import base64 | |
| 4 | 4 | import sys | |
| 5 | 5 | from argparse import ArgumentParser | |
| @@ -7,11 +7,11 @@ from textwrap import wrap | |||
| 7 | 7 | ||
| 8 | 8 | def main(): | |
| 9 | 9 | parser = ArgumentParser() | |
| 10 | - | parser.add_argument("input", help="Input filename") | |
| 10 | + | parser.add_argument("input", help="Input filename (or - for stdin)") | |
| 11 | 11 | parser.add_argument("domain", help="Target domain") | |
| 12 | 12 | parser.add_argument("--format", help="DNS record format, where {0} is the target domain (without trailing dot), and {1} is the record text (defaults to bind/named \"{0}. IN TXT '{1}'\")", default="{0}. IN TXT '{1}'") | |
| 13 | 13 | args = parser.parse_args() | |
| 14 | - | with open(args.input,"rb") as f: | |
| 14 | + | with open(sys.stdin if args.input == "-" else args.input,"rb") as f: | |
| 15 | 15 | enc = base64.b64encode(f.read()).decode("utf-8") | |
| 16 | 16 | tot = len(enc) | |
| 17 | 17 | tmp = 0 | |
Suv Smith revised this gist . Go to revision
1 file changed, 21 insertions, 13 deletions
txtrecord_encode.py
| @@ -1,18 +1,26 @@ | |||
| 1 | 1 | #!/usr/bin/env python3 | |
| 2 | - | # txtrecord_encode.py input.png logo.example.com | |
| 2 | + | # txtrecord_encode.py input.png logo.example.com [--format '{0} IN TXT "{1}"'] | |
| 3 | 3 | import base64 | |
| 4 | 4 | import sys | |
| 5 | + | from argparse import ArgumentParser | |
| 5 | 6 | from textwrap import wrap | |
| 6 | - | with open(sys.argv[1],"rb") as f: | |
| 7 | - | enc = base64.b64encode(f.read()).decode("utf-8") | |
| 8 | 7 | ||
| 9 | - | # '%04d' and '247' may need to be updated for large files to ensure the line count doesn't push the length | |
| 10 | - | # longer than 255 bytes | |
| 11 | - | tot = len(enc) | |
| 12 | - | tmp = 0 | |
| 13 | - | for n,block in enumerate(wrap(enc,65000)): | |
| 14 | - | tmp += len(block) | |
| 15 | - | print("\n".join("{0}. IN TXT '{1}{2}'".format((str(n) if n else "") + sys.argv[2], "{%03d}" % _n, s) for _n, s in enumerate(wrap(block,249)))) | |
| 16 | - | if tmp != tot: | |
| 17 | - | print("{0}. IN TXT '{1}{2}.".format((str(n) if n else "") + sys.argv[2], "{nxt}", str(n+1) + sys.argv[2])) | |
| 18 | - | #print("\n".join("%s. IN TXT '{%03d}%s'" % (sys.argv[2], n,s) for n,s in enumerate(wrap(enc,249)))) | |
| 8 | + | def main(): | |
| 9 | + | parser = ArgumentParser() | |
| 10 | + | parser.add_argument("input", help="Input filename") | |
| 11 | + | parser.add_argument("domain", help="Target domain") | |
| 12 | + | parser.add_argument("--format", help="DNS record format, where {0} is the target domain (without trailing dot), and {1} is the record text (defaults to bind/named \"{0}. IN TXT '{1}'\")", default="{0}. IN TXT '{1}'") | |
| 13 | + | args = parser.parse_args() | |
| 14 | + | with open(args.input,"rb") as f: | |
| 15 | + | enc = base64.b64encode(f.read()).decode("utf-8") | |
| 16 | + | tot = len(enc) | |
| 17 | + | tmp = 0 | |
| 18 | + | for n,block in enumerate(wrap(enc,65000)): | |
| 19 | + | tmp += len(block) | |
| 20 | + | print("\n".join(args.format.format((str(n) if n else "") + sys.argv[2], "{}{}".format("{%03d}" % _n, s)) for _n, s in enumerate(wrap(block,249)))) | |
| 21 | + | if tmp != tot: | |
| 22 | + | print(args.format.format((str(n) if n else "") + sys.argv[2], "{}{}".format("{nxt}", str(n+1) + sys.argv[2] + "."))) | |
| 23 | + | return 0 | |
| 24 | + | ||
| 25 | + | if __name__ == "__main__": | |
| 26 | + | sys.exit(main()) | |
Suv Smith revised this gist . Go to revision
1 file changed, 4 insertions, 11 deletions
untitled.ipynb
Diff is too large to be shown
Suv Smith revised this gist . Go to revision
1 file changed, 80 insertions, 20 deletions
untitled.ipynb
Diff is too large to be shown
blha303 revised this gist . Go to revision
2 files changed, 32 insertions, 9 deletions
txtrecord_decode.py
| @@ -3,13 +3,29 @@ | |||
| 3 | 3 | import dns.resolver # pip3 install dnspython | |
| 4 | 4 | import base64 | |
| 5 | 5 | import sys | |
| 6 | - | q = dns.resolver.query(sys.argv[2],"TXT").response.answer[0] | |
| 6 | + | def parse_records(name): | |
| 7 | + | _next = "" | |
| 8 | + | print("{}".format(name), file=sys.stderr) | |
| 9 | + | q = dns.resolver.query(name,"TXT").response.answer[0] | |
| 10 | + | out = b"" | |
| 11 | + | for line in sorted(_.strings[0] for _ in q): | |
| 12 | + | if chr(line[0]) == "{": | |
| 13 | + | if chr(line[1]) == "n": | |
| 14 | + | _next = line.split(b"}",1)[1].decode("utf-8") | |
| 15 | + | continue | |
| 16 | + | try: | |
| 17 | + | out += line.split(b"}",1)[1] | |
| 18 | + | except IndexError: | |
| 19 | + | pass | |
| 20 | + | return out, _next | |
| 21 | + | ||
| 7 | 22 | out = b"" | |
| 8 | - | for line in sorted(_.strings[0] for _ in q): | |
| 9 | - | if chr(line[0]) == "{": | |
| 10 | - | try: | |
| 11 | - | out += line.split(b"}",1)[1] | |
| 12 | - | except IndexError: | |
| 13 | - | pass | |
| 23 | + | name = sys.argv[2] | |
| 24 | + | while True: | |
| 25 | + | next_out, name = parse_records(name) | |
| 26 | + | out += next_out | |
| 27 | + | if not name: | |
| 28 | + | break | |
| 29 | + | ||
| 14 | 30 | with open(sys.argv[1],"wb") as f: | |
| 15 | - | f.write(base64.b64decode(out)) | |
| 31 | + | f.write(base64.b64decode(out)) | |
txtrecord_encode.py
| @@ -8,4 +8,11 @@ with open(sys.argv[1],"rb") as f: | |||
| 8 | 8 | ||
| 9 | 9 | # '%04d' and '247' may need to be updated for large files to ensure the line count doesn't push the length | |
| 10 | 10 | # longer than 255 bytes | |
| 11 | - | print("\n".join("%s. IN TXT '{%04d}%s'" % (sys.argv[2], n,s) for n,s in enumerate(wrap(enc,247)))) | |
| 11 | + | tot = len(enc) | |
| 12 | + | tmp = 0 | |
| 13 | + | for n,block in enumerate(wrap(enc,65000)): | |
| 14 | + | tmp += len(block) | |
| 15 | + | print("\n".join("{0}. IN TXT '{1}{2}'".format((str(n) if n else "") + sys.argv[2], "{%03d}" % _n, s) for _n, s in enumerate(wrap(block,249)))) | |
| 16 | + | if tmp != tot: | |
| 17 | + | print("{0}. IN TXT '{1}{2}.".format((str(n) if n else "") + sys.argv[2], "{nxt}", str(n+1) + sys.argv[2])) | |
| 18 | + | #print("\n".join("%s. IN TXT '{%03d}%s'" % (sys.argv[2], n,s) for n,s in enumerate(wrap(enc,249)))) | |
S Smith revised this gist . Go to revision
1 file changed, 88 insertions
untitled.ipynb(file created)
| @@ -0,0 +1,88 @@ | |||
| 1 | + | { | |
| 2 | + | "cells": [ | |
| 3 | + | { | |
| 4 | + | "cell_type": "markdown", | |
| 5 | + | "metadata": {}, | |
| 6 | + | "source": [ | |
| 7 | + | "This is a test of Jupyter generating a cool blog post about a neat python project or something." | |
| 8 | + | ] | |
| 9 | + | }, | |
| 10 | + | { | |
| 11 | + | "cell_type": "code", | |
| 12 | + | "execution_count": 10, | |
| 13 | + | "metadata": {}, | |
| 14 | + | "outputs": [ | |
| 15 | + | { | |
| 16 | + | "name": "stdout", | |
| 17 | + | "output_type": "stream", | |
| 18 | + | "text": [ | |
| 19 | + | "b'test'\n", | |
| 20 | + | "b'{00}iVBORw0KGgoAAAAN...sQo8aFRo0+M8YCYKGjiE'\n", | |
| 21 | + | "b'{01}Q1CiALGgCAgINfud...ZGAkyJ9sDvO2DzNa4dZk'\n", | |
| 22 | + | "b'{02}E+BTF9RgIePCSjO3...UX6911GGr69VMh/3eWDV'\n", | |
| 23 | + | "b'{03}bE6tkPWUyTPRkqrY...bw8nGGgoCoYXopEPQ1Q7'\n" | |
| 24 | + | ] | |
| 25 | + | } | |
| 26 | + | ], | |
| 27 | + | "source": [ | |
| 28 | + | "import dns.resolver\n", | |
| 29 | + | "import base64\n", | |
| 30 | + | "from IPython.display import HTML\n", | |
| 31 | + | "q = dns.resolver.query(\"logo.hosttel.com.au\",\"TXT\").response.answer[0]\n", | |
| 32 | + | "for line in sorted(_.strings[0] for _ in q)[:5]:\n", | |
| 33 | + | " print((line[:20] + b\"...\" + line[-20:]) if len(line) > 20 else line)" | |
| 34 | + | ] | |
| 35 | + | }, | |
| 36 | + | { | |
| 37 | + | "cell_type": "code", | |
| 38 | + | "execution_count": 3, | |
| 39 | + | "metadata": {}, | |
| 40 | + | "outputs": [ | |
| 41 | + | { | |
| 42 | + | "data": { | |
| 43 | + | "text/html": [ | |
| 44 | + | "<img src='data:image/png;base64,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'/>" | |
| 45 | + | ], | |
| 46 | + | "text/plain": [ | |
| 47 | + | "<IPython.core.display.HTML object>" | |
| 48 | + | ] | |
| 49 | + | }, | |
| 50 | + | "execution_count": 3, | |
| 51 | + | "metadata": {}, | |
| 52 | + | "output_type": "execute_result" | |
| 53 | + | } | |
| 54 | + | ], | |
| 55 | + | "source": [ | |
| 56 | + | "out = b\"\"\n", | |
| 57 | + | "for line in sorted(_.strings[0] for _ in q):\n", | |
| 58 | + | " if chr(line[0]) == \"{\":\n", | |
| 59 | + | " try:\n", | |
| 60 | + | " out += line.split(b\"}\",1)[1]\n", | |
| 61 | + | " except IndexError:\n", | |
| 62 | + | " pass\n", | |
| 63 | + | "HTML(\"<img src='data:image/png;base64,{0}'/>\".format(out.decode('utf-8')))" | |
| 64 | + | ] | |
| 65 | + | } | |
| 66 | + | ], | |
| 67 | + | "metadata": { | |
| 68 | + | "kernelspec": { | |
| 69 | + | "display_name": "Python 3", | |
| 70 | + | "language": "python", | |
| 71 | + | "name": "python3" | |
| 72 | + | }, | |
| 73 | + | "language_info": { | |
| 74 | + | "codemirror_mode": { | |
| 75 | + | "name": "ipython", | |
| 76 | + | "version": 3 | |
| 77 | + | }, | |
| 78 | + | "file_extension": ".py", | |
| 79 | + | "mimetype": "text/x-python", | |
| 80 | + | "name": "python", | |
| 81 | + | "nbconvert_exporter": "python", | |
| 82 | + | "pygments_lexer": "ipython3", | |
| 83 | + | "version": "3.7.3" | |
| 84 | + | } | |
| 85 | + | }, | |
| 86 | + | "nbformat": 4, | |
| 87 | + | "nbformat_minor": 2 | |
| 88 | + | } | |
S Smith revised this gist . Go to revision
1 file changed, 38 deletions
README.md (file deleted)
| @@ -1,38 +0,0 @@ | |||
| 1 | - | This is a test of Jupyter generating a cool blog post about a neat python project or something. | |
| 2 | - | ||
| 3 | - | ||
| 4 | - | ```python | |
| 5 | - | import dns.resolver | |
| 6 | - | import base64 | |
| 7 | - | from IPython.display import HTML | |
| 8 | - | q = dns.resolver.query("logo.hosttel.com.au","TXT").response.answer[0] | |
| 9 | - | for line in sorted(_.strings[0] for _ in q)[:5]: | |
| 10 | - | print((line[:20] + b"..." + line[-20:]) if len(line) > 20 else line) | |
| 11 | - | ``` | |
| 12 | - | ||
| 13 | - | b'test' | |
| 14 | - | b'{00}iVBORw0KGgoAAAAN...sQo8aFRo0+M8YCYKGjiE' | |
| 15 | - | b'{01}Q1CiALGgCAgINfud...ZGAkyJ9sDvO2DzNa4dZk' | |
| 16 | - | b'{02}E+BTF9RgIePCSjO3...UX6911GGr69VMh/3eWDV' | |
| 17 | - | b'{03}bE6tkPWUyTPRkqrY...bw8nGGgoCoYXopEPQ1Q7' | |
| 18 | - | ||
| 19 | - | ||
| 20 | - | ||
| 21 | - | ```python | |
| 22 | - | out = b"" | |
| 23 | - | for line in sorted(_.strings[0] for _ in q): | |
| 24 | - | if chr(line[0]) == "{": | |
| 25 | - | try: | |
| 26 | - | out += line.split(b"}",1)[1] | |
| 27 | - | except IndexError: | |
| 28 | - | pass | |
| 29 | - | HTML("<img src='data:image/png;base64,{0}'/>".format(out.decode('utf-8'))) | |
| 30 | - | ``` | |
| 31 | - | ||
| 32 | - | ||
| 33 | - | ||
| 34 | - | ||
| 35 | - | <img src='data:image/png;base64,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'/> | |
| 36 | - | ||
| 37 | - | ||
| 38 | - | ||
S Smith revised this gist . Go to revision
1 file changed, 38 insertions
README.md(file created)
| @@ -0,0 +1,38 @@ | |||
| 1 | + | This is a test of Jupyter generating a cool blog post about a neat python project or something. | |
| 2 | + | ||
| 3 | + | ||
| 4 | + | ```python | |
| 5 | + | import dns.resolver | |
| 6 | + | import base64 | |
| 7 | + | from IPython.display import HTML | |
| 8 | + | q = dns.resolver.query("logo.hosttel.com.au","TXT").response.answer[0] | |
| 9 | + | for line in sorted(_.strings[0] for _ in q)[:5]: | |
| 10 | + | print((line[:20] + b"..." + line[-20:]) if len(line) > 20 else line) | |
| 11 | + | ``` | |
| 12 | + | ||
| 13 | + | b'test' | |
| 14 | + | b'{00}iVBORw0KGgoAAAAN...sQo8aFRo0+M8YCYKGjiE' | |
| 15 | + | b'{01}Q1CiALGgCAgINfud...ZGAkyJ9sDvO2DzNa4dZk' | |
| 16 | + | b'{02}E+BTF9RgIePCSjO3...UX6911GGr69VMh/3eWDV' | |
| 17 | + | b'{03}bE6tkPWUyTPRkqrY...bw8nGGgoCoYXopEPQ1Q7' | |
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ```python | |
| 22 | + | out = b"" | |
| 23 | + | for line in sorted(_.strings[0] for _ in q): | |
| 24 | + | if chr(line[0]) == "{": | |
| 25 | + | try: | |
| 26 | + | out += line.split(b"}",1)[1] | |
| 27 | + | except IndexError: | |
| 28 | + | pass | |
| 29 | + | HTML("<img src='data:image/png;base64,{0}'/>".format(out.decode('utf-8'))) | |
| 30 | + | ``` | |
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | <img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAAAvCAYAAAABxDNfAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMS4xYyqcSwAAEBhJREFUeF7tXAmUFMUZrlluBUFRVCSiCCILM9M9uxwiiIKgoKIoRDkisAoq6x5TPbO7wB6ASjCIURMlJi8QXsQo8aFRo0+M8YCYKGjiEQ1CiALGgCAgINfudL6/uqane6Z7Z3bZ4fGgv/e+NzNdf1V1VX1d9dfRw3Rd9+ixyel40aPHo6XjRY8ej5ZZRE0OU6OdWYAPYiF+HVO161lQu4LlFZ8vwjx4aDB6FrRjSqSKKdoGpvLvmMKPSO7H700spEU9cXnIHN2LWkFQN6B3+gTUbVQgMFXbCWHVGb+1paxf0WkypgcPLhgYbQfB/ArC2WeKyRDUAYjoAaZGAkyJ9sDvO2DzNa4dZkE+BTF9RgIePCSjO3oeJbwIYqm1i0r7jgUiRSxvegtpaSAUvhLi2g6RvcUGhNvIqx48JDB8+KRTmwfKlkIkNlE1U7S63MsK7mPjxjWTpnao4TsR5zALRQfLKx5OdmAy6YvVsIv3zm5VVDH28r+3ivtNcSoR/apht+o7K1vvjc1hL8L2GvAMGd0AzRgV/insF8orHk5m6DWsZayKlUEoWx+c2K+2DURkExXYLq9UX6911GGr69VMh/3eWDVbE6tkPWUyTPRkqrYM/AvLrWkpr3o4YZHHz2TBcD80+F3wg+bj83HBYOT+M/oV5dbW5JRBJIc+CJ+tn9u3KEVUPgiN3zRMj831CVFZCYFtAC+lHk/kpWpzRK8VLOkgfns4AZE7riULadPhcH+Ext6Nz/3g2+AiiKqwmRodvTHaoQSi2qfP8enXjRgrRJQsrDPzS/S1peekiCpOxP88No/1Enmq/Bak/xkLaJ3Ebw8nGGgoCoYXopEPQ1Q70OCPwbnuLhcxRe+CoS8XotiCT/03U/26L1CeIiryrQYPnaDvrWzpKKo4kc7K2CLWhvmjIdFj9Sk+m/LICEp4FPL6LMHSfBniDhKuwt+xxHv4uB5+u05ujftdIh46ul9FezY+e4Y70QP19xF6/s8awI/Bm0XaTQzooRPa9E0zL7q32exCIzQYjgpRqdou9FpD2ZCa5kZAAoj0OBj7emZb3X/ZHUJEsLczUKH/dFJf07dyI9Kphc2UFrS2pUY+RqXZHfv6oGq3JuV7uQxxh5goaN9Y4qwQjXe8gkSk8tfM+1W0dSyv5hQKQkP2Qf0dcqpXN8L+MARZINJuYuB+OiP9rZa8Dhm+tL+sC278S7AWvF3a2wARXAAlYghk+vKC3nqLRAPZeEpeWP8y2j6tsIhI792RI0fns2DZOvQop8qs0iNFWCUnqLC0VYn75e+ZwprHeqPuDjrVqRuFsKrZVJF2EyN2HzsX6W+x5CWFpfJhqPTvUYCdYmXcATCeLyJBWFcOG+/cWylRfczVN+l18L/imdRHFHTHY5MDd7FA2fMN2jc82YVVyfzUeE516kbYH0F9TxNpNzHchaWU3iB6K1U7ACf9MmlvAr1Pa9zUGuqF3ijsqvuCZfHGsTEH/OVtqhCftVBupBt45EfKCp+/7Mcyq8xwsgvrAdYOdTcSvFawko3C5/Kkut2BIWqSzWY2+4FIOw3QzjlE+TMt3IVFR1ro5AEVIMRfQNK2vTtkciaE9a/D1c30MSPHiJ4pUeAET8Mw+Nfizmbh0hFp1t4/od/6lsHyMTKrzHBsheVjamFn1MvVqKM7xKw5gO+h0nNFWMPgY8ESBfcxWaRFx4ncdiWchEXXXKBXsTlJdbuVfB8ZnBZo4w4Qww8RbxGE8RS4HGkuwLXRSKfegwLuwqICGicPqBAxsNI6Y0Km58B4w+dlp+td+t0Tb5gUXtC/UP93eQezcOmIQuj33jpgxxkDwufJrDLDsRAW+XwkIFV7DtyLhq2zU9uDz5VIc2R6/xAPah7qWNX+DHuMDLa01rBQ9ErGpMDorJqi/Qmk0yHI17xfclVwjX+MsOpkQaJ95iXV7VY0eNp6jc2CKKpZFNyCNOrwGbOkERPXqth6fJ8GgTlOsOoRFk3F6dyULIRxZurB+MYxEuyE4W39U7f31psnCprC4OCp+s7ZbczCpSNuVl8wof/reckb1OmQbWGJDXWa6lM9WPNxIt+HdF90800FFD4cdtud4xP5t5gZ3wlL9I7h7vi9xdlOUuFPsHErjlpYaNcA4q0Fj1jjOpFskOZLeoSdI6ObcBcWQeFV9gJw6rlWMH/Y/1xJ1w6Yiawlx9zRaSfi+oChE/R9VS1SbsqNh6qa67PHDVnG/EVdjhvnXfQY/G2EU/kNW2Nt7yt8fmoQ31V+yAwX5P9kochFMpUE+lZ0hP37ibT4Adh+bhA+rXkds/L8aE+Rhqr9B3bkmiTugb7HD0vSLshRCgs91XmwWWONk46wj4EvJA+N9Qsrr7w9CrfWUpB4Yb5qFtSWLZjYf91p+cXWMDshrBEjxkEszVJuyI1HKpptvPHGghG+QBgVz+eyYIZDYrKwAlp/GeIO6pVVzdprpAqrJ50n4y+BNNSRDcpPw1dkAlPLeok0RDr4HuITYfeGJT3iqpStKeGbiWGMRHVYnOggkVNZFX430pACRZ5BXggXpK1YAFb4ePBDM22FbzTuI3Iz85eGkLLNv2uIsPQFrD3CXySh2OJAHBDEE/ichbCZIH3flmRDw+UiuEemq1S/sAhi2cH0tayM5QTLrE9PKjFTLBg9EgXKbKlBr8QNzO/4vsi3Z2E+KqsOeW9CI4x0Wpy1IVlYCv8d7v1BVLoLEabwxWYDG7QLS2yI85/gulFO0Utpv5AOs5OT7hO9RpA/hrSNiY+IizSs/o+qhWUYiF7N5hvB9yK/K96DBfl8s+emfBX+qiVuvc47GjMjYek688G2GOGHLba14Mu0Wk6zQbIRpO/lYv1yFQnKtK9ie9BrkbgF0gtLbOuITWdZmAYwUK7PuWVQRgujgrNwA0tGDBf59pihQFgyLeFvzK53uyVlKGwU7cJSS3rh2v8S4fxN0Yung7/idAjgLTMe9Sz5PDGtV7V7LGF7WLC0twwxoBSdJXow0YtZejunWaFcbnACGjMjYdEwhrDVNtsq9lpsJjtLmqQAbdoNcTYlxXlKBmcgLAE8MSpfhqfVfhI0HQMV+uLJqrE4SuKqT2BVPj22uP9Gfd30Fu0HVXRrpUbgAPNEWtSzKOFiV78rK8LSpopeSoRhWFK0GTIkPRQ+0Iwreq/S62UIwiJXifLE8xWTpPAkDKkXgu6zyewJi7aD9pl2VWw/RDBaBrsCdsXW9MHdaGPhyGcoLICOzdCmp1moDAgfq8fAafqMMSP0J2/vo38Y7qR/N6uVXkdDIy2YStZW5+i7KtpujC3uch7rcXe35sHwFpuozPTgaCvhoLwjO1KHwndgj5kZ/CM3in03m8OdEBYNT4r2aCIM7oC110mHGjwACv9bIn44cXBR1CVP9l1rce0L5PkKOFa8gJKMbAmrkhUk2e2BQCoQf0Z9pHUyfNaa8WiLqIoNE2lmLCwCFZYc2aTjxunoC0b15hgWW6oRvVP/Ql29fIo+aOh4fdhV4/E5Qe8zuEBvn19cx3qVHMDwlzSzSibE4ORXpPRYkUuFX1YfaUHTzXmn5Q77g/QP4f80BOSPxeMr2nPyqgGxTqj9F+Vx8FMhdkV7WgyFVmRJWLToabWTtuRjpaUtjrH8MJHSbJiwCEbPtQgFSyMAN0ZQydEk0nKFy5JFCoW/dam8mwRShHWUyw0kLFVbaYZR79NQWHs8hXYvkiBOcWg/BzeDTg/ranEYII7s9ViPWO0aSyGsSjZBpNlgYRGGzGiLgu1KFPAYkvwVp9fDmlpYxlBIjR4P2878d58uwjKFVQQkMifQLJKWNIKREbB5Oul+qDd72DYrzIawqlnUZmcsH+zA57YGkraMBoo0GyUsf+lgWeh4BRw7krACnM4QZVdYlH4oPE3kR2Fi4hLO/FCcsahpbL9kGlf0kqX5EMwmeT/EraZDny1hzWVDYGuutOP7fvhYUyCEYAPpRzxRf40TlnW6fOx5EA01Vt5JAk0vLAxlmCjYwvnvHZ3qZNCyiKI9acajFXSa8RHU8DVI501cB5Ge0wKwommJuPQgybjZEtZMdhZs11tEQPuBS2Mac52hQkB0CIEWTO+FYO6F/X34NNulccJS+M8ShTvGpIYOaXnyThLIhrCEA8+XmOGK2GROf+KSVs+te4q0jxff+xR7hPHenu9zfH8yiJ4yHpd82d5yNpot572GNYftQ6B1wfMg+GisgnWUZiZg3xYioRV4ay93EMPgKGnSGGHRyjCetETB3ekv3cxyizfDJ6LKdbZpOFdhRpdo/DiyISxC8ma80WNWixllXCwEMYwhPfGGUXztC1S0LbZeiY5bi/+qiIfDqc8VR7BpaPcZ2zf8dTOcVt/jvWSWhEWAKC6mcJu9cYrhfQiiABRDHWwm49pafCaWGYz9wudJcDK5RgiLnE2Vv5wonAsDYZ31LLxCNMAlhdNZn5KFrHfJ0QlMwexJ0XLlndiRLWFRYwe1a2GH3kra0fCkaB+Cv8bvctRHGa6hZ+Of4FpidifeaoqaT7EJsdUkbQyuZiFeg7gzEfZHMLEvqWrzxMNMyKKwCGj4UbDZbo0j45Fw9glimEwJp9f3Kplt96ARwhL7Zyi8WSnOJGFdBGHFQfEw+2ndN1oL34X+IGSXrRHq50HwA5DE4ryWlCKspnyZghY7w0MQThvj8UYn0oY0vRNA5bBOZug3PQRj7fuAEkbPthq0x7HXB8IgnPgwSBDCsr5Mwdc2pbDQ4+Qgzs3gV2CKgJIJGxo61yGeIpMw0XBhUcMq2m8tFeDMZGFJ+HoXHxL/g0ULhGqEozdYjvQgmsg2xIOAaMFQNN5eVNwGhGEKHrmNKTNd960ExLuItO0imcl/P4gG5tss8Z5xFpaEqnUFF8LuC3xaRREnhBaGoPgCx+MyVuSV0+G9pcjf/i88RGO7Z1lKGoawXjXvV9XexRDsLqxqNpca32Q120xHY2SwKzAshmC/BILYHRdGMoVI6Z2HGna+jGaDOCxYxb40865iB2i4lcEuUPgsW0U4MRjWc3JLxssYrCv8Il+vkldwHTMkLjNAT0AzKHrq6IxSHr8EldpXOOdU8fQXSMbGs3MvZQVt/Aa4ajJ3hjneu4L8olDYn4hHs680q+u0Ym/4XWNRDw+BtDq/UnynJYW+hR2FTSag/GkDWg2XGw+Q9izK/oCoA8cNd9QXHfqL329+CXoAucblANG4lUy10K9PZxkdoIRgWsKe3lWkk6R/AN8jQlQr8HknRNJFX8FSe2MJygc2feJ5U68We4SlmVEbw4KzoCxsTk67LHiHgRXP5Bj+1cKMK97DSQYaLuyLeO7sXfIt61X8rQ89GJ5E7/8YPKSBMRuyOrL1U8EUm15E8OChXtAREusx2XpJLxfwkvr8AQ8eEqCD/gpNm52Ofkgq/GvM+GifLL0D7sGDif4zz4aAHobAvgHpFTH609rvIajd+P46vvf1eioPjYe/tJuxQs3HQVCjWag05Dxl9uDBgwcPHo5/MPZ/tTFbrDAsHEgAAAAASUVORK5CYII='/> | |
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||