From e4eccc8abeb14f26befa0ece9dface016158aa91 Mon Sep 17 00:00:00 2001 From: Allen Houchins <32207388+allenhouchins@users.noreply.github.com> Date: Fri, 14 Nov 2025 20:59:04 -0600 Subject: [PATCH] Add Webex as macOS FMA (#35396) Introduces Webex as a maintained app for macOS, including input and output metadata, install/uninstall scripts, an app icon, and a frontend SVG icon component. **Related issue:** Resolves # # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [ ] Added/updated automated tests - [ ] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [ ] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [ ] Confirmed that the fix is not expected to adversely impact load test results - [ ] Alerted the release DRI if additional load testing is needed ## Database migrations - [ ] Checked schema for all modified table for columns that will auto-update timestamps during migration. - [ ] Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects. - [ ] Ensured the correct collation is explicitly set for character columns (`COLLATE utf8mb4_unicode_ci`). ## New Fleet configuration settings - [ ] Setting(s) is/are explicitly excluded from GitOps If you didn't check the box above, follow this checklist for GitOps-enabled settings: - [ ] Verified that the setting is exported via `fleetctl generate-gitops` - [ ] Verified the setting is documented in a separate PR to [the GitOps documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485) - [ ] Verified that the setting is cleared on the server if it is not supplied in a YAML file (or that it is documented as being optional) - [ ] Verified that any relevant UI is disabled when GitOps mode is enabled ## fleetd/orbit/Fleet Desktop - [ ] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [ ] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [ ] Verified that fleetd runs on macOS, Linux and Windows - [ ] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md)) --- ee/maintained-apps/inputs/homebrew/webex.json | 8 +++++++ ee/maintained-apps/outputs/apps.json | 7 ++++++ ee/maintained-apps/outputs/webex/darwin.json | 21 ++++++++++++++++++ .../SoftwarePage/components/icons/Webex.tsx | 14 ++++++++++++ .../assets/images/app-icon-webex-60x60@2x.png | Bin 0 -> 13945 bytes 5 files changed, 50 insertions(+) create mode 100644 ee/maintained-apps/inputs/homebrew/webex.json create mode 100644 ee/maintained-apps/outputs/webex/darwin.json create mode 100644 frontend/pages/SoftwarePage/components/icons/Webex.tsx create mode 100644 website/assets/images/app-icon-webex-60x60@2x.png diff --git a/ee/maintained-apps/inputs/homebrew/webex.json b/ee/maintained-apps/inputs/homebrew/webex.json new file mode 100644 index 0000000000..e4a3eb3769 --- /dev/null +++ b/ee/maintained-apps/inputs/homebrew/webex.json @@ -0,0 +1,8 @@ +{ + "name": "Webex", + "unique_identifier": "Cisco-Systems.Spark", + "token": "webex", + "installer_format": "dmg", + "slug": "webex/darwin", + "default_categories": ["Communication"] +} diff --git a/ee/maintained-apps/outputs/apps.json b/ee/maintained-apps/outputs/apps.json index f83e7cb08c..0f3412b219 100644 --- a/ee/maintained-apps/outputs/apps.json +++ b/ee/maintained-apps/outputs/apps.json @@ -309,6 +309,13 @@ "unique_identifier": "com.realvnc.vncviewer", "description": "" }, + { + "name": "Webex", + "slug": "webex/darwin", + "platform": "darwin", + "unique_identifier": "Cisco-Systems.Spark", + "description": "Webex is a video communication and virtual meeting platform." + }, { "name": "WhatsApp", "slug": "whatsapp/darwin", diff --git a/ee/maintained-apps/outputs/webex/darwin.json b/ee/maintained-apps/outputs/webex/darwin.json new file mode 100644 index 0000000000..4308e44ae7 --- /dev/null +++ b/ee/maintained-apps/outputs/webex/darwin.json @@ -0,0 +1,21 @@ +{ + "versions": [ + { + "version": "45.11.0.33441", + "queries": { + "exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'Cisco-Systems.Spark';" + }, + "installer_url": "https://binaries.webex.com/webex-macos-apple-silicon/Webex.dmg", + "install_script_ref": "c9895bbf", + "uninstall_script_ref": "a7a30839", + "sha256": "no_check", + "default_categories": [ + "Communication" + ] + } + ], + "refs": { + "a7a30839": "#!/bin/sh\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil \u003c\u003c\u003c \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nsend_signal() {\n local signal=\"$1\"\n local bundle_id=\"$2\"\n local logged_in_user=\"$3\"\n local logged_in_uid pids\n\n if [ -z \"$signal\" ] || [ -z \"$bundle_id\" ] || [ -z \"$logged_in_user\" ]; then\n echo \"Usage: uninstall_signal \u003csignal\u003e \u003cbundle_id\u003e \u003clogged_in_user\u003e\"\n return 1\n fi\n\n logged_in_uid=$(id -u \"$logged_in_user\")\n if [ -z \"$logged_in_uid\" ]; then\n echo \"Could not find UID for user '$logged_in_user'.\"\n return 1\n fi\n\n echo \"Signalling '$signal' to application ID '$bundle_id' for user '$logged_in_user'\"\n\n pids=$(/bin/launchctl asuser \"$logged_in_uid\" sudo -iu \"$logged_in_user\" /bin/launchctl list | awk -v bundle_id=\"$bundle_id\" '\n $3 ~ bundle_id { print $1 }')\n\n if [ -z \"$pids\" ]; then\n echo \"No processes found for bundle ID '$bundle_id'.\"\n return 0\n fi\n\n echo \"Unix PIDs are $pids for processes with bundle identifier $bundle_id\"\n for pid in $pids; do\n if kill -s \"$signal\" \"$pid\" 2\u003e/dev/null; then\n echo \"Successfully signaled PID $pid with signal $signal.\"\n else\n echo \"Failed to kill PID $pid with signal $signal. Check permissions.\"\n fi\n done\n\n sleep 3\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsend_signal 'TERM' 'Cisco-Systems.Spark' \"$LOGGED_IN_USER\"\nsudo rm -rf \"$APPDIR/Webex.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.cisco.webex.Cisco-WebEx-Start.CWSSafariExtension'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/group.com.cisco.webex.meetings'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Cisco Spark'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Cisco Webex Launcher'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Cisco/WebEx Meetings'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.cisco.webex.*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/webex-pt.webexapplauncher.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/WebEx Folder'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Webex Meetings'\ntrash $LOGGED_IN_USER '~/Library/Caches/Cisco-Systems.Spark'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.cisco.webex.*'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.webex.meetingmanager'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.cisco.webex.*'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/group.com.cisco.webex.meetings'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.cisco.webex.*'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.webex.*'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/WebEx-PT.webexAppLauncher'\ntrash $LOGGED_IN_USER '~/Library/Logs/SparkMacDesktop'\ntrash $LOGGED_IN_USER '~/Library/Logs/Webex Meetings'\ntrash $LOGGED_IN_USER '~/Library/Logs/webexmta'\ntrash $LOGGED_IN_USER '~/Library/Preferences/Cisco-Systems.Spark.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.cisco.meetings.shortcut.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.cisco.webex.*'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.webex.*'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/Cisco-Systems.Spark.savedState'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.webex.meetingmanager.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/Cisco-Systems.Spark'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.webex.meetingmanager'\n", + "c9895bbf": "#!/bin/sh\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2\u003e/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 \u0026\u0026 \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS \u003c timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" \u003e/dev/null 2\u003e\u00261; then\n if ! pgrep -f \"$bundle_id\" \u003e/dev/null 2\u003e\u00261; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n# copy to the applications folder\nquit_application 'Cisco-Systems.Spark'\nif [ -d \"$APPDIR/Webex.app\" ]; then\n\tsudo mv \"$APPDIR/Webex.app\" \"$TMPDIR/Webex.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Webex.app\" \"$APPDIR\"\n" + } +} \ No newline at end of file diff --git a/frontend/pages/SoftwarePage/components/icons/Webex.tsx b/frontend/pages/SoftwarePage/components/icons/Webex.tsx new file mode 100644 index 0000000000..0f0584d92a --- /dev/null +++ b/frontend/pages/SoftwarePage/components/icons/Webex.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; + +import type { SVGProps } from "react"; + +const Webex = (props: SVGProps) => ( + + + +); +export default Webex; diff --git a/website/assets/images/app-icon-webex-60x60@2x.png b/website/assets/images/app-icon-webex-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ad0c94822e2ce2592f897f564e9f535129ea4a0d GIT binary patch literal 13945 zcma)jRal)p6YYz;yF+nzw+$4EYjLM&ad+6bODV8%w*tl8p|})^ySux~`Tm=8ZqLOe z>q&BxJjqOE)=ZSD@)tB@Vq^dS(Bx!4tN+)7|0js>|FwU_OveBKO2S4;N>xruic;0Z z(bC4w0st6(d^0h@mStfWHZ?Ud8J=KfM0W91kBp2}Hwhf=8Ks=;nV=lZOHVT}*d)Z< zg!$SB6sq+$+oHx&KG(4gvpjfz9MDL^Hqu=fJJOEmEXVvJhjS_}!l#Eh5(i~v8K{2k z>*+}Y%$Xq&T<{_*s7V%UN)2?6iYZLiX9QzLFR_Tw^IbAHE9jIN)C6*oF+)y#gB_li zlf+i}VkUJ42c@k2h1zw-X+sg(ftDz_NGlm^eefDQS}=Yaiw*b11hJUOYoGSyh=GuZ zkcf)|+(%OIe1qmBz!mLG**}^@NN7hI6s(0$95}(ldnmz&cQ1T=e008jd~}Zy5~ewFa*#g415|hh zPthnV<^P?jfQ62nrIHfB^dCk9pdxGl*#8jJe?t790049z^#2_J=fV6x{J%+C89F5Z z;Hj4TEb-L~>MYwk(O|)S-Lbmf6n+dK1k>S{${}y{DWmAH6{AL1=!N5(i-ZVNwVL!l%XkQgDLT$H-V7e z)6Ttz>=%d0Z2mRTHBnKXlw*ai){C{hRoBUk;a%3Nyv*5Y2WYnqSr7+z_x(Gc~uv@8ke#^QhS>yk7kP{|eR z1m2Ei8ve0OXd?sPhj77lUz!}&eEiuU?ZsLZYoDKc73u1KdWBZ>q@b4*+z{asS%-JH zwWcYT6*jc^8PNGtj26$_kuHD7=P$=uV7_unKVk6~MyQIiP;t8^%V^WHfqo)rSd^+e6P%O(|Z05EpbnBY;Vpe^XOa2T~|}2#~E%ZM{n)w?N2Nt@WT#hfh8it3SoX5U>aApDxwcH|XjNKb1l4m$D&%$uqj)QZ7J>uy z@8rm@y9xq=4$cN|lC3n^``WpP-5>uU4pA>uzI ztK58i_mnxCG`9<)^g8T7Xy15_sILPFIr%&3gK*$b#*-RmHi@VHoGaD|i7j(BHv9SxQ3NC{G{QwQ(|8s51P(KI!J>AWD0Y zi=yrC@kI^Kg?%632Np-mZHd{P0{dL8^eeyCHTp)7rKVeX{c^=Y?O;c&ks_}4x{~n= z7mT^yKEbo98iOC;b`9$8@_)I1OXTQulP@R1pgds*z};VV9ML3C8@9B|{p|MQmQhnT z7*uR*=Nz>zQe+8$O-B?T0U=)A;#P2YP<(i>g9s?qe*J7Y855@Zz6L+xWFnCFmcsBA z?{O+9JpOLU1}^jUO6-G|$HNfQD3Uhz*1zJwW3(bR_%L*=wDO(gdd9i%IbU&DK?CK< znRGO?;ZabjRE?;3fGWU2ORT7L3|>fn2xT=16(;+5W+dAadlrNbaYczkZ#HA1BZg@B z&`%!KRcRHAxsu_Oz#`Mx-$B`?55B3)AWqi$V%TtQ9QiUAdd#uZc1uIOYIDy}Dr?Hm zoZSl25iG=AFxF?|X!2u=571IIh!UN`128S5tm2rUwsxLQtbDB!g;P&+Q-1Mdt}xb9 zP;8!O&Pavkem1j;>ljt$=qJ)Vw3La4ob85z?lzrYU}1;4vNj#3^!$P`RBVD96Ldj_ zz}nsK+zM4~HJ_h~?7BE9eOW)b{jlJrtY-25{>@qnisN$#!ZP-{kFTC|n%+gc!CBqP z`F7hM3z;hE%N5l@Ko?PmTw;>}3Oq1VCG=KQVf30`VdO(-kyRMmqk5W!gKNYLF|^Fv zbn&G#*jip=3pDB5^KkH3`X}Kv+^U#UtOIYcz{I8z9|}pEZmFy!9@uYMKfm@3?6nx$i0x_i z;qu6k1t6PIJs>*%{x)-zO##qSd)CT_r-A)@QANiqtG3`B9_WhUwr2hG`iB(MV$Tmt z<*LrF9!s@Y{Ey+8tD7o@7uPQyCU@9)XIhss3T7|%*K(^7V8a&J*LeWK)`3NX|USv<$5 zMV~|iUCq##SYBa)v`c<#FFT8SpWG>Pi;+FL^(}a#4`DX`cZf)Dd9vPu3ql+sCPPRo z$m2$dP5jE?IMu)%*>O`<=X)PR#pK!IG2h#SXW^@Gni;O4eH4{!)f!!PRNch3JG+J4 zljdr*$6kv|n>O(TbRx?gF2)XCQ`Zx+wdU&T4@T;R^b9>uVW?hR57>{iB%v8{mV9?< zmv*Qg58yJt5x^Ab%OEWSg3I$Ox90*E@El+H17a5*yXCI{iF4&t1{LZUjki5EJTKFncR%>gkHaul?&{ zFT)1rJ=a`302Q_$9taBZ?dS{&7Wp@fVYxP+o8dG-7UJ;y17d@dlLor~ga~Aj`9)3S zu}i58O-R`L=I>Aeb-IlF2EQ|O_tr`9Qr)Shw)2gh!)(REUtl|2o|vJ}IPXztn3#jE z7noJ{2MM!&aA|0DCc(Nf6G6JK4-7nVDe_@))&92h*xG#G|8afDk3G`w3o9geFwKRdr z@prOJ46(JgiKWB2U97Rqr2e(9H!v0mx$XqPehVrr!3)Bz^o4bh-#6lRV)EX~B*@EQ zGIeo@Vuf+9|5HiWWN-$*E;b$;xF{G7rBTM1#wRsSY%H&Bw6<(dcqs*D)S4#`5AWYj z$r+GZ%%YU%riYvOQSrsl*>B45k&QW&+ypSRMw}uw`SaiFoQcKlE=iQK8AyJ}WJFYd zU|hi$k}atVs)@vnPgTkQJ0ukOJiSgk-hlP@%}7h|&GX zktSfkV~)P`V~qtB;~&6YbiCuARG)n%LgZL>FRAn@U=5meESuXa+KSg6^tC9zmoF%C zfc^s|hL4oSh_a?6t}x2;%manqYBg$-)YN@*ECx01X^edNW#%`h2NwcjR?m?OA{q+j zRj2%7%Y>p3HwU=*!n1YFS9d$E?Rd4aLRp#fqP_uE}@e? zl-I3^q}8bpE^G?6Z{~=yKR3y{J2%FW6z7R_o!ex04Hl(XzbMJw@-$6wFdG=-GHTCI zVCQ@t=AJT<@g*4Zk3v(qj^FFD3?#ulga-!Wh%t}})^7cO_roF#V0@fTw*JU{^M-VX zZv^2liGj8>2N#)EN>b!rduF(+UU5frz8p5WBOB`GLgkH5F%|n-ByLIM!&|)B!CAT3 z^~}-~!9sdtfHK|?IxD<;BIV8z%?Cd$>@GtRiC&Y9(?emtV>%}W$`(w{-KbxP`*@~bTVxN2-CGdD z)#Csy*h$jjFNuY0fTEBB0C>@QauS%WDs{VUzOZL zJ<0d9vz{8vg5t^`G7jgW#~aC;cIAq&TyD9#c~68d#>@Y->(Io?vx-WU3F9@~%&F2j zIL9Um&CWe*Q^|Js)0K$bu+8lVFC8Y0rTDb1kNRlz8igTnDDXL%nY67}v!rI7R_pw* zanPgewqkL!8ZqB;$kpM}Fmv@)o8IsVm5qaXY$0}IXg_}9twIS&Wm-8kKphrx+BurU zM14ZTUMd*WIvLqo(mdPhR9dl{6N-;oV5i%q#1q#={9BR&dUbTeH)PTWV{-`#WS;L- zAK=mv2s$dK$-^r9B|Ziv$?LW5`e5pLAAzvCnvV2{a7YwB@`^clqpVHZHq9#bu0n`! zR8sW-I|e)Nxj?8MXA^CI1{=?R157KIs5-5PU#&Q7qItGNvt+zw<=yHbsd*)2AY%8* z7DB@siPY1c;A0rWvefx?0I8E+z5WfeGxL=}66b=y*#FXKbF=@3Hn)V9b=hbUANy6e zdab2BK{iCGB1zr`p49JtfF7H_z+=M9ApdQsbc;<6fRsrj^q`#f8U%}czeTm}E+fr*Izg6Mv2neyZB)%9E?75e>YS>{9e#gp4X%9Pk!;&!C>vp*6J?? ziXP|VR&R*p3yf(?+4o4<9y22;`B{!yORzXy{L&KtGG<;gc#HrrVJKS;BQRml(^IdE zIp1t^_coXo^cKA11mjGTlgKM}K+87@hJmdfrWmZ&`p?)~{)ry+h)iy;&=oX@7P(Eh@z&1AXPTP@k>IGSiq+K;@%aCxFe%Xa z17p34aRV^w=JX5(qM@}F*;PADV3gZ^TFMII(j=bMM1kb+cO9wtN--2aI$-l!&4GiqXFsOzl0*uDd3d!_P&FG)_ z4qX(QH-F`s-eJS_WR(`{*t?9JZ9h1lcjacR&`4!HcNG}t+W;nns!FlW<+|cIBNMh(O3)kyS`0t5 z?AQ0`K0-NPu$VaYyI;R)cSaM)>885!c}qPhb`|02elI~*GCH*`9HEO;wIfZ7nAM5a zL~oJ5|B`IQM^|D!-v-aF7oDPF>{fgsG7z2$(sPX&`rCT-ur{t!p1|b*vOlBV+mG}$|XfDnRNBiQmT>*e{YRxsa@Z1>W%s!*_ z5l<_x4wpm1iM{ySS+8V=#gm^Bgq!-52ob2oMMG5o#C?LY!BM=RBQ(o(nlnM}kzW5n zMl@pPHlo0x`|~o%YK)sFdd5;hao@1Z#Z^*)P5f5lw4QMSrLY(wVL65xhIyzHKcRD% zZ5@Sj_s%ZV%o?#)2NYN$d}mBxJ#8TYq~H@O?;L8dB^mWrt6d)5;>w_z5uQ zw^jH$eapbbJoN%h%pRb(pYBmm)*NQ#{zXv!$#;{68`V*Vnr+=)?D@T3LuGa9A|WluSg76@UN8eDGJFp5{Ub z@pHCv_2=Iz+?#qi!}1KLyY}QIk9C`(dc#%YZKt!%tyotUd_@|JqTJr>ee5zmzYUthYCrei(VLF#(1M|FH+bY|ql{ND<9HKZRlz@HY=5db%(G^lc zzWDbup1CQHj4K?P|08QI@nxa0((eN9v~^vlkVMd`snoXm&V7Id;=aT3bHe8AD_i@f zP?*7B%3sCSC3h!F1HjOS2Wm1%1tgc=q28?x)2*h&_?(AQb6<(45 z=q$dMT+v?5oZ+v>Hqv9%M$Z{MAS0>7su*YJw@QimPvT;waHFjfHymJ+lgeE_n`Zvy zX&gZ21%^M#?Z%mU?3;dP(GM_Ko4%v7KbEjA`)v_6mKj+yF!DCqc2rtEw%|bX!!<}t zr9-VblUADvLxwl#qOSM>GV5d-C^Y#-` z=w5s)IXOx3I6CFg_@Pmg^Np|vW-*L)49D82q7#|~yM=%-F+wRAPl4rC@F9|~P&Lk= zbITB9`ZS{UU=-m1U^X;o5X66lsC4!ifSs8nJP(s^P3CuT{MJB>{l~0#wNv3+%IVkEsCGy?J)u1;-BpeeMb-WUiwO@Aq9dQf0>brnc$%puf8xSI-EkUtH)G7 z2w-+38qR%R=WKQhfNI7-#D_tw2}m}UcuL_QNc_o#={1>0);q=?Uklq2+#GC+4i$tJ4+d(lu8{#2i)VhlUcUTNDWr30C6-lfL(%IXHihbU+|i zqQvYR$LyiP0%{66i~Ma#w31rRtaS_QwQc?(j%%_TI;G5z|JwHtL8Pth$uYxOmv?)# z6B<_v2xgt^pp#@lImj8*t~(0mRNx-Kd$a6MK;xX_}2Y{$rB+O*jqZ`Yx;J zM+5V!Qz@e$eq*zm23FiCt^V$g5XqE@d*Vu03K~^v2)EAqDwYdG*ob}kQ04~gjqaKJ z2qohXY`JR{LLkf3ugF^xr6N;_tG>7=D)1MEaDdR?8AqO-Y^E1keGbEHtqC28P?8GC%`NQ@rZAy; zo@PcUe7~%*FpxYg4S|AnaMIr9d^P8CN~&psXPkf;G!UyFVm0)NZVp{G3is%f`gAK4 zcUx~^&g}3k+p9FOamsh*KN4pkxCcK(VBm}k-dP)kd|4eRTv-b%ZQ8*T;2#mj6z(r@ zCI=RgDBG=;gkNH(f(i6kLttYi$B)N_BH|o{-~sZUP-6Wa*47B_*p}6P~i16%hJwY(+5D zM0`a|+(W~Tf4!vunJk|6GeY1~(O_R=GzW9g^sgP#N0G5=i-%ync`>z~UJ}L5<(bqA z6ebnWr13~Mqnb}plU|50*jX2Gyxb~*s{vZ8$o2@3_%h*|fx-j%*8j_)c6Q*+?hTs3 z@*${e8Rg*@GBdg0)nWMnvkgY^$=+9NyC{Ut%J?*9_F6BEn&iLr*&g_a4ZQ>SPVVl^R=12S);00SkPP9joQ0ki}pn z#&2PgG%eD6O5abHnDZWMU~k#Am;V6l{)Qel)nl7EqSZ3?7W!f~cg9d`lNBpwTo_Rb zGzxN2{UO>e(^u?)Hq%z(?qf%@H{go#Y!h_9_&$jo&f2@Rhn#{()A^3aTMWp7eTiSS z3C3og9bP<0Rhz~}$e2Uu+-0E)3ZrW}rc7&$lA1y)P0E!IdiXmu08J=sBiCoeg+aJm zh)MlY=4ji*Iw!N>JrIKt9nh!4HACK!{ku%i3B zK4cw-!GUbN!s)Yc^Pc%a!#@(%-E&QffaNH4p)nXHsA(B$~ zLfW9=mEyDftB9-jj4ztIrD_@}6~vxfg442txjnB46@~3KX#vf@XFEOU8nsZcu)5Ec z>B)t9I1tZXuVqIfC+vA6W{TbGO&OKb?WIN1A=+>c?HFfPJEXa(KsvoX538sRO^MDIhU!Qkn9+JAPR_k{dlQPVQU?|HC--w!+)!8UfWWtO!BCZ zXJHM~o)IxQ?$8$+j3VpV^v(QyyNWmql`Wf28z10?WqH~ZqrJVjFpm__9w_W8$LFz( zv@AwWywwcfo+e&PoxauCb|A2&OF7LVqD$0}XY-{wEocm8k^XxFYD{usRa@53SYE!= zt$*w%BtTQ3*6hRw8diMf3)=p*;DyPKc(=zid(LBqoclfD1u*Z0P@pw?!6wNMSYHg~ z$8NvqFX>=a#uR{UeD)Y45w7{O& zPfou)Jz9wd^JO3$M=2RN2fW73+J7U2rkM+3Ci>WtcuOqSj}XP!zfUnaTEDZcocs>0 zg8+;k_~kd%EBwUh?YVvrEbNL2EcV1{g92ZS=>6UkoOL=D)JMOL`C_~b+xuIOm&t6| zxNL9(fg`O3OF(kij@UJ9WgQ;StA%UC1-~ z)i@L3PF@jvJEH>=1i86BtH@FEw2TG|OU`({sMWU6*N z0&L$;IE6fQnr^&thweVSjY|*90am&Y2A;sXJDu`2xWrklAV-WEVoYJaD}_V05Eh$e z-N4UMr&m9Iz5Z=CounNzUO!}X>2m8~rfANU ze#&@70x4K^OQT>X6E3Dr{r6X96wl+S$rvFpIBKO|oY-6RAcRl0nNLivgOFgSvRz=E zQbxY$K&-?em^w7UZd08Hm00vyUea@Xakr>Y57hR8K{$e_U`v}`d){VNpk4~ z;kuSC?FL_v3&UAvaf@|+iv5OfIlz_nI8o-moX7YSD2~dqFz|Mq3A?a9tj3jU)Z~iD zs+&1K8Ipx-?{YSt$uxhMEuKy_G18sXFIA$YO^vZj0lEkk(gm)xg!+*Js@ z9E#>mvF$Ti7h3H0JtX-2X=mycOK1(Z}rGov9X_ z=gTcE`gc^c_I%&*C?_O>g}i`~Al{^qK|_4aUCRPy0il8mxz ziE$MP0m@s=ry5`2$CfAf`ya7abN5u?%>yW-{O1%0(+A;nopZPU)F0Q@&hGT#Nv!XS zN06y5`1($BK?VG_-sSnGE|y!$9cD|Icx~~1=)29Y zm)f*z{8$3F@_o(qg0Y?LkY90Z=jj7^z^t zO99cfgnTS$-;?fKLe)hW#+fN~XiiW#a2K!ij0hR;Bg9im*|tn^>5*&h-9|lb;fCc# zR&hw|HM*XE0wCu?OfTitRk_nsHuNwN6oBBb`Yve@nw=Sn>_ZaV;pW!9|Izx+CSPCJdwJTG+z zMMyEA=a^M#25BuA(Tk*5!m7H)y$QW@=_`0mXl}pb$M8X#LM{ARO1UyG0Uv&oHf=-4 zt1-|eWz9jFKk+S2I}JXf-4mTOJ@R0Ar(~x^W|)2k#YSgJ;UhGA`J+M31CRk@y|ID8 zzL&n^a2_Tez7a?9BK44{>PaPICj3x$d;Fwve!U$<5)Ees~0J625h6DF%qKx zAU~z-pc4gsG@B2^0YBc|ig*4$yYy7R#+Ph2Zp8-OtqWzG4HVT61#F~Psa&r<&pA?i zcPBZ**ci{xNGB3J&P=vX*S`*HunTwGM`A*!ey_J?R0Sm_DlKAnvlAy@{5B*HJ^R`b zW&MO=o8-v}gc7zfee20veYEKSZs1(W_mNxBQmX}ny8Q}AjA6_+zi__xWg4yR^OR%~ znD9B`cUNALB15((o^dD!v`}Ot;^(X5;p0Q zcDGNSClgF<�PoJbDKOR+WA+M9ma3vYDFhMf2jz&>M;07O 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 literal 0 HcmV?d00001