From e9d813b189322f9c49688ba068635e010a4c45ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=A1=D0=B2=D0=B5=D0=BA=D1=80=D0=BE=D0=B2=D0=B8=D0=BD?= Date: Wed, 7 May 2025 21:24:21 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D0=B8?= =?UTF-8?q?=D0=BB=D0=B8=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA?= =?UTF-8?q?=D1=83=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + README.md | 1 + git-bash.exe.lnk | Bin 0 -> 1339 bytes lab3.html | 164 +++++++++++++++++++++++++++++++++++++++++++++++ ~$дание 3.docx | Bin 0 -> 162 bytes задание 3.docx | Bin 0 -> 22748 bytes 6 files changed, 166 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 git-bash.exe.lnk create mode 100644 lab3.html create mode 100644 ~$дание 3.docx create mode 100644 задание 3.docx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ + diff --git a/git-bash.exe.lnk b/git-bash.exe.lnk new file mode 100644 index 0000000000000000000000000000000000000000..7012407532cc9f6fd3ac33dac88f3596c93ed757 GIT binary patch literal 1339 zcmcgrUr3Wt6hE^oXy)3=LQQiNg<_lA%v`hON^wi9%|8z@KEgRax9P@Yo3J8_2*PTX z5mG^gg!Vm@fk8=7X%9hvuy~*k zpwbbr5U7FKSPe5U3)3?P(@;ILLNl|2%mk@t0@Xt91}w1Dz@wV>p>t5bu^S*|Xm_?R z=%2lBpz}8AYhvSgq-Wb8?A@Gk8BhbP4xyp)e@?Z6rcWhkPF)v^6- z4@#CQ9L(}hO0HPBSb2zCodh`HyS<)r%jlf?(Hoj|yemvxfqg4?;E}Ds|F~Y^k7Xg+ z3m%;8)aGF0 + + + + + + lab3 + + + + +

Работа с сетевыми соединениями в Python

+

Цели и задачи

+

Цель данного занятия — ознакомить студентов с основами работы с сетевыми соединениями в Python, а также научить их анализировать сетевой трафик с помощью Wireshark. В рамках занятия студенты изучат:

+
    +
  • Принципы работы сетевых протоколов TCP и UDP.
  • +
  • Реализацию клиент-серверного взаимодействия на Python.
  • +
  • Основы анализа сетевого трафика.
  • +
  • Работа с HTTP-запросами через socket и requests.
  • +
  • Взаимодействие с сервисом по протоколу HTTP.
  • +
+

Подготовительный этап

+

Работу следует выполнять в среде Visual Studio Code, используя установленное расширение для Python. Перед началом необходимо:

+
    +
  1. Создать и активировать виртуальное окружение с помощью venv или conda.
  2. +
  3. Установить библиотеку requests для работы с HTTP-запросами.
  4. +
  5. Инициализировать Git-репозиторий, добавить .gitignore и README.md.
  6. +
  7. Закоммитить изменения. Не выполнять push.
  8. +
+

Создание простых программ для клиент-серверного взаимодействия и анализ сетевого трафика в Wireshark

+

Необходимо реализовать две программы: сервер и клиент. Они должны обмениваться данными по протоколам TCP и UDP. В первом случае клиент отправляет строку, а сервер её модифицирует и возвращает обратно.

+

Пример TCP-сервера:

+
import socket
+
+server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+server.bind(("0.0.0.0", 10000))
+server.listen(1)
+print("TCP сервер запущен")
+
+while True:
+
+    conn, addr = server.accept()
+    print(f"Подключение от {addr}")
+
+    data = conn.recv(1024)
+    if not data:
+        break
+    conn.sendall(data.upper())
+
+    conn.close()
+
+    if data.upper() == b'EXIT':
+        break
+
+
+

Пример TCP-клиента:

+
import socket
+
+client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+client.connect(('127.0.0.1', 10000))
+client.sendall(b'hello server')
+data = client.recv(1024)
+print(f"Ответ от сервера: {data.decode()}")
+client.close()
+
+

Wireshark — это инструмент для анализа сетевого трафика, который позволяет просматривать отправленные и полученные пакеты. Важным аспектом работы с TCP является трёхстороннее рукопожатие (three-way handshake):

+
    +
  • Клиент отправляет SYN-пакет серверу.
  • +
  • Сервер отвечает SYN-ACK.
  • +
  • Клиент отправляет ACK, устанавливая соединение.
  • +
+

Задание:

+
    +
  1. Запустите Wireshark и начните захват трафика. Вам очень поможет фитльр tcp.port==10000 || udp.port==10001.
  2. +
  3. Запустите сервер и клиент, зафиксируйте обмен пакетами.
  4. +
  5. Остановите захват и найдите последовательность SYN, SYN-ACK, ACK.
  6. +
  7. Обратите внимание на Sequence Number, Sequence Number (raw), Acknowledgment Number, Acknowledgment Number (raw), Flags. Эти параметры определяют порядок передачи данных и подтверждения приёма.
  8. +
  9. Зафиксируйте последовательность завершения соединения (FIN), которая включает обмен FIN- и ACK-пакетами.
  10. +
  11. Измените TCP-клиент так, чтобы TCP-сервер завершил работу.
  12. +
+

Пример UDP-сервера:

+
import socket
+
+server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+server.bind(('0.0.0.0', 10001))
+print("UDP сервер запущен")
+
+while True:
+    data, addr = server.recvfrom(1024)
+    print(f"Сообщение от {addr}: {data.decode()}")
+    server.sendto(data.upper(), addr)
+
+

Пример UDP-клиента:

+
import socket
+
+client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+client.sendto(b'hello server', ('127.0.0.1', 10001))
+data, _ = client.recvfrom(1024)
+print(f"Ответ от сервера: {data.decode()}")
+client.close()
+
+

Задание:

+
    +
  1. Запустите Wireshark и начните захват трафика.
  2. +
  3. Запустите сервер и клиент, зафиксируйте обмен пакетами.
  4. +
  5. Проанализируйте разницу в передаче данных между TCP и UDP, сравнив структуру пакетов в Wireshark.
  6. +
  7. Модифицируйте серверную программу, чтобы изменять входящие данные перед отправкой клиенту. Измените порты для сервера и клиента.
  8. +
+

Подключение к веб-серверу и работа с HTTP-запросами

+

Создайте TCP-клиент, который устанавливает соединение с vyatsu.ru по порту 80 и отправляет HTTP-запрос:

+
import socket
+
+client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+client.connect(('vyatsu.ru', 80))
+request = "GET / HTTP/1.1\r\nHost: vyatsu.ru\r\n\r\n"
+client.sendall(request.encode())
+response = client.recv(4096)
+print(response.decode())
+client.close()
+
+

Задание:

+
    +
  1. Запустите Wireshark, выполните запрос и проанализируйте трафик (фильтр tcp.port==80 оставит интересующие нас пакеты видимыми). Определите используемые протоколы. Поясните ответ от сервера.
  2. +
  3. Повторите запрос с использованием requests:
  4. +
+
import requests
+
+response = requests.get("http://vyatsu.ru")
+print(response.text[:500])
+
+
    +
  1. Сравните полученные данные с анализом Wireshark и измените код первого примера так, чтобы он выглядел как захваченный трафик при использовании requests.
  2. +
+

Работа с API Gitea

+

Задание:

+
    +
  1. Сгенерируйте API-токен в Gitea (https://git.vyatsu.ru/user/settings/applications) с правами только на чтение.
  2. +
  3. Важно! Токен не должен попадать в коммиты. Добавьте его в .gitignore и используйте переменные окружения.
  4. +
  5. Выполните запрос к API Gitea:
  6. +
+
import requests
+
+TOKEN = "ВАШ_ТОКЕН"
+headers = {"Authorization": f"token {TOKEN}"}
+response = requests.get("https://git.vyatsu.ru/api/v1/user", headers=headers)
+print(response.json())
+
+
    +
  1. Выпустите новый токен с правами на запись и, например, создайте репозиторий, issue или комментарий. У каждого студента должно быть свой вариант.
  2. +
  3. Закоммитьте весь написанный код и выполните git push из среды Visual Studio Code.
  4. +
+

Критерии успешного выполнения

+
    +
  • Все программы корректно работают и взаимодействуют друг с другом.
  • +
  • В Wireshark зафиксированы последовательности TCP Handshake и завершения соединения.
  • +
  • Анализ трафика выполнен, найдены отличия между socket и requests.
  • +
  • API-токен не попал в коммиты.
  • +
  • Программа взаимодействия с Gitea Vyatsu.ru написана, отлажена и работает.
  • +
  • Все изменения зафиксированы в git и запушены в удалённый репозиторий на https://git.vyatsu.ru/. В названии репозитория упомянуть, что это третья работа.
  • +
+
+ + + diff --git a/~$дание 3.docx b/~$дание 3.docx new file mode 100644 index 0000000000000000000000000000000000000000..9b00fbe13fd4fc0895520a7551cdb4d12d7d136e GIT binary patch literal 162 zcmZR-_~7l+@2?&(kObHn6j=;dY*|cM+*z!EECz;_DWXga3{p^2VDy~`RAYfkzyKz` i_1r9ts{OYa^TpP$GwfqvIH@KWT?6F9bor%~J_i7h{}?R* literal 0 HcmV?d00001 diff --git a/задание 3.docx b/задание 3.docx new file mode 100644 index 0000000000000000000000000000000000000000..4c1f32c8013967aafc195a140b2ea9d464406c9e GIT binary patch literal 22748 zcmeFXbyO$6lPC%dI=H*T;O_1YgS*4v?(XjHE+5?8-Q67qcX#LV{q5cNcF*oT@4UbF zc22sJE=eV+>PjaiC-nmq1qd7n5(o&05Qs6(M%5S?2nYZM1cVF(38E=vW9?{U?Wn8d zW^3f2P3vl9Nstc;LY@l*@{Rw0um8a#(2zK8-cOGp@)YzLFx#{u*+vc+7|o9{!Zv*c z4rl%?{2*A+@!7S<&Hx}`U>+SJnBMT1hGYnsT}!uwLTq#)JwxY7_Dj$)W20JK-ly^T zgZXPGk$y{Hl-1XgxuX+PniZIyxUoNeQt_v3WBCcL0`1m^Xd z&Xu3k6;exL@mc^Z1f5)1ki_a)x;GmMB23+Rt64?86`p zU94qhRVrqzr+pIpY0goIDCpqlG+YGr)-Za;k(s+TZ(@<4s(@=8E``;4@9)e}x+k~< zD95rwOZ~zHV$J9P~6sR0A+xn*7pQtYXiho$W z6X=XbDfzML+5RVl?_0CJzJ377{U`Ipi^FQZ`iA`ewm#@@^VGFBvUH%M{pbFF&GLV+ zE&hkDSH$;znVWDj8zCoO$lk_^%e8w&kydE6%g$ceX;Sm z`GgsFhfGnY?L_TstYl@_@J^_u7oC31w+>gJq@WG}gX@y*E={3fK!iGK z_%s%H+;eE^WDoKIrSRiHF|-*G#q@$9Nqs@Ko$~Tisy9<^8pGm}xwxhWL>Z4rS1@kd z6sGr2W4_uHCYsoozO6d#0j1M~7RD%ZiU(>eOL{ue%s7LJpIFx&v#0I_-Nl1pLDW!r zP+@d$p2k{88lOkuhnReq=&RgWl>r^32sU3)ajb{jth1$_E!Rq#~rAn)iaUCe-2EZ0y@{(xh++mWj&A|HOAeq6g1ZS^Wx=bVPH zPTE^DuhfaKxnoc!#xByb*kJEPz9|PMwyZg=6{AmKOJ6LRDqAI=gofU9HYDx*eBX9= zy-(VIy*IQKQA%m2>CWoJ@j_YVvU9f540awp@TOD)T})n=&zi4YJ+4^R_;FHWH#hs7 za<)pqrYq)~f&Fmap-DqDYF>?G<;@7&4{U_Tm(?ESe!E|dA6J4@4tQTg z*Ne#AaT6wxS*f27Q(NhP~Y3p3SswzcO zE8a#)g|?C<{o>X@Idn$(%t-6G5!?XVgwf+UK5_YD=$rr@g*_vUU=?K0Ui*E6+|Y zzBZl9+08RsibKeNqLy{PSg~@|HQOQCq6NQ8S*b19yBz?!TKjTnGRTO%F-vO}E+eX? zf11LDl7;td*&JJ5%#E)Npk-#Ah;94OHh(PrSu}^qM-8qkKI>W}^ziDSXGW{Gi`A#prnWlbS3*>VizpZPup; z3@L?k>}&HSps(AluiIzEW5{REpu{Iecd2`vkM(6xi}%Lisnv8hKN7mJ-JrzEyA8p} zg;9OE+ec8nxzIPYgY5FFrMaM|;GPY5Y**lUm@M2iCwwTTkt><+lMQhlE9|Jxu>51zb$2iI%FgiyjynfVKv)k?2kZ6EW(n{@ zCDLxn!5}CT>t*N7QUD|JJW=qzmaL|=3Y0E^IdQ8go_pm~`CS=V&t+7-Lf$ze zWb;w7!{cr1$>@l7v`sWAk8|vm@NNp;PVZT>Vx;UxxQ*5AlaT zmADn#_H%&$q0aI&V5=8si-$6c)LU|`u+j2c;g9H+N%2=wJmWSkeS%s&7{0u)20^E2 z%~z9N)AUaEu4rbN?KU2LeIy!T^iJSFS~3Td?E4UYIW?X#P6XBwUkm47%hW$5=fGQ{ zv5fOJwgc4H%f5;Bz|?R#Xv^I4Z^jL_h-y#o?;Xb8`J##U{qxMq=tlX~ff=pRutlgn zf`}{*C8bsk=@)7e$=jp|1CBHeEFK!O0L9SUQO6}qt)(S5 zdB6u+>Zklmx62=TKzpz#O!yGEfjNreg9ceNR)jFP@Pc#N&T$C@qA*nGulB-9=SoC6 zT7GFWP$j01I=7_}uA;j;aI$EEi6asK^liq+G$EE-deOB_`40!kPs6kcmYU1}%5?Ug)m$k||%Pm$s1U_N2TL_p^G= zk~ulizLAoMJq%x|N-1BZgZu#eh1bR3aiK$OdM?dx!EU2-X|VMT$4K_$7s|y2YuIx|5r$QY2?8PrT!b$n3%%e_>9N(nv8=I)mbIf=-H=wY z);z`BkSyY~*27>8FJUWsrl_Tl?o5)Nml<=MP6rtj)`qgf3et=;KvE#t(c&5{r+7|Ad=y=u6G<0_A4e~<|Y$}TJLPaK}rGVSAL zWHgcGd>U}%UJ(ufm>fc)l#fm$C$DE|4LDmPc-Mes`HC>*c#(^J5K-{0{gpn=6TFyd z;J&VPzoHSyQgCq2CpHbtm+fo$!$9m*Iy`{hQ>D*Ltzh! zi}x>U-J=uny1*^5gF#h$(amq5N@VjU#~S6Y2Ps)?V_V7wI<>qO!&1@<8morTtY^rw z36^0<(0$-TG)m9A{^&AIttZAhyru|#ZRDRE&S#`PSJRAKUYB?LRC#Ht)3H|KsId_) zu(z>}rK!IZvs%ncl(t|IXfx%L(uIq7?3Mw2_;eJmJe(&at@^xsyBpm(3Q_PW6nFNi zC+U4FJLH%!nqLcw?%-SR__FFc=Dg;8r!;TLA?o70a^*{t-AdW9-CXwkTNB$K*FRn5 zoTCY+JNEP@{oXSm;0ZM5t=j;%If+H~;9RKW&96N}M$SF#**wG5p$ z^qu%%xm%@e@tu%}7^n0=LAJ3t=`^?}$I8MCXRG?GzA+IM zb+f&YvkxnK(h+OIa|BMG6E)S_p~dP(Up*sycS~`WU&ix8p+Yb;`eBz6GWhC`Rm-6J z2zv3*p00vIvyTMFVpsPLs9cDth6s?H^h8T4#=Q^#t)P_*|L*r-;!>j91pk&+E-QuCpttqItpqOP6{ zZ>kFF?4WV#0?p6(^Ln5gE_QsTsiQbDGBPZD(s z6E^XXblUpLjTcv$(k85}>FQ0b>2%Vn{Y7Ydm9qHWkFWY5@%NoE1r(x@+-4El(jyNs zkt7JqFio*=s96YaZyQw*p($h5B0Xf9u>lqB{z9T+f;;grW$}Kuhe%a=ynaiSEQLS= z;o9x@FUb9*SA9`e56=6&r$gcJ!HwjX|O?r$EcZ-JnPpm4cc*viobaT3dmn3z-3ge$nFuW zLYuhP7(HXE0jYf| zd>Ecz`o)l%9}}1RdgVE_f_+s*rL>1M<9nvG%=&nk!`2UmsfnDFhs+bm$1JK6s$Q$j2#in*&*id#}^aCoK;gae=GI=j~c8>&o*x_#B-^ZnJ zUd&=3>4BSerVG`#m`b*QyAR?z;ayhoB&{)HvC9ru(^)IkaQr=+1U_};w4)3$PP@OH zQMTQRKfoaNQp^Gdx1P+hnma!a#m%sKi6v5oAtdB0tgMCkADSROrbXC#2*pU88Wp@T zFOorIKy#u?d_RpPFsYJ>$Lu!|dC=#h;|uhI``v}792pvY8RzGV2Waa-UKjU|px)C< z>w8A=dE#FE3G2f3%%&Pal74bjx&Mt?&;dE=$S7|nSxcq7(r$Nt@oclBI}xL#M#2mb zZZ6r;S36dc(h@)RAp+GWGJ!|`z&dl}YPEt68O^KN zP@+~AAA=cfT+CtZ6QCH4mOaQr3!BsQ-@$eURsJF z7)t9QKdL6v`dI%!Obl3`6YYcD9R$ATnEDfPijG>Y&8 zd?oFznABhy=L>s;d4!CxMCb`qk?3)`B4kK^eR~+{95?0{6L6|;&)l3mXuJ{_9L#oS zF(>+3*7ED43GcB)tC3Vqu?xN&v-5~})qFKvWRCItAq~6LlhsJxQ}FMdM?uy!&4V7* z$t6j$xU)#HZf!I*TICCR#s^)!k=00cd&c;JFN>LXlv?WQ-gNu&x>s@Geb?xd&^VrV zvk#kF&L?^&**l@j0BTJa%@!ouvcAZ>+ZQkX4&D365AWXX#U0RECXsh{Q>YG--iU#Q zG%V104F_SJOe>whgX@bw4E9LPP{HFrFn&)f3D{ieQ9ZAMW28%)OwyYkL$tI6bfn*!(?%!VSeVg-qoXhFwKUdsaEJDe zU&KOd8Oy=nINfhdRNC2*%Yh}l(^0jReU>Xl0b?NuITfLr#5QS8-dE0AdzCw%HTO5X z3N+C-%dyR8PBH)B$cct2vfMJ-xVpeyBW4k|nHmD^K9^4(?to33C0c}&J}A5;APJ0a zzTU^DL*je%h;t{~5Wu(~EKGxI)`7);I4PM=-`HJDe!85wOtu3~D?jn;2f8&;U#j}W zH?22yw`2-Z@9+|TYfTe9hO{EjVk|$&cec`Ndu2gypy4M~!g-gGT(2sk{PC#tV8KS? zGmc79!aq~^0!fQ5cQoHqvhvoN6-s4aY3AG+$;;wdRz{fiQgs#jgc)0;>#)Le zxU%*Yg7{|=>TL)ezRBGO*M2u*pe%SXZFsfo+^d!rB*P$q$1iNN17ZT4ij)-a1VJC^ z2d0k+F1jK?eR2^{iDYuHrctmO{Tv0C(a|5Zy{ghTz%5(p@u?(e8cMdK${VY%lLVTF zm(J9U=Rd&(+wj!IYw&QhI^&+q5apQgI$%JrXv*8|jb%H!mvq=z_Ld$2@Q3c7`NN5P z8mzR;Koa#mX=O4DJ} zv{};&G!j?ImH(#h7K@Zsi5-|PT-vt2-uTZ)EoWS;RSUNm>x;B@A+Xs9!yXtCy8F~$ zV?zZpXgjEx>II+(tA*Dr7g0tI!;e?4-O3R4g+fb7{+xzBDW1@1Ji*MH!lAacy+5Bs zUARryX&T)K?Aj0 zG`JX_ASroeBk`->5D`3>zN*Bmg`y5;Agv$h1{(6#d%2qqr2n0PAZVB3&lFh!PvD&t z67@jwbj?Mn$ZTwoaYm3{FK73DEG=WtFQ{Hrf8v2L!DLvHG5GL}>`f@_-*8PWUbziz zSx#yR$2=0@u9x?C4_8!t)lO{(ZT2jeDi$(>7AnM;KpALIGRCcnAoRxD(l@hU!e5D2 z)d>DJstcaT5gIvAW;qqX2ezrSrV{+)HNCyg#$9M^h!FDZU0!dymwNT;Rdr_{g+F(2 z30Jc1{`gm+{VfVJ_@En%W=AN{Gw@{r4q|d?fdwuaYg)k@o^~Zk*6T)plz8O|HNY$_ zdBKCivCwFrMQp2w+w}Cl%)`3TBZB^M>#gv1ON*XSbEANRcETMia80zi(@JG-->qt` z^kT}^Gb96ZR5*5KlGc(XXQN14>dQzoGg-=#FGe!W9`D09!Ns>=Z76+FjJGkrkmGM@ z52v>x^IqzETr>6FtD?{hAGxqc8d#o(x>5vOBiKTu1>gT*`w9?$1ql_*UcQ6E)L}F( zE4H9ilour0|0Ow6h&kNDi|TJzx06PBN&<1FX94Q*u5Qzu&zh5gE$IOmLR{)nS{&qB z;Iymv%8<3ay%mc;F!yZ7GlJKuDn#Z+9(Z+YvbRgU0;l5>W14PUHuXH*Q7F147=aW` zHGPPElF7vjPMm>KnyfvUxFQtJV z8vRra5Z~K3ZLhigQ;6`C+wd^%G!lnsEawMhT+%{|THnPP~^nXyIYI{Fmv$bUc@h`LtER$HcP>Ix!&1GBdF8aW^ z86!?wV)Wtzp(qCE6#nqLM3{iKjWjWTG*ld@fY=s1N!4Z zd~9wIA@g=HGQ+GTWn^wq84@n~NjOtRs6N+3|NBfnq$IbX(&f~5r@~n=(@l=yI@pmK z5HL^IN#qzD3P;{&dYUjO0ez5Tkak%JNec3y$~>BEsY+BL-}918)>fc#JdSP>BFI^A zuw%X7hhUD8ZUlj$M;o3i{h-~?N{-Y(?!QJ|h=P9dQyPs}!}lZ-jA(&y;+`V-Dx9bU zkux2DHF6t-s6@=ENF$9#6`orJ;4Hh+w=JX(Ec<1oMMo$Qp&%*Th>K1YfjWH4sy}f{ zZ=j1KSUOJa|MsmVrWnQs`oLG`V{>p? zKNJzUD9*NNa_jQ%p%TsINRI%ep=IB7?>d#AsHKC+OUDIGkGA->q(r;+upnNd@0l!% zT;(-FfznXoR&vo68g@P&tnEN%M|1erSa$zcaCyv2(eIfLmP)&ni(EnfHYa=S^<{=N zB@_V`gWxjM++s(2f9HHj&sG{Kikn*t)gABV+?tF^fB2d@IMN2{YuP;74KXX6+x>c9$28ADW(nbmulhv2F&x zApW~^Zor{u58L+%_%kRF5DpL|@W0Nv|1B8gKc05~dteCgcf8g&_W$gwBT+y$fF5P| z>X$dfTsun9Z$lMl`2^e!a(B9GU*nnhM~30%CyxH1U6OQ!m@Af#51$vd8a3;)v2|ak zG1Fc_K0UnSg+G$${+&ZH=*<%j8d4{i%ME(7{9?#x zfH(216APaR(3v4kIZ@POvn71m^#%s|s2Z@p=ISNh;k{hADyZZqSU$_;!&$C>)FBD1) zAxxiW9@EYBdGP$SM{H}zKH#-qF@5h6_Kpr!1^yanMRj5N>;9s?f3IM#csM2|CYvYr zqWJcWiG~XUbpbu+npIy9KR%c^1#cz**HM+-m!EcDxZmy}CqcJ6H3u58R*;o=dEQ5{ zwX{cX-;Cq%Y6@(#N|g%r@Rh|k)JUtjh}Xdj3+Tq0 zMaEOq$4=d+bM96WTqhvj*vu`a)4f@d^%^UYd0gtb=&bQnl*CQY{j4c^KSKA17wz#;y8O({;4b;BQs~HmKpa>?U z>2cHgph=Nno2Y(%UA%sv8n!fl)^1o6PWr(+xVM-fZ6GYEYrtG-AYr$E0SZOZoMe|5 zG}NggiT`%7W1HBq5pFbBZt7gyyWosF_*zk}12dXhBc9kF7eGSg9v(vyMy%jQ!nRxQ z@)l&mfwcq(KpT`xIA2#G%9PHa;z)K&TY>_*Vb?9Uz-c5cPq|G03XjzThslr<1!L0n z*ZSrqF~CTmwE~Oi5x4T_d-ZQ?iOar)%FW;sOj$9qtqkOPz>aYnJH7o%3;Y!i#a&0p zMgUO%6B4}!3}Z-Tf&-?0F6K!hgyK&_SwT|bCa9$Q3M@*s>4i<)zgf+@-uwrv4k9!i zlW9GUe}Ov&nK5vrsAE)+c#svdNmR_@96PVm55W(@))%4WAr4m7u>X+aq}*?UQZ;sx zRW%Q@ybPZ(+LzXuI(l#ea@A^o9@UeT3_8pNqyV8#IlVe&BKG8x(GA1uM)H-IILV+0 zt}<%?77y!9v($;oS5&Q(w|V$15cAU`i|Loq);oy);Yo42_BHKQCcs7Dq_4mGB#@H~C9V<%=u4}rviL#)2g`LU{8dV0X z(U12}bXHvU=%&~XDe9TKw!@C9m%qy_v|-xEis zJ3J1vb&RAP*0YT~oCY5(xvgSH0y89tkc0g?q|rjASC$_Z0N^}E;YL`CYwg#Kl9bS` ze!|A^I3rA|)KV;77;Kq&@0g?+`qU40Nv#Ao1;O*^ibCBo#$lM~xFZ3eMaA(SA!-ER zkZ?v7CY${EiJHCTWjtNQ`=^(0CLAA0PK;P^^12lm67BZ1@&;Kvq-svbYVlie;1GH# zk*hM~u*y|viNFx45v?o`sYd=>jk|(v>3AZ0u=4K0gke9}JLT&}x&6)_Gk+W7r=RRr zO?)~swRhRimD+5oLYIa~&uQ8Dm1xdq^KEUC=IAFKdIc!Qx1l>|dnKQ#Y$6qRBQP$^ z4Z@g**9K{Dnk#Vi`xDe}a5JlJBAR$%Q;Sx%5g0oaUD9;I6t{aY-g4Es<0AL6D8Enz z_dcFC8pT81A5*t)pz2N7_O~7-X8@X1t&cV|S~I9nrL3z|tkE1M?OWB3lcBAP4>nUo z5e3x9$t<4sV|*CXx-OUZq^jTh)la_GS21bG&)`W0>5EtnWL=(B%71VQPwWBN_Qz= z8{MlkZaa)i*D9Q(Cf^h_$FrupOb!=2mcIVmNJO4M&n({W)ma)0(El5W=wRgNXl8BV z@Q;&hP+hlPXGieT)%)t5x#Mh8tE)H9>RXlxchwxAcuYg0$bh8yNn$ii^Z3_AJS=(s zPehA|4z>BzMB0umJ8}2d^@zHSSYduXj>nG3_JepDwDkDo%A0-nxvo18Kt2o+nH19l zBEJJ(wfpPQJBKo#rKA*3E|K!!Wo6x58_-pKOS2=c9U7hpgeGWTxT9?C8NDy0{ov3` zRcI!Pxd_4c(?4%{F0@v4oY9KnHSrNruD3XpBu)?qS^ka8|W;Pzy5E$>Ae<94$m6ygS=<%?47s}=P=k1KJ*DF;Hv5T zP;gqfJNiR1t)CVhJTX&QaW zhdc->v(3;eq`K3#+G_7;3iq_ZJSHqCxMy zB^X-SMm5iV5KBRN%XG&}gz+s&D(W?8-=Y&e%L5fMXY=*i{l%xOBN1PYEn>4bmNghP zZOm8r>85DFe#qt^8sRT)%OCfPiX5MEaO?0TodAaTDe8SG{Qbw6?K=3ATr#|3UgP$1 zh&goYXJbOcaxWi^?z3&r7|mtijM$1WbP;R=2)Uf3>zBL0F#8gjge@p4Kw2lJpjj)tzB>g;nfrRhCYD`Sq3 zN=aD;%s9jLoS|*?bOt3Vm<>kP^O1C2mH23H~4W7Q^+sUFjkV6C6+h=e-zs%!vn@Wi8jCuLp!bE4_U>4T_ z`-tFBy-NKdjv@?V*R#mrvoop9YcRONl{v>)6XdG0m=kI?)!knME6L9;wW+O1isZu& zekPmjuLV$<@?ez({-b~(#}%%KAiHo8Z^I$u4Yb8wdn|~X5;Sbja@z(@B#D{`e63nT7`pn3~ucnlRkK&eB`2TKI{+YAc zeD%F5m$e51Li+brxwVs(fsy_9=jLBa@~qA10#=ORX{rajd~u!)-~iZPYpcrf5@nTT z%7D$XVHkGghIc4&#`*rvG#x=Y3!A*A7YSo=1Rsc!*WbaQ>vW$whIgJqf?GbGaPO;e zq^0OVPY#a7Qzq1oM9a`Qmq$L{n_UHW>glU_7H{$+mq&EeSw8RAcd}Qq5!VRZb%Cmx zc2V@&nFdGRUDI{0dE}+_CVp94VA%=6W)0()ndEZ$n^O*{_TfmXvr2_ys&+^m)H1D8 zYj82noOJt{N6zNf205;VgrTS=He{F{ycW4rM8dTw8t8NGkT;MlN-1+(Qkdb#$}*5o zNV}b76mi~?s{Tx`6lPAO^*Ql6s`(#@=EaI~e7yy!K^?Z}q<&d9&7%oOE2GUq@6pi1 z&WAkiT`8TmGK=I!mUQn+1!5h_0EA;}6EH<6qLi05%`)MqJ0T?6@W-pN$NaO14zJo$ z4f^g){g)l;ARZI%^dzeU)~$m{e4-bEB zZ}lsbf@H;urMbsg_onWuKOG$l5Lagm!8gwR(kYC zEl)|{%3pfy6$gX)3%NnTyO}1=o-H zKP;1Q4w$gmq^=d;#d{&$F9?*UUZ+IJaaJ(tJ~~gR-u9?_y8kQ~@Vg99 zIti>+HyIPVtm+#4i1bq)#nn?0PwEj+5qYbTY1Ayxcz3h?MqR$6>o$2uUxCvN?^p`ij&m52nniTBVG5 zTX{vVrcoHb?^{@Y3)U!;T~d(5ra>K?Z$ObXB~WJ<0fv-l zNX_?1CDCN(6&&i4)1y+z)VXD(PLya^Z1)Z%&}0V{4wSPAHJE=9f@rss5n@Pm@5Zy%ZLx+yk3qVmZ|nN5TwB4UM1DhVanU8Q`&ot{T?mq*p(CSq z(hUQ-Vljq;T8C^;$amlhTI~eN8MG`SZ6V@SWFe7M%PtXwrSq%tlHFW42}d-_uoc-@ zlPngm8$M*I`QgG7>YfrreOs?*xx?zlu~@ZvuWhHJ%zMNk5VMgaW} zNhxq0(SJZ=3D=*x%ety!>kBF$6dObR!a4*P6c{wC9}E)Y|4CS|{sa4$FapA4Wwje< zIZG$N0-BbV6Q~<-*o11n1pguB5^Y2ykW4*JA^b7rTs(2k2wBGUS81yyq57j#rQGiT z<{zG63?#4|@E_TOKvMQyKnfT;8-uvrv5JFgyG_xSj?{deLA z;%^d~M#1!JW&ATd;+odWe;PGZzT5dRed2%Q*jSI0J3%7%IEz%h2<(PFx6tQFImI0HdhQOU)>^$9|=SPl7x`QDu@I$ zK6Xq&T#x|D@4JZbPa(||32AJfxWkpb=6NZ) zM2X+@q>?BXVIFAOOllWU$e-lSr|e%FjbL_M{2n<5EB~T=-JG9pelw!1T>jBDuCC+_ zb{bsrZmwKeyuu&qqHJ?q+7ag{q~xvC`pcX!DaQgluUX`vdSnA33IC%sLL<;1a3T2m zprW0S(gv_7TxvuZ<d~3MGCLEVq_^{I~U53?AT71Br zkpIFeyU6$c-|m(k)n9(4AOHcG76Ac$`_F&dv~qBCvo!kGO8i_~%3;3=v8$N!%a5ga zzb5%GZ?=HC{eHsQ$c3i5;RaL4fVqKvATVZeY#7IWlu)^KKUH(8ilnMAQ_?%&5g!bw z7gJ8gc7=d>$r_+#0gL~EcwXHNj^*j~dGO}8-&r7mRrg%8{AJmGG`nIVfT4^3xTTZD zw|?ekCc5h@OkEVx$(8=t^}c(=_xAosFnLLo?v6w78~*T9-zM28BA~KzA!n9Dg3k~d z>n=($c|u|cJ>jg9L&ExYkSS*podlXpAH~>3GvMOFPPUiCN^Zpw>-9eILev z=>Vd7=2V}EM*e1#K)aDdjd-f;d}7W$H|6yqNn{HB2O>~m=_US%C&gUW=QL z=4ZMXl`k$%4-inK*DGE~Z83dQ3m_U9oIUdfi42Arr+vs2NFdrD17_Sgl&?>#UowC? zb!S^Lx+#!mbR@E{o^qGDk1(2ffT)M)@b7Ud%27iW>Gr0UE&CI^j@B?WVL~YJP078h zo*RKJk_?Md;{6VvoJxy|n`T}N>Mr@N^u?sZ5$%e&YeT2uR0Yn>9q`S#0NSF6q zwIuImty(PyA}nQf^tk6Xt(5)gt&T-(mz9E>`sNga#X$Vi8nJkj6tTG)KF-iSi}(Ym zX+r}EB9s$asNc^o^H1u(iE8hX?WJ#29hP@@;w=ySpYtqH(u@;L8b4h%8wh@iAmN^$ zr$F1-_mYk>6~Pe!hj&Y@(DY!)I&(j0qhY4n0OnJ;mrQNbZeT-r+^D;5FCrpH{y-tkNq61GPxT+^Bh09+Gh_z=e;AAIHB-QBzA(uWRgxwUY%Fn?J=EvYsvu1=F9X2mS~KoVxe_+vmuC~>X3PrUcGj(5sI zU|FB?7s%k6nkYhG*_`sXXK>DJ6~U3{Eea2AJX0>RnxEi_s7akmF%-~ z%h_E!?&Yhabx1p}$NKlHCD#pul7r4|#)$eU$_&QjLF$5RjC*HMVus;()K+Zn*^}9U zQ3+083dW4nP_BX(VcO~#1PX<>Pj2L(g5jbq<_)~Wdz>LCDFx`Jj*ua0TM3q@YD{t1opr;GNhqj)q%Ti15ysC5$W4dk z)LhCK4yb#(Vis+Bk@9!!afg=>S1el#N*g#;!;(lp&GGj+R>OQ3`uO)Ik|I#jiDfC6 z#o!c8qu*5qimAH4E8hQ9ie}p0E+{96(sm!@#kxN>HYElISQ4i$T41UTIjGh#B_`9{ z(MbrGq0}e18OpWc%X63>*@vlH?y9uz&7??F_uMgw3~0F`?=Imgb6b&?k*4E1l3k-g zn+DEkYgIi{sliRBHy4;vUP#JOD}~KT*QAgR27Q~_*Tk22`cy#J;S(0pU{3XMg|96b zGEp7dMm)<^oNZQqmbX{n8Iu-ID#pTTP|&utN%T)&p)v0mt;(1bI-rT1Cxc%i(A5W` z))q;56Hu6uzSO@Mh|b9^Nuq{6YJ0go1wDmRbLPy52=}eP+L%m#e;>GAh(nK5t99H} zEeXe@cQDv|hpER`HZY6Qq234C9B-xAV7YfiY(0;TEn{$G;3aAjW(3F-32J)~k?@U! z?T!oKlU%!tT#!ZMdtlc@1S8($8BZZ^;wR7tbNl_8Ty;7QUWR*3#dkk~N%B(B?Mch1 z$n@44^wVX#0NzhZPw8&Ijf1-c19d<(LHd3rL9c4Z%KdQcI0n&s*@gi-r#xX6d&!y3UT_B{ zC2oHNc}tzYJkSej=I0z&Q|gKoJUA$`0Y@;1TkdXk?dZ<#{nV89Q`HVC6YHw9?2SGpXJGj3gA@?VP-ic(gV98YM_SG)f%boxq`ol(+oO{|5NaO(Id!HzQFB3;e6Ce`u4?p}8Rcf77M!Dr)C5ZyNs{o_5E&TCwpt zkz_fI`Xq0LW3hx+ZW@bR{8SG#9J20MgMbgI+cJef`kfy;N@3n_vw(8aMvCDSonBXM4b|2wuQ->~Mr|Xx zvx!J=EypVK&B%BXfwP4I-y)bRTYL(>(naIdtfQkFg@8Gz zAh^at)byv+h;mwV9{pOpv8d^IHfA18lrbnujwl9qtuZ-szcD#iS>8mA(mM2Fq%Q!A zNKGDA@4PfvZb?b#8=`M8pa6^b4J9*S@<&|+8p<|@G?HNntSi8BHc~4i1W7gz^#!yU zhFAvH7GnvjE5hcTmjnlJQ7<9@OR)&|d=pocfYU#IGqWfoOvGKxl@wL{hoKPYH%f1~ zIgp|3H@6}zK^A!$6M0Id0*s{zy8!x0gk?gD;FkRgObsQe^hTq`LP9kaso3&(2d&1! zg#Tkl>=qSp7as*#i1kW`l%+(=zU#z`E#{?h=30$^im+5^7UiSLlTS;UWT%Wlss4}P zZ(1iMm-E=DZ^8G<0RQlbPy1$}B*s#uQC9Hpd?NoH_^(DrrT-J~wB)}?a37u#2&V(= z#6c!;*y^FX;SfK?IQMZ7XtNhsMC~s2WBQ`BOE~Lb$?D)v6-3iJJoYNbE+>pF*CK`r zY!F)yHFx6%OpNFjS|uMb`_(q})i%kpyiGw9M|!P-V+^So-c}XAA$|tAZ+f3<2e>r} z#lr9gZ{UadZ6a#pnU|=dRcEXgv8jHPota1o27@Rdw#x(SLS)}+@OUwf9r2* z+pl>g+R83XR>Z6CeF_e0UacZt!=_@azVK$oPET~2n8FhIVbk|eoR_8@Vta$VG!3#Q z)h=SyS}iZJ-xa(%-eObelsZjko(){d8{=7kzSbB(mumT-3>nVxa|gegmvdD|YK4z; zm0GbE0vsyg55qw6;q-6567rq21NxI6afvTZKPjlz#^aubrQ2cNic`QW!)UvjHN^f`JLlomM83uG zupsCHQWb$fD3RWK69hqeFQF(3hyv0C>7l4-5CWk{4NX|-y#}cPAxf1dNG}3{bfpvW zvip1w%%w zlLG_jF5b7d9jM6HbQdbv*77vouZqfWroBY64HCAcQLJ6j-cTccw#VmsuuI3JR;p1h zZI$E``PD=fTb%Sg)(r_Q3p9etpdB*aGkSBjm{p6m+ln8x=h6>ngSa4VnrYi>t1OKZ zVtiPI1=l)yc?D-H(9K0`#zu29?g$&af$PCxBXLLl-vXcu!TT$qZ=Oc7%%%ETC7Rb4 zUv1+)pm%>zTJ}q~4CbO7#)F}U&fdv654#r2E+KCyAf2ZAt|667^NYj>?OTfk#k0-2 z;hWugjHukU?wqBPF|o42@Fy$^#7<(XgZ(e$GZ0n>Q21V5O5!0;)>L5i^e1e6@kDck zPjd>Ve-=A#P!?Jm-?q1T5pr!von`}Zi(MKO+#G+jx3vzj4$9hU%1`F{t(2U>%`DH$ zuH3svf=(1avK3%tP^odZAP<$!ne!5b48L%Z!zl40R+ zUdMOkhNS8ZwOc%;BVmPtb6yUe!@Ai;30q}yn!YZ~4c$dAcbUQsSw8!}mG;G5d@>SJ zI9=($2EC1Oiy}u79nQ%_2S-Fa_Go@Z_Vn<#Z68}XRyo5$8a*6meVo&Y`RyFP(iZUgOWERZSQJb03OKRs3H zxc_J~K+tg>CeSg^0Po|@wYi~!ydv4)PsJgW9S=!0V01A8-tgm0i{p`FCzoy_YOCBn zk&{OpwAdBGQry$|gcC<5o*Q_LZh7Or9v97(If3xa(D68g*Ro!+DKb7WpfGf(os4Kx zxyR1LyVpDzM%pVqzm`^+M)&-h71JTjRW%_)8t{Gl{W%Hv{-?^5<%4C%#)!^4%M5ta zpMMbE0PQZz?&3R*xA0Fm=>PK!!^hs%_)JT2H69&>6rp~x5r25`{T^jBmxMC1h`zX{ zz{J$FJ`iAsyj#4cTtgQdco_8r{KvA*@|#5Kq^%^JU56d=2=>gZ-`boTU8EtWsR5=S z7V7a<3sO{?6x8^lAeqW1VyhO_8Ux!o^4Zg!3Y&v%vQ9syF@kqVTE%o8$sz18e6RD7 z*99r`67EXw$W)D+8y{5^Ze01A;%}jG6)T#~rFqjI9!P$!(@1RVymRjJtzyL*6?PhU z;k`Azszt#nQh`!Iky+rUY*WmjNs2gE+GI%8z01H?K~LL%Fjn)t%GLbl=tb0xABxHUE)VDd24Oz*0zZ(YHf!Gp%+wo(EyIji(If{U3#g@GnTdS$M<0#!`Bw@a z+U9rAJRr8MMbnohvKzy#sty=^hhD={7BXr{1qA71-61zo7yBUEg`@$U-N`1 zUQ>7X;ZMFnbrbbdH+5OPRTH=(9w!UNc{c%qpw3IX^bq!|kHY4bu^d{#;ap2!ed>x& zsDoY{N}-50lyR3a3Q`lKeRm{C-B_Ly?=el0>**$c4J7@2vm#TTibaJ|j5$}JM2so7 zx~&tVF|Xa97BCrwsJxdfuw=2@%z`UmNpnG57_xRc;7f0D6_C&y-F;}n>(CU49a<*C zz1tDSXTjeETINafL@s!DsGSRET0!^mCT=D+w$Ao{wt^<&Z@Z0&(7)K=UQ<%76Fy*r z(qAfwtQm0iF83a*egw1~2E`zFH#dA%NzQ9q#Wn!`)HuR|=gCYQJ6TMI~XV!Jb(Ao$D$hD?Yg`b>gkv~aOj!OGsp#?pW zU@}rdp%-6h80HHaZ9CN4b59W_?R=fLQzRf zhs}_m$L}23*e>mu8L~kvMGP<`pw<%?TFA-uL5}T1et#yp{B==XHP+|LnyUdusetUD zkSgLU#x>tCNmB6h;^V;dy?HnSm|iQ>4ACKvcJpT+n04>kg9)za>=u z2iPE;j=Ud{R2{ZMN|&Non_QIPn9b=fJjtXbcT{0E79D?`cD)lIZ8n2mkNP&xG;J>r z@~M$XQ$byPTjQYTT9(GkLGuHZ$S(+O;Lsx0cK`Z3^Uyam1MDsDPm3sLX^#`}pmWru z5W(be=XjymVk5BZPF3In);!dk1@;pa3LmBw_L+yk(H6d&dY;d{z-XmEzH5vniz^@u z`jXStV?P0pd-9|*?cUKPQamknW`=%`Z(a-=m!0MyDNiKP)C-~dRi1)@xPb6g$k4#-!y7{S#GT-yQb!GO9e8Qb| zHK}7}>*E%@6$yVUGxr4lN@xO0F4h1u6B~w1qxHDC{d7$y zz-vftp**_1SJaB|3b zmh0J%pn;c+7(eQuBRau6ZOZbWz>lxnhe~z42iWOKN7JrZs*KL@8S{!tnLZS_Fc~X3 zQ?fKULr-Dzj{4Sl`3ljj?AZRBct;@Kb8uS?wsSTTySG6Z=EQu%4AQUSmF{)+D7UIr z2}%7xEK(*d)gkw^hITjR5eI`=$HNyH+KYHHW$sCcOn|9j`}AWP8%<45Qk?2Eopmlz z$L0Hq`ZaCngANgN4-Vyo%io$%1d_uPjCHJ(`75sw>t0Iiu(p5WCTK3lKGwZ9St3(5 z-u78@Nwr)Poz76oxgM_?_X1-GnI!UD4SVX8>9x=(-DuToFtPLYS=58(*#QvgGn*N| z47F#)SZ*7C=b4NS!x^vf4oiccJgmEG*x3T(_oXQUUJAnsvx(O-OO*W`T9an=x+;!cj4CSfG+p zGfByA+6V6|S>E39iIp6EAGLC;T+9x%y#gw_E0aP^TV)~&k3&S8=P>G$)$p^?8}HY2F9$w~Kt?R*BI7n##@^{g*rMGtKJuAx2Z6iEI=XHj z3g>%Nj4;#=qv=4f-{sv@RZd2IQj$ILiKVg(>cBd0IPP&|5is{fzL+binA3-#=bvezl>TODr6s zYm6F6pihl&c@b81uAgLf{C!siL?)*!rgbI-I8!Y`^8^bh^G;*f-OPr8gO#!H+Wk3x zpTYX=;Unf$f#U+>`Yn~%q=Rj!;_X1ArWg3jE7g<*8}h;AjmhJ) z+1nnX{9mDO_abA6=c(pE_+$U?GE4NEAbwr=&o-`qouV@z|6uBBp#5urUyUZuuz(Ew z^7M@DBq2!Xz;}u^;{_^z^W!7Le;sT%g#m!vt3UDoG3G!RiBPG28jFqRf9Tc;LlA2C zPD5zo7hiwQbBfo9|HOaM=n(RRZOc=BSnfZ&|8EnM5GK4|IE9n7f5HTJ z4}=j2SCXd@(7Hb({Iaej+ O@NXh~hPIpj`R!lB(&vx> literal 0 HcmV?d00001