diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs index dff4d483e7..6fd3d301a5 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -94,14 +94,24 @@ namespace OpenSim.ApplicationPlugins.LoadRegions regionLoader = new RegionLoaderWebServer(); } + m_log.Info("[LOADREGIONSPLUGIN]: Loading region configurations..."); + regionLoader.SetIniConfigSource(m_openSim.ConfigSource.Source); RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); + m_log.Info("[LOADREGIONSPLUGIN]: Loading specific shared modules..."); + m_log.Info("[LOADREGIONSPLUGIN]: DynamicTextureModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule()); + m_log.Info("[LOADREGIONSPLUGIN]: InstantMessageModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new InstantMessageModule()); + m_log.Info("[LOADREGIONSPLUGIN]: LoadImageURLModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule()); + m_log.Info("[LOADREGIONSPLUGIN]: XMLRPCModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new XMLRPCModule()); + m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule()); + m_log.Info("[LOADREGIONSPLUGIN]: Done."); + if (!CheckRegionsForSanity(regionsToLoad)) { m_log.Error("[LOADREGIONS]: Halting startup due to conflicts in region configurations"); diff --git a/OpenSim/Data/IUserAccountData.cs b/OpenSim/Data/IUserAccountData.cs new file mode 100644 index 0000000000..6bec18833d --- /dev/null +++ b/OpenSim/Data/IUserAccountData.cs @@ -0,0 +1,55 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data +{ + public class UserAccountData + { + public UUID PrincipalID; + public UUID ScopeID; + public Dictionary Data; + } + + /// + /// An interface for connecting to the authentication datastore + /// + public interface IUserAccountData + { + UserAccountData Get(UUID principalID, UUID ScopeID); + + List Query(UUID principalID, UUID ScopeID, string query); + + bool Store(UserAccountData data); + + bool SetDataItem(UUID principalID, string item, string value); + } +} diff --git a/OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs b/OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs new file mode 100644 index 0000000000..78fc22cdf9 --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs @@ -0,0 +1,222 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using System.Data.SqlClient; +using System.Reflection; +using System.Text; + +namespace OpenSim.Data.MSSQL +{ + public class MSSQLAuthenticationData : IAuthenticationData + { + private string m_Realm; + private List m_ColumnNames = null; + private int m_LastExpire = 0; + private string m_ConnectionString; + + public MSSQLAuthenticationData(string connectionString, string realm) + { + m_Realm = realm; + m_ConnectionString = connectionString; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + { + conn.Open(); + Migration m = new Migration(conn, GetType().Assembly, "AuthStore"); + m.Update(); + } + } + + public AuthenticationData Get(UUID principalID) + { + AuthenticationData ret = new AuthenticationData(); + ret.Data = new Dictionary(); + + string sql = string.Format("select * from '{0}' where UUID = @principalID", m_Realm); + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@principalID", principalID.ToString()); + conn.Open(); + using (SqlDataReader result = cmd.ExecuteReader()) + { + if (result.Read()) + { + ret.PrincipalID = principalID; + + if (m_ColumnNames == null) + { + m_ColumnNames = new List(); + + DataTable schemaTable = result.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + + foreach (string s in m_ColumnNames) + { + if (s == "UUID") + continue; + + ret.Data[s] = result[s].ToString(); + } + return ret; + } + } + } + return null; + } + + public bool Store(AuthenticationData data) + { + if (data.Data.ContainsKey("UUID")) + data.Data.Remove("UUID"); + + string[] fields = new List(data.Data.Keys).ToArray(); + StringBuilder updateBuilder = new StringBuilder(); + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + updateBuilder.AppendFormat("update '{0}' set ", m_Realm); + + bool first = true; + foreach (string field in fields) + { + if (!first) + updateBuilder.Append(", "); + updateBuilder.AppendFormat("'{0}' = @{0}",field); + + first = false; + + cmd.Parameters.AddWithValue("@" + field, data.Data[field]); + } + + updateBuilder.Append(" where UUID = @principalID"); + + cmd.CommandText = updateBuilder.ToString(); + cmd.Connection = conn; + + cmd.Parameters.AddWithValue("@principalID", data.PrincipalID.ToString()); + conn.Open(); + if (cmd.ExecuteNonQuery() < 1) + { + StringBuilder insertBuilder = new StringBuilder(); + + insertBuilder.AppendFormat("insert into '{0}' ('UUID', '", m_Realm); + insertBuilder.Append(String.Join("', '", fields)); + insertBuilder.Append("') values ( @principalID, @"); + insertBuilder.Append(String.Join(", @", fields)); + insertBuilder.Append(")"); + + cmd.CommandText = insertBuilder.ToString(); + + if (cmd.ExecuteNonQuery() < 1) + { + return false; + } + } + } + return true; + } + + public bool SetDataItem(UUID principalID, string item, string value) + { + string sql = string.Format("update '{0}' set '{1}' = @{1} where UUID = @UUID", m_Realm, item); + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@" + item, value); + cmd.Parameters.AddWithValue("@UUID", principalID.ToString()); + conn.Open(); + if (cmd.ExecuteNonQuery() > 0) + return true; + } + return false; + } + + public bool SetToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + string sql = "insert into tokens (UUID, token, validity) values (@principalID, @token, date_add(now(), interval @lifetime minute))"; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@principalID", principalID.ToString()); + cmd.Parameters.AddWithValue("@token", token); + cmd.Parameters.AddWithValue("@lifetime", lifetime.ToString()); + conn.Open(); + + if (cmd.ExecuteNonQuery() > 0) + { + return true; + } + } + return false; + } + + public bool CheckToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + string sql = "update tokens set validity = date_add(now(), interval @lifetime minute) where UUID = @principalID and token = @token and validity > now()"; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@principalID", principalID.ToString()); + cmd.Parameters.AddWithValue("@token", token); + cmd.Parameters.AddWithValue("@lifetime", lifetime.ToString()); + conn.Open(); + + if (cmd.ExecuteNonQuery() > 0) + { + return true; + } + } + return false; + } + + private void DoExpire() + { + string sql = "delete from tokens where validity < now()"; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + cmd.ExecuteNonQuery(); + } + m_LastExpire = System.Environment.TickCount; + } + } +} diff --git a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs new file mode 100644 index 0000000000..15208883ea --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs @@ -0,0 +1,186 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using System.Data.SqlClient; +using System.Text; + +namespace OpenSim.Data.MSSQL +{ + public class MSSQLUserAccountData : IUserAccountData + { + private string m_Realm; + private List m_ColumnNames = null; + private int m_LastExpire = 0; + private string m_ConnectionString; + + public MSSQLUserAccountData(string connectionString, string realm) + { + m_Realm = realm; + m_ConnectionString = connectionString; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + { + conn.Open(); + Migration m = new Migration(conn, GetType().Assembly, "UserStore"); + m.Update(); + } + } + + public List Query(UUID principalID, UUID scopeID, string query) + { + return null; + } + + public UserAccountData Get(UUID principalID, UUID scopeID) + { + UserAccountData ret = new UserAccountData(); + ret.Data = new Dictionary(); + + string sql = string.Format("select * from '{0}' where UUID = @principalID", m_Realm); + if (scopeID != UUID.Zero) + sql += " and ScopeID = @scopeID"; + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + + cmd.Parameters.AddWithValue("@principalID", principalID); + cmd.Parameters.AddWithValue("@scopeID", scopeID); + conn.Open(); + using (SqlDataReader result = cmd.ExecuteReader()) + { + if (result.Read()) + { + ret.PrincipalID = principalID; + UUID scope; + UUID.TryParse(result["ScopeID"].ToString(), out scope); + ret.ScopeID = scope; + + if (m_ColumnNames == null) + { + m_ColumnNames = new List(); + + DataTable schemaTable = result.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + + foreach (string s in m_ColumnNames) + { + if (s == "UUID") + continue; + if (s == "ScopeID") + continue; + + ret.Data[s] = result[s].ToString(); + } + return ret; + } + } + } + return null; + } + + public bool Store(UserAccountData data) + { + if (data.Data.ContainsKey("UUID")) + data.Data.Remove("UUID"); + if (data.Data.ContainsKey("ScopeID")) + data.Data.Remove("ScopeID"); + + string[] fields = new List(data.Data.Keys).ToArray(); + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + StringBuilder updateBuilder = new StringBuilder(); + updateBuilder.AppendFormat("update '{0}' set ", m_Realm); + bool first = true; + foreach (string field in fields) + { + if (!first) + updateBuilder.Append(", "); + updateBuilder.AppendFormat("'{0}' = @{0}", field); + + first = false; + + cmd.Parameters.AddWithValue("@" + field, data.Data[field]); + } + + updateBuilder.Append(" where UUID = @principalID"); + + if (data.ScopeID != UUID.Zero) + updateBuilder.Append(" and ScopeID = @scopeID"); + + cmd.CommandText = updateBuilder.ToString(); + cmd.Connection = conn; + cmd.Parameters.AddWithValue("@principalID", data.PrincipalID); + cmd.Parameters.AddWithValue("@scopeID", data.ScopeID); + conn.Open(); + + if (cmd.ExecuteNonQuery() < 1) + { + StringBuilder insertBuilder = new StringBuilder(); + insertBuilder.AppendFormat("insert into '{0}' ('UUID', 'ScopeID', '", m_Realm); + insertBuilder.Append(String.Join("', '", fields)); + insertBuilder.Append("') values ( @principalID, @scopeID, @"); + insertBuilder.Append(String.Join(", @", fields)); + insertBuilder.Append(")"); + + cmd.CommandText = insertBuilder.ToString(); + + if (cmd.ExecuteNonQuery() < 1) + { + return false; + } + } + } + return true; + } + + public bool SetDataItem(UUID principalID, string item, string value) + { + string sql = string.Format("update '{0}' set '{1}' = @{1} where UUID = @UUID", m_Realm, item); + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@" + item, value); + cmd.Parameters.AddWithValue("@UUID", principalID); + conn.Open(); + + if (cmd.ExecuteNonQuery() > 0) + return true; + } + return false; + } + } +} diff --git a/OpenSim/Data/MSSQL/Resources/011_UserStore.sql b/OpenSim/Data/MSSQL/Resources/011_UserStore.sql new file mode 100644 index 0000000000..5aa064fac8 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/011_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION + +ALTER TABLE users ADD scopeID uniqueidentifier not null default '00000000-0000-0000-0000-000000000000' + +COMMIT diff --git a/OpenSim/Data/MySQL/MySQLUserAccountData.cs b/OpenSim/Data/MySQL/MySQLUserAccountData.cs new file mode 100644 index 0000000000..39d60ca6c0 --- /dev/null +++ b/OpenSim/Data/MySQL/MySQLUserAccountData.cs @@ -0,0 +1,180 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using MySql.Data.MySqlClient; + +namespace OpenSim.Data.MySQL +{ + public class MySqlUserAccountData : MySqlFramework, IUserAccountData + { + private string m_Realm; + private List m_ColumnNames = null; + private int m_LastExpire = 0; + + public MySqlUserAccountData(string connectionString, string realm) + : base(connectionString) + { + m_Realm = realm; + + Migration m = new Migration(m_Connection, GetType().Assembly, "UserStore"); + m.Update(); + } + + public List Query(UUID principalID, UUID scopeID, string query) + { + return null; + } + + public UserAccountData Get(UUID principalID, UUID scopeID) + { + UserAccountData ret = new UserAccountData(); + ret.Data = new Dictionary(); + + string command = "select * from `"+m_Realm+"` where UUID = ?principalID"; + if (scopeID != UUID.Zero) + command += " and ScopeID = ?scopeID"; + + MySqlCommand cmd = new MySqlCommand(command); + + cmd.Parameters.AddWithValue("?principalID", principalID.ToString()); + cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); + + IDataReader result = ExecuteReader(cmd); + + if (result.Read()) + { + ret.PrincipalID = principalID; + UUID scope; + UUID.TryParse(result["ScopeID"].ToString(), out scope); + ret.ScopeID = scope; + + if (m_ColumnNames == null) + { + m_ColumnNames = new List(); + + DataTable schemaTable = result.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + + foreach (string s in m_ColumnNames) + { + if (s == "UUID") + continue; + if (s == "ScopeID") + continue; + + ret.Data[s] = result[s].ToString(); + } + + result.Close(); + CloseReaderCommand(cmd); + + return ret; + } + + result.Close(); + CloseReaderCommand(cmd); + + return null; + } + + public bool Store(UserAccountData data) + { + if (data.Data.ContainsKey("UUID")) + data.Data.Remove("UUID"); + if (data.Data.ContainsKey("ScopeID")) + data.Data.Remove("ScopeID"); + + string[] fields = new List(data.Data.Keys).ToArray(); + + MySqlCommand cmd = new MySqlCommand(); + + string update = "update `"+m_Realm+"` set "; + bool first = true; + foreach (string field in fields) + { + if (!first) + update += ", "; + update += "`" + field + "` = ?"+field; + + first = false; + + cmd.Parameters.AddWithValue("?"+field, data.Data[field]); + } + + update += " where UUID = ?principalID"; + + if (data.ScopeID != UUID.Zero) + update += " and ScopeID = ?scopeID"; + + cmd.CommandText = update; + cmd.Parameters.AddWithValue("?principalID", data.PrincipalID.ToString()); + cmd.Parameters.AddWithValue("?scopeID", data.ScopeID.ToString()); + + if (ExecuteNonQuery(cmd) < 1) + { + string insert = "insert into `" + m_Realm + "` (`UUID`, `ScopeID`, `" + + String.Join("`, `", fields) + + "`) values ( ?principalID, ?scopeID, ?" + String.Join(", ?", fields) + ")"; + + cmd.CommandText = insert; + + if (ExecuteNonQuery(cmd) < 1) + { + cmd.Dispose(); + return false; + } + } + + cmd.Dispose(); + + return true; + } + + public bool SetDataItem(UUID principalID, string item, string value) + { + MySqlCommand cmd = new MySqlCommand("update `" + m_Realm + + "` set `" + item + "` = ?" + item + " where UUID = ?UUID"); + + + cmd.Parameters.AddWithValue("?"+item, value); + cmd.Parameters.AddWithValue("?UUID", principalID.ToString()); + + if (ExecuteNonQuery(cmd) > 0) + return true; + + return false; + } + } +} diff --git a/OpenSim/Data/MySQL/Resources/008_UserStore.sql b/OpenSim/Data/MySQL/Resources/008_UserStore.sql new file mode 100644 index 0000000000..4500bd5d7b --- /dev/null +++ b/OpenSim/Data/MySQL/Resources/008_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE users add scopeID char(36) not null default '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs b/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs index 44f44fec84..63e09ae401 100644 --- a/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs +++ b/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs @@ -78,6 +78,7 @@ namespace OpenSim.Framework.RegionLoader.Filesystem foreach (IConfig config in source.Configs) { + //m_log.Info("[REGIONLOADERFILESYSTEM]: Creating RegionInfo for " + config.Name); RegionInfo regionInfo = new RegionInfo("REGION CONFIG #" + (i + 1), file, false, m_configSource, config.Name); regionInfos.Add(regionInfo); i++; diff --git a/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs b/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs index 381070ee82..80f2e79418 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs @@ -59,7 +59,7 @@ namespace OpenSim.Region.Communications.Hypergrid HGUserServices userServices = new HGUserServices(this); // This plugin arrangement could eventually be configurable rather than hardcoded here. userServices.AddPlugin(new TemporaryUserProfilePlugin()); - userServices.AddPlugin(new OGS1UserDataPlugin(this)); + userServices.AddPlugin(new HGUserDataPlugin(this, userServices)); m_userService = userServices; m_messageService = userServices; diff --git a/OpenSim/Region/Communications/Hypergrid/HGCommunicationsStandalone.cs b/OpenSim/Region/Communications/Hypergrid/HGCommunicationsStandalone.cs index 568437de8d..e4e12d4b7a 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGCommunicationsStandalone.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGCommunicationsStandalone.cs @@ -57,7 +57,7 @@ namespace OpenSim.Region.Communications.Hypergrid HGUserServices hgUserService = new HGUserServices(this, localUserService); // This plugin arrangement could eventually be configurable rather than hardcoded here. hgUserService.AddPlugin(new TemporaryUserProfilePlugin()); - hgUserService.AddPlugin(new OGS1UserDataPlugin(this)); + hgUserService.AddPlugin(new HGUserDataPlugin(this, hgUserService)); m_userService = hgUserService; m_userAdminService = hgUserService; diff --git a/OpenSim/Region/Communications/Hypergrid/HGUserDataPlugin.cs b/OpenSim/Region/Communications/Hypergrid/HGUserDataPlugin.cs new file mode 100644 index 0000000000..4b8fc26122 --- /dev/null +++ b/OpenSim/Region/Communications/Hypergrid/HGUserDataPlugin.cs @@ -0,0 +1,72 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Xml.Serialization; +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Clients; +using OpenSim.Region.Communications.OGS1; + +namespace OpenSim.Region.Communications.Hypergrid +{ + public class HGUserDataPlugin : OGS1UserDataPlugin + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + HGUserServices m_UserServices; + + public HGUserDataPlugin() + { + } + + public HGUserDataPlugin(CommunicationsManager commsManager, HGUserServices userServices) + { + m_log.DebugFormat("[HG USER SERVICES]: {0} initialized", Name); + m_commsManager = commsManager; + m_UserServices = userServices; + } + + protected override string GetUserServerURL(UUID userID) + { + string url = string.Empty; + if (m_UserServices.IsForeignUser(userID, out url)) + return url; + return m_commsManager.NetworkServersInfo.UserURL; + } + + } +} diff --git a/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs b/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs index 68a90764b0..f1a56ef64c 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs @@ -311,9 +311,9 @@ namespace OpenSim.Region.Communications.Hypergrid return m_commsManager.NetworkServersInfo.UserURL; } - private bool IsForeignUser(UUID userID, out string userServerURL) + public bool IsForeignUser(UUID userID, out string userServerURL) { - userServerURL = string.Empty; + userServerURL = m_commsManager.NetworkServersInfo.UserURL; CachedUserInfo uinfo = m_commsManager.UserProfileCacheService.GetUserDetails(userID); if (uinfo != null) { diff --git a/OpenSim/Region/Communications/OGS1/OGS1UserDataPlugin.cs b/OpenSim/Region/Communications/OGS1/OGS1UserDataPlugin.cs index 9f234bea89..ec8512aff8 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1UserDataPlugin.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1UserDataPlugin.cs @@ -48,6 +48,10 @@ namespace OpenSim.Region.Communications.OGS1 protected CommunicationsManager m_commsManager; + public OGS1UserDataPlugin() + { + } + public OGS1UserDataPlugin(CommunicationsManager commsManager) { m_log.DebugFormat("[OGS1 USER SERVICES]: {0} initialized", Name); @@ -108,7 +112,7 @@ namespace OpenSim.Region.Communications.OGS1 parameters.Add(param); XmlRpcRequest req = new XmlRpcRequest("get_agent_by_uuid", parameters); - XmlRpcResponse resp = req.Send(GetUserServerURL(userId), 6000); + XmlRpcResponse resp = req.Send(m_commsManager.NetworkServersInfo.UserURL, 6000); Hashtable respData = (Hashtable)resp.Value; if (respData.Contains("error_type")) { @@ -603,7 +607,7 @@ namespace OpenSim.Region.Communications.OGS1 { if ((string)respData["returnString"] == "TRUE") { - + m_log.DebugFormat("[OGS1 USER SERVICES]: Updated user appearance in {0}", GetUserServerURL(user)); } else { @@ -622,8 +626,8 @@ namespace OpenSim.Region.Communications.OGS1 } catch (WebException e) { - m_log.Warn("[OGS1 USER SERVICES]: Error when trying to update Avatar's appearance: " + - e.Message); + m_log.WarnFormat("[OGS1 USER SERVICES]: Error when trying to update Avatar's appearance in {0}: {1}", + GetUserServerURL(user), e.Message); // Return Empty list (no friends) } } diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs index a5894c6d5a..613dbe942d 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs @@ -34,6 +34,7 @@ using System.Text.RegularExpressions; using log4net; using Nini.Config; using OpenMetaverse; +using Nwc.XmlRpc; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Services; @@ -115,6 +116,8 @@ namespace OpenSim.Region.CoreModules.Hypergrid httpServer.AddXmlRPCHandler("hg_login", m_loginService.XmlRpcLoginMethod); httpServer.AddXmlRPCHandler("check_auth_session", m_loginService.XmlRPCCheckAuthSession, false); + httpServer.AddXmlRPCHandler("get_avatar_appearance", XmlRPCGetAvatarAppearance); + httpServer.AddXmlRPCHandler("update_avatar_appearance", XmlRPCUpdateAvatarAppearance); } } @@ -256,5 +259,64 @@ namespace OpenSim.Region.CoreModules.Hypergrid scene = null; return false; } + + public XmlRpcResponse XmlRPCGetAvatarAppearance(XmlRpcRequest request, IPEndPoint remoteClient) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + AvatarAppearance appearance; + Hashtable responseData; + if (requestData.Contains("owner")) + { + appearance = m_firstScene.CommsManager.AvatarService.GetUserAppearance(new UUID((string)requestData["owner"])); + if (appearance == null) + { + responseData = new Hashtable(); + responseData["error_type"] = "no appearance"; + responseData["error_desc"] = "There was no appearance found for this avatar"; + } + else + { + responseData = appearance.ToHashTable(); + } + } + else + { + responseData = new Hashtable(); + responseData["error_type"] = "unknown_avatar"; + responseData["error_desc"] = "The avatar appearance requested is not in the database"; + } + + response.Value = responseData; + return response; + } + + public XmlRpcResponse XmlRPCUpdateAvatarAppearance(XmlRpcRequest request, IPEndPoint remoteClient) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData; + if (requestData.Contains("owner")) + { + AvatarAppearance appearance = new AvatarAppearance(requestData); + + // TODO: Sometime in the future we may have a database layer that is capable of updating appearance when + // the TextureEntry is null. When that happens, this check can be removed + if (appearance.Texture != null) + m_firstScene.CommsManager.AvatarService.UpdateUserAppearance(new UUID((string)requestData["owner"]), appearance); + + responseData = new Hashtable(); + responseData["returnString"] = "TRUE"; + } + else + { + responseData = new Hashtable(); + responseData["error_type"] = "unknown_avatar"; + responseData["error_desc"] = "The avatar appearance requested is not in the database"; + } + response.Value = responseData; + return response; + } } + } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/LocalUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/LocalUserServiceConnector.cs index fcd030400e..cca5bb4f6f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/LocalUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/LocalUserServiceConnector.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - private IUserAccountDataService m_UserService; + private IUserAccountService m_UserService; private bool m_Enabled = false; @@ -82,7 +82,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User Object[] args = new Object[] { source }; m_UserService = - ServerUtils.LoadPlugin(serviceDll, + ServerUtils.LoadPlugin(serviceDll, args); if (m_UserService == null) @@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User if (!m_Enabled) return; - scene.RegisterModuleInterface(m_UserService); + scene.RegisterModuleInterface(m_UserService); } public void RemoveRegion(Scene scene) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/RemoteUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/RemoteUserServiceConnector.cs index a2b854b992..cef9129b29 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/RemoteUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/RemoteUserServiceConnector.cs @@ -37,7 +37,7 @@ using OpenSim.Services.Connectors; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User { public class RemoteUserServicesConnector : UserServicesConnector, - ISharedRegionModule, IUserAccountDataService + ISharedRegionModule, IUserAccountService { private static readonly ILog m_log = LogManager.GetLogger( @@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User if (!m_Enabled) return; - scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); } public void RemoveRegion(Scene scene) diff --git a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs index 5c5f1649fb..9da869cb92 100644 --- a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs @@ -32,6 +32,7 @@ using log4net; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Framework.Client; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -71,6 +72,18 @@ namespace OpenSim.Region.CoreModules.World.Land public void AddRegion(Scene scene) { + + + } + + public void RemoveRegion(Scene scene) + { + + + } + + public void RegionLoaded(Scene scene) + { if (!enabledYN) return; @@ -295,8 +308,8 @@ namespace OpenSim.Region.CoreModules.World.Land m_log.DebugFormat("Scene: {0} to the west of Scene{1} Offset: {2}. Extents:{3}", conn.RegionScene.RegionInfo.RegionName, regionConnections.RegionScene.RegionInfo.RegionName, offset, extents); - - + + scene.BordersLocked = true; conn.RegionScene.BordersLocked = true; @@ -325,9 +338,11 @@ namespace OpenSim.Region.CoreModules.World.Land // scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); - + conn.RegionScene.BordersLocked = false; scene.BordersLocked = false; + if (conn.ClientEventForwarder != null) + conn.ClientEventForwarder.AddSceneToEventForwarding(scene); connectedYN = true; break; } @@ -367,7 +382,7 @@ namespace OpenSim.Region.CoreModules.World.Land m_log.DebugFormat("Scene: {0} to the northeast of Scene{1} Offset: {2}. Extents:{3}", conn.RegionScene.RegionInfo.RegionName, regionConnections.RegionScene.RegionInfo.RegionName, offset, extents); - conn.RegionScene.PhysicsScene.Combine(null,Vector3.Zero,extents); + conn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, Vector3.Zero); lock (conn.RegionScene.NorthBorders) @@ -386,7 +401,8 @@ namespace OpenSim.Region.CoreModules.World.Land scene.BordersLocked = false; conn.RegionScene.BordersLocked = false; - + if (conn.ClientEventForwarder != null) + conn.ClientEventForwarder.AddSceneToEventForwarding(scene); connectedYN = true; break; } @@ -424,52 +440,52 @@ namespace OpenSim.Region.CoreModules.World.Land m_log.DebugFormat("Scene: {0} to the NorthEast of Scene{1} Offset: {2}. Extents:{3}", conn.RegionScene.RegionInfo.RegionName, regionConnections.RegionScene.RegionInfo.RegionName, offset, extents); - + conn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, Vector3.Zero); lock (conn.RegionScene.NorthBorders) - if (conn.RegionScene.NorthBorders.Count == 1)// && 2) - { - //compound border - // already locked above - conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize; + if (conn.RegionScene.NorthBorders.Count == 1)// && 2) + { + //compound border + // already locked above + conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize; - lock (conn.RegionScene.EastBorders) - conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize; - lock (conn.RegionScene.WestBorders) - conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize; + lock (conn.RegionScene.EastBorders) + conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize; + lock (conn.RegionScene.WestBorders) + conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize; - - } + + } lock (scene.SouthBorders) scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south - + lock (conn.RegionScene.EastBorders) - if (conn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2) - { + if (conn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2) + { - conn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize; - lock (conn.RegionScene.NorthBorders) - conn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize; - lock (conn.RegionScene.SouthBorders) - conn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize; + conn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize; + lock (conn.RegionScene.NorthBorders) + conn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize; + lock (conn.RegionScene.SouthBorders) + conn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize; - - } + + } lock (scene.WestBorders) scene.WestBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport West -/* - else - { - conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize; - conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize; - conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize; - scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south - } -*/ - + /* + else + { + conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize; + conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize; + conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize; + scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south + } + */ + // Reset Terrain.. since terrain normally loads first. //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); @@ -478,6 +494,9 @@ namespace OpenSim.Region.CoreModules.World.Land scene.BordersLocked = false; conn.RegionScene.BordersLocked = false; + if (conn.ClientEventForwarder != null) + conn.ClientEventForwarder.AddSceneToEventForwarding(scene); + connectedYN = true; //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents); @@ -495,7 +514,8 @@ namespace OpenSim.Region.CoreModules.World.Land rdata.RegionScene = scene; regionConnections.RegionLandChannel = scene.LandChannel; - RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata,scene.LandChannel,regionConnections.ConnectedRegions); + RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata, scene.LandChannel, + regionConnections.ConnectedRegions); scene.LandChannel = lnd; lock (m_regions) { @@ -504,24 +524,157 @@ namespace OpenSim.Region.CoreModules.World.Land ForwardPermissionRequests(regionConnections, r.RegionScene); } } - - m_regions.Add(scene.RegionInfo.originRegionID,regionConnections); + + regionConnections.ClientEventForwarder = new RegionCombinerClientEventForwarder(regionConnections); + scene.EventManager.OnNewPresence += SetCourseLocationDelegate; + m_regions.Add(scene.RegionInfo.originRegionID, regionConnections); + } - + } AdjustLargeRegionBounds(); - } - public void RemoveRegion(Scene scene) + private void SetCourseLocationDelegate(ScenePresence presence) { - + presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); + } + + private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence) + { + RegionConnections connectiondata = null; + lock (m_regions) + { + if (m_regions.ContainsKey(sceneId)) + connectiondata = m_regions[sceneId]; + else + return; + } + + List avatars = connectiondata.RegionScene.GetAvatars(); + List CoarseLocations = new List(); + List AvatarUUIDs = new List(); + for (int i = 0; i < avatars.Count; i++) + { + if (avatars[i].UUID != presence.UUID) + { + if (avatars[i].ParentID != 0) + { + // sitting avatar + SceneObjectPart sop = connectiondata.RegionScene.GetSceneObjectPart(avatars[i].ParentID); + if (sop != null) + { + CoarseLocations.Add(sop.AbsolutePosition + avatars[i].AbsolutePosition); + AvatarUUIDs.Add(avatars[i].UUID); + } + else + { + // we can't find the parent.. ! arg! + CoarseLocations.Add(avatars[i].AbsolutePosition); + AvatarUUIDs.Add(avatars[i].UUID); + } + } + else + { + CoarseLocations.Add(avatars[i].AbsolutePosition); + AvatarUUIDs.Add(avatars[i].UUID); + } + } + } + DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); + } + + private void DistributeCourseLocationUpdates(List locations, List uuids, + RegionConnections connectiondata, ScenePresence rootPresence) + { + RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); + List clients = new List(); + Dictionary updates = new Dictionary(); + + + // Root Region entry + RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); + rootupdatedata.Locations = new List(); + rootupdatedata.Uuids = new List(); + rootupdatedata.Offset = Vector2.Zero; + + rootupdatedata.UserAPI = rootPresence.ControllingClient; + + if (rootupdatedata.UserAPI != null) + updates.Add(Vector2.Zero, rootupdatedata); + + //Each Region needs an entry or we will end up with dead minimap dots + foreach (RegionData regiondata in rdata) + { + Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); + RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); + updatedata.Locations = new List(); + updatedata.Uuids = new List(); + updatedata.Offset = offset; + + if (offset == Vector2.Zero) + updatedata.UserAPI = rootPresence.ControllingClient; + else + updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata); + + if (updatedata.UserAPI != null) + updates.Add(offset, updatedata); + } + + // go over the locations and assign them to an IClientAPI + for (int i = 0; i < locations.Count;i++ ) + //{locations[i]/(int) Constants.RegionSize; + { + Vector3 pPosition = new Vector3((int)locations[i].X / (int)Constants.RegionSize, + (int)locations[i].Y / (int)Constants.RegionSize, locations[i].Z); + Vector2 offset = new Vector2(pPosition.X*(int) Constants.RegionSize, + pPosition.Y*(int) Constants.RegionSize); + if (!updates.ContainsKey(offset)) + { + // This shouldn't happen + RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); + updatedata.Locations = new List(); + updatedata.Uuids = new List(); + updatedata.Offset = offset; + + if (offset == Vector2.Zero) + updatedata.UserAPI = rootPresence.ControllingClient; + else + updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata); + + updates.Add(offset,updatedata); + + } + + updates[offset].Locations.Add(locations[i]); + updates[offset].Uuids.Add(uuids[i]); + + } + + // Send out the CoarseLocationupdates from their respective client connection based on where the avatar is + foreach (Vector2 offset in updates.Keys) + { + if (updates[offset].UserAPI != null) + { + updates[offset].UserAPI.SendCoarseLocationUpdate(updates[offset].Uuids,updates[offset].Locations); + } + } + } - public void RegionLoaded(Scene scene) + private IClientAPI LocateUsersChildAgentIClientAPI(Vector2 offset, UUID uUID, RegionData[] rdata) { - + IClientAPI returnclient = null; + foreach (RegionData r in rdata) + { + if (r.Offset.X == offset.X && r.Offset.Y == offset.Y) + { + return r.RegionScene.SceneGraph.GetControllingClient(uUID); + } + } + + return returnclient; } public void PostInitialise() @@ -529,6 +682,8 @@ namespace OpenSim.Region.CoreModules.World.Land } + + public void UnCombineRegion(RegionData rdata) { lock (m_regions) @@ -733,6 +888,7 @@ namespace OpenSim.Region.CoreModules.World.Land public int YEnd; public List ConnectedRegions; public RegionCombinerPermissionModule PermissionModule; + public RegionCombinerClientEventForwarder ClientEventForwarder; public void UpdateExtents(Vector3 extents) { XEnd = (int)extents.X; @@ -748,6 +904,13 @@ namespace OpenSim.Region.CoreModules.World.Land public Vector3 Offset; } + struct RegionCourseLocationStruct + { + public List Locations; + public List Uuids; + public IClientAPI UserAPI; + public Vector2 Offset; + } public class RegionCombinerLargeLandChannel : ILandChannel { @@ -759,7 +922,8 @@ namespace OpenSim.Region.CoreModules.World.Land #region ILandChannel Members - public RegionCombinerLargeLandChannel(RegionData regData, ILandChannel rootRegionLandChannel,List regionConnections) + public RegionCombinerLargeLandChannel(RegionData regData, ILandChannel rootRegionLandChannel, + List regionConnections) { RegData = regData; RootRegionLandChannel = rootRegionLandChannel; @@ -790,7 +954,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { int offsetX = (x / (int)Constants.RegionSize); - int offsetY = (x / (int)Constants.RegionSize); + int offsetY = (y / (int)Constants.RegionSize); offsetX *= (int)Constants.RegionSize; offsetY *= (int)Constants.RegionSize; @@ -823,7 +987,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { int offsetX = (int)(x/(int) Constants.RegionSize); - int offsetY = (int)(x/(int) Constants.RegionSize); + int offsetY = (int)(y/(int) Constants.RegionSize); offsetX *= (int) Constants.RegionSize; offsetY *= (int) Constants.RegionSize; @@ -886,6 +1050,7 @@ namespace OpenSim.Region.CoreModules.World.Land m_rootScene = RootScene; } + #region Permission Override public bool BypassPermissions() { return m_rootScene.Permissions.BypassPermissions(); @@ -1110,5 +1275,137 @@ namespace OpenSim.Region.CoreModules.World.Land { return m_rootScene.Permissions.CanUseObjectReturn(landdata, type, client, retlist); } + #endregion + } + + public class RegionCombinerClientEventForwarder + { + private Scene m_rootScene; + private Dictionary m_virtScene = new Dictionary(); + private Dictionary m_forwarders = new Dictionary(); + public RegionCombinerClientEventForwarder(RegionConnections rootScene) + { + m_rootScene = rootScene.RegionScene; + + + } + + public void AddSceneToEventForwarding( Scene virtualScene ) + { + lock (m_virtScene) + { + if (m_virtScene.ContainsKey(virtualScene.RegionInfo.originRegionID)) + { + m_virtScene[virtualScene.RegionInfo.originRegionID] = virtualScene; + } + else + { + m_virtScene.Add(virtualScene.RegionInfo.originRegionID, virtualScene); + } + } + + lock (m_forwarders) + { + // TODO: Fix this to unregister if this happens + if (m_forwarders.ContainsKey(virtualScene.RegionInfo.originRegionID)) + m_forwarders.Remove(virtualScene.RegionInfo.originRegionID); + + RegionCombinerModuleIndividualForwarder forwarder = + new RegionCombinerModuleIndividualForwarder(m_rootScene, virtualScene); + m_forwarders.Add(virtualScene.RegionInfo.originRegionID, forwarder); + + virtualScene.EventManager.OnNewClient += forwarder.ClientConnect; + virtualScene.EventManager.OnClientClosed += forwarder.ClientClosed; + } + } + + public void RemoveSceneFromEventForwarding (Scene virtualScene) + { + lock (m_forwarders) + { + RegionCombinerModuleIndividualForwarder forwarder = m_forwarders[virtualScene.RegionInfo.originRegionID]; + virtualScene.EventManager.OnNewClient -= forwarder.ClientConnect; + virtualScene.EventManager.OnClientClosed -= forwarder.ClientClosed; + m_forwarders.Remove(virtualScene.RegionInfo.originRegionID); + } + lock (m_virtScene) + { + if (m_virtScene.ContainsKey(virtualScene.RegionInfo.originRegionID)) + { + m_virtScene.Remove(virtualScene.RegionInfo.originRegionID); + } + } + } + } + + public class RegionCombinerModuleIndividualForwarder + { + private Scene m_rootScene; + private Scene m_virtScene; + public RegionCombinerModuleIndividualForwarder(Scene rootScene, Scene virtScene) + { + m_rootScene = rootScene; + m_virtScene = virtScene; + } + + public void ClientConnect(IClientAPI client) + { + + m_virtScene.UnSubscribeToClientPrimEvents(client); + m_virtScene.UnSubscribeToClientPrimRezEvents(client); + m_virtScene.UnSubscribeToClientInventoryEvents(client); + m_virtScene.UnSubscribeToClientAttachmentEvents(client); + m_virtScene.UnSubscribeToClientTeleportEvents(client); + m_virtScene.UnSubscribeToClientScriptEvents(client); + m_virtScene.UnSubscribeToClientGodEvents(client); + m_virtScene.UnSubscribeToClientNetworkEvents(client); + + m_rootScene.SubscribeToClientPrimEvents(client); + client.OnAddPrim += LocalAddNewPrim; + client.OnRezObject += LocalRezObject; + m_rootScene.SubscribeToClientInventoryEvents(client); + m_rootScene.SubscribeToClientAttachmentEvents(client); + m_rootScene.SubscribeToClientTeleportEvents(client); + m_rootScene.SubscribeToClientScriptEvents(client); + m_rootScene.SubscribeToClientGodEvents(client); + m_rootScene.SubscribeToClientNetworkEvents(client); + } + public void ClientClosed(UUID clientid, Scene scene) + { + + } + + + private void LocalRezObject(IClientAPI remoteclient, UUID itemid, Vector3 rayend, Vector3 raystart, + UUID raytargetid, byte bypassraycast, bool rayendisintersection, bool rezselected, bool removeitem, + UUID fromtaskid) + { + int differenceX = (int)m_virtScene.RegionInfo.RegionLocX - (int)m_rootScene.RegionInfo.RegionLocX; + int differenceY = (int)m_virtScene.RegionInfo.RegionLocY - (int)m_rootScene.RegionInfo.RegionLocY; + rayend.X += differenceX * (int)Constants.RegionSize; + rayend.Y += differenceY * (int)Constants.RegionSize; + raystart.X += differenceX * (int)Constants.RegionSize; + raystart.Y += differenceY * (int)Constants.RegionSize; + + m_rootScene.RezObject(remoteclient, itemid, rayend, raystart, raytargetid, bypassraycast, + rayendisintersection, rezselected, removeitem, fromtaskid); + + } + + private void LocalAddNewPrim(UUID ownerid, UUID groupid, Vector3 rayend, Quaternion rot, + PrimitiveBaseShape shape, byte bypassraycast, Vector3 raystart, UUID raytargetid, + byte rayendisintersection) + { + int differenceX = (int)m_virtScene.RegionInfo.RegionLocX - (int)m_rootScene.RegionInfo.RegionLocX; + int differenceY = (int)m_virtScene.RegionInfo.RegionLocY - (int)m_rootScene.RegionInfo.RegionLocY; + rayend.X += differenceX * (int)Constants.RegionSize; + rayend.Y += differenceY * (int)Constants.RegionSize; + raystart.X += differenceX * (int)Constants.RegionSize; + raystart.Y += differenceY * (int)Constants.RegionSize; + m_rootScene.AddNewPrim(ownerid, groupid, rayend, rot, shape, bypassraycast, raystart, raytargetid, + rayendisintersection); + + } } } diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs index dd6928f5af..8fe3565be5 100644 --- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs @@ -113,26 +113,26 @@ namespace OpenSim.Region.Framework.Scenes.Hypergrid UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { - //m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); + m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); - if (fromTaskID.Equals(UUID.Zero)) + //if (fromTaskID.Equals(UUID.Zero)) + //{ + InventoryItemBase item = new InventoryItemBase(itemID); + item.Owner = remoteClient.AgentId; + item = InventoryService.GetItem(item); + //if (item == null) + //{ // Fetch the item + // item = new InventoryItemBase(); + // item.Owner = remoteClient.AgentId; + // item.ID = itemID; + // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo); + //} + if (item != null) { - InventoryItemBase item = new InventoryItemBase(itemID); - item.Owner = remoteClient.AgentId; - item = InventoryService.GetItem(item); - //if (item == null) - //{ // Fetch the item - // item = new InventoryItemBase(); - // item.Owner = remoteClient.AgentId; - // item.ID = itemID; - // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo); - //} - if (item != null) - { - m_assMapper.Get(item.AssetID, remoteClient.AgentId); + m_assMapper.Get(item.AssetID, remoteClient.AgentId); - } } + //} // OK, we're done fetching. Pass it up to the default RezObject return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1d0da4cad9..3b91dd0b8f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -220,11 +220,12 @@ namespace OpenSim.Region.Framework.Scenes private bool m_scripts_enabled = true; private string m_defaultScriptEngine; private int m_LastLogin = 0; - private Thread HeartbeatThread; + private Thread HeartbeatThread = null; private volatile bool shuttingdown = false; private int m_lastUpdate = Environment.TickCount; private int m_maxPrimsPerFrame = 200; + private bool m_firstHeartbeat = true; private object m_deleting_scene_object = new object(); @@ -876,6 +877,13 @@ namespace OpenSim.Region.Framework.Scenes //m_heartbeatTimer.Enabled = true; //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); + if (HeartbeatThread != null) + { + ThreadTracker.Remove(HeartbeatThread); + HeartbeatThread.Abort(); + HeartbeatThread = null; + } + m_lastUpdate = Environment.TickCount; HeartbeatThread = new Thread(new ParameterizedThreadStart(Heartbeat)); HeartbeatThread.SetApartmentState(ApartmentState.MTA); HeartbeatThread.Name = string.Format("Heartbeat for region {0}", RegionInfo.RegionName); @@ -912,9 +920,16 @@ namespace OpenSim.Region.Framework.Scenes /// private void Heartbeat(object sender) { - Update(); + try + { + Update(); - m_lastUpdate = Environment.TickCount; + m_lastUpdate = Environment.TickCount; + m_firstHeartbeat = false; + } + catch (ThreadAbortException) + { + } } /// @@ -2307,6 +2322,7 @@ namespace OpenSim.Region.Framework.Scenes /// public override void AddNewClient(IClientAPI client) { + CheckHeartbeat(); SubscribeToClientEvents(client); ScenePresence presence; @@ -2365,14 +2381,40 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnNewClient(client); } + + /// /// Register for events from the client /// /// The IClientAPI of the connected client - protected virtual void SubscribeToClientEvents(IClientAPI client) + public virtual void SubscribeToClientEvents(IClientAPI client) + { + SubscribeToClientTerrainEvents(client); + SubscribeToClientPrimEvents(client); + SubscribeToClientPrimRezEvents(client); + SubscribeToClientInventoryEvents(client); + SubscribeToClientAttachmentEvents(client); + SubscribeToClientTeleportEvents(client); + SubscribeToClientScriptEvents(client); + SubscribeToClientParcelEvents(client); + SubscribeToClientGridEvents(client); + SubscribeToClientGodEvents(client); + + SubscribeToClientNetworkEvents(client); + + + // EventManager.TriggerOnNewClient(client); + } + + public virtual void SubscribeToClientTerrainEvents(IClientAPI client) { client.OnRegionHandShakeReply += SendLayerData; - client.OnAddPrim += AddNewPrim; + client.OnUnackedTerrain += TerrainUnAcked; + } + + public virtual void SubscribeToClientPrimEvents(IClientAPI client) + { + client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimPosition; client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimRotation; @@ -2384,8 +2426,6 @@ namespace OpenSim.Region.Framework.Scenes client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam; client.OnUpdatePrimShape += m_sceneGraph.UpdatePrimShape; client.OnUpdatePrimTexture += m_sceneGraph.UpdatePrimTexture; - client.OnTeleportLocationRequest += RequestTeleportLocation; - client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnObjectRequest += RequestPrim; client.OnObjectSelect += SelectPrim; client.OnObjectDeselect += DeselectPrim; @@ -2393,15 +2433,7 @@ namespace OpenSim.Region.Framework.Scenes client.OnSpinStart += m_sceneGraph.SpinStart; client.OnSpinUpdate += m_sceneGraph.SpinObject; client.OnDeRezObject += DeRezObject; - client.OnRezObject += RezObject; - client.OnRezSingleAttachmentFromInv += RezSingleAttachment; - client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; - client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv; - client.OnObjectAttach += m_sceneGraph.AttachObject; - client.OnObjectDetach += m_sceneGraph.DetachObject; - client.OnObjectDrop += m_sceneGraph.DropObject; - client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest; - client.OnObjectDescription += m_sceneGraph.PrimDescription; + client.OnObjectName += m_sceneGraph.PrimName; client.OnObjectClickAction += m_sceneGraph.PrimClickAction; client.OnObjectMaterial += m_sceneGraph.PrimMaterial; @@ -2412,7 +2444,24 @@ namespace OpenSim.Region.Framework.Scenes client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; client.OnObjectPermissions += HandleObjectPermissionsUpdate; + client.OnGrabObject += ProcessObjectGrab; + client.OnDeGrabObject += ProcessObjectDeGrab; + client.OnUndo += m_sceneGraph.HandleUndo; + client.OnObjectDescription += m_sceneGraph.PrimDescription; + client.OnObjectDrop += m_sceneGraph.DropObject; + client.OnObjectSaleInfo += ObjectSaleInfo; + client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; + client.OnObjectOwner += ObjectOwner; + } + public virtual void SubscribeToClientPrimRezEvents(IClientAPI client) + { + client.OnAddPrim += AddNewPrim; + client.OnRezObject += RezObject; + } + + public virtual void SubscribeToClientInventoryEvents(IClientAPI client) + { client.OnCreateNewInventoryItem += CreateNewInventoryItem; client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; @@ -2430,36 +2479,217 @@ namespace OpenSim.Region.Framework.Scenes client.OnRemoveTaskItem += RemoveTaskInventory; client.OnUpdateTaskInventory += UpdateTaskInventory; client.OnMoveTaskItem += ClientMoveTaskInventoryItem; + } - client.OnGrabObject += ProcessObjectGrab; - client.OnDeGrabObject += ProcessObjectDeGrab; - client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; - client.OnParcelBuy += ProcessParcelBuy; - client.OnAvatarPickerRequest += ProcessAvatarPickerRequest; - client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; + public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) + { + client.OnRezSingleAttachmentFromInv += RezSingleAttachment; + client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; + client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv; + client.OnObjectAttach += m_sceneGraph.AttachObject; + client.OnObjectDetach += m_sceneGraph.DetachObject; + } + + public virtual void SubscribeToClientTeleportEvents(IClientAPI client) + { + client.OnTeleportLocationRequest += RequestTeleportLocation; + client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnTeleportHomeRequest += TeleportClientHome; - client.OnSetStartLocationRequest += SetHomeRezPoint; - client.OnUndo += m_sceneGraph.HandleUndo; - client.OnObjectGroupRequest += m_sceneGraph.HandleObjectGroupUpdate; - client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; - client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; - client.OnObjectSaleInfo += ObjectSaleInfo; + } + + public virtual void SubscribeToClientScriptEvents(IClientAPI client) + { client.OnScriptReset += ProcessScriptReset; client.OnGetScriptRunning += GetScriptRunning; client.OnSetScriptRunning += SetScriptRunning; - client.OnRegionHandleRequest += RegionHandleRequest; - client.OnUnackedTerrain += TerrainUnAcked; - client.OnObjectOwner += ObjectOwner; + } + public virtual void SubscribeToClientParcelEvents(IClientAPI client) + { + client.OnObjectGroupRequest += m_sceneGraph.HandleObjectGroupUpdate; + client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; + client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; + client.OnParcelBuy += ProcessParcelBuy; + } + + public virtual void SubscribeToClientGridEvents(IClientAPI client) + { + client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest; + client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; + client.OnAvatarPickerRequest += ProcessAvatarPickerRequest; + client.OnSetStartLocationRequest += SetHomeRezPoint; + client.OnRegionHandleRequest += RegionHandleRequest; + } + + public virtual void SubscribeToClientGodEvents(IClientAPI client) + { IGodsModule godsModule = RequestModuleInterface(); client.OnGodKickUser += godsModule.KickUser; client.OnRequestGodlikePowers += godsModule.RequestGodlikePowers; + } + public virtual void SubscribeToClientNetworkEvents(IClientAPI client) + { client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; + } + + protected virtual void UnsubscribeToClientEvents(IClientAPI client) + { + + } + + /// + /// Register for events from the client + /// + /// The IClientAPI of the connected client + public virtual void UnSubscribeToClientEvents(IClientAPI client) + { + UnSubscribeToClientTerrainEvents(client); + UnSubscribeToClientPrimEvents(client); + UnSubscribeToClientPrimRezEvents(client); + UnSubscribeToClientInventoryEvents(client); + UnSubscribeToClientAttachmentEvents(client); + UnSubscribeToClientTeleportEvents(client); + UnSubscribeToClientScriptEvents(client); + UnSubscribeToClientParcelEvents(client); + UnSubscribeToClientGridEvents(client); + UnSubscribeToClientGodEvents(client); + + UnSubscribeToClientNetworkEvents(client); + // EventManager.TriggerOnNewClient(client); } + public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) + { + client.OnRegionHandShakeReply -= SendLayerData; + client.OnUnackedTerrain -= TerrainUnAcked; + } + + public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) + { + client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimPosition; + client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; + client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimRotation; + client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimRotation; + client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; + client.OnUpdatePrimSingleRotationPosition -= m_sceneGraph.UpdatePrimSingleRotationPosition; + client.OnUpdatePrimScale -= m_sceneGraph.UpdatePrimScale; + client.OnUpdatePrimGroupScale -= m_sceneGraph.UpdatePrimGroupScale; + client.OnUpdateExtraParams -= m_sceneGraph.UpdateExtraParam; + client.OnUpdatePrimShape -= m_sceneGraph.UpdatePrimShape; + client.OnUpdatePrimTexture -= m_sceneGraph.UpdatePrimTexture; + client.OnObjectRequest -= RequestPrim; + client.OnObjectSelect -= SelectPrim; + client.OnObjectDeselect -= DeselectPrim; + client.OnGrabUpdate -= m_sceneGraph.MoveObject; + client.OnSpinStart -= m_sceneGraph.SpinStart; + client.OnSpinUpdate -= m_sceneGraph.SpinObject; + client.OnDeRezObject -= DeRezObject; + client.OnObjectName -= m_sceneGraph.PrimName; + client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; + client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; + client.OnLinkObjects -= m_sceneGraph.LinkObjects; + client.OnDelinkObjects -= m_sceneGraph.DelinkObjects; + client.OnObjectDuplicate -= m_sceneGraph.DuplicateObject; + client.OnObjectDuplicateOnRay -= doObjectDuplicateOnRay; + client.OnUpdatePrimFlags -= m_sceneGraph.UpdatePrimFlags; + client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily; + client.OnObjectPermissions -= HandleObjectPermissionsUpdate; + client.OnGrabObject -= ProcessObjectGrab; + client.OnDeGrabObject -= ProcessObjectDeGrab; + client.OnUndo -= m_sceneGraph.HandleUndo; + client.OnObjectDescription -= m_sceneGraph.PrimDescription; + client.OnObjectDrop -= m_sceneGraph.DropObject; + client.OnObjectSaleInfo -= ObjectSaleInfo; + client.OnObjectIncludeInSearch -= m_sceneGraph.MakeObjectSearchable; + client.OnObjectOwner -= ObjectOwner; + } + + public virtual void UnSubscribeToClientPrimRezEvents(IClientAPI client) + { + client.OnAddPrim -= AddNewPrim; + client.OnRezObject -= RezObject; + } + + + public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) + { + client.OnCreateNewInventoryItem -= CreateNewInventoryItem; + client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; + client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; + client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! + client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; + client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! + client.OnFetchInventory -= HandleFetchInventory; + client.OnUpdateInventoryItem -= UpdateInventoryItemAsset; + client.OnCopyInventoryItem -= CopyInventoryItem; + client.OnMoveInventoryItem -= MoveInventoryItem; + client.OnRemoveInventoryItem -= RemoveInventoryItem; + client.OnRemoveInventoryFolder -= RemoveInventoryFolder; + client.OnRezScript -= RezScript; + client.OnRequestTaskInventory -= RequestTaskInventory; + client.OnRemoveTaskItem -= RemoveTaskInventory; + client.OnUpdateTaskInventory -= UpdateTaskInventory; + client.OnMoveTaskItem -= ClientMoveTaskInventoryItem; + } + + public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) + { + client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; + client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; + client.OnDetachAttachmentIntoInv -= DetachSingleAttachmentToInv; + client.OnObjectAttach -= m_sceneGraph.AttachObject; + client.OnObjectDetach -= m_sceneGraph.DetachObject; + } + + public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client) + { + client.OnTeleportLocationRequest -= RequestTeleportLocation; + client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; + client.OnTeleportHomeRequest -= TeleportClientHome; + } + + public virtual void UnSubscribeToClientScriptEvents(IClientAPI client) + { + client.OnScriptReset -= ProcessScriptReset; + client.OnGetScriptRunning -= GetScriptRunning; + client.OnSetScriptRunning -= SetScriptRunning; + } + + public virtual void UnSubscribeToClientParcelEvents(IClientAPI client) + { + client.OnObjectGroupRequest -= m_sceneGraph.HandleObjectGroupUpdate; + client.OnParcelReturnObjectsRequest -= LandChannel.ReturnObjectsInParcel; + client.OnParcelSetOtherCleanTime -= LandChannel.SetParcelOtherCleanTime; + client.OnParcelBuy -= ProcessParcelBuy; + } + + public virtual void UnSubscribeToClientGridEvents(IClientAPI client) + { + client.OnNameFromUUIDRequest -= CommsManager.HandleUUIDNameRequest; + client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; + client.OnAvatarPickerRequest -= ProcessAvatarPickerRequest; + client.OnSetStartLocationRequest -= SetHomeRezPoint; + client.OnRegionHandleRequest -= RegionHandleRequest; + } + + public virtual void UnSubscribeToClientGodEvents(IClientAPI client) + { + IGodsModule godsModule = RequestModuleInterface(); + client.OnGodKickUser -= godsModule.KickUser; + client.OnRequestGodlikePowers -= godsModule.RequestGodlikePowers; + } + + public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) + { + client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; + } + + + + /// /// Teleport an avatar to their home region /// @@ -2617,6 +2847,7 @@ namespace OpenSim.Region.Framework.Scenes /// protected virtual ScenePresence CreateAndAddScenePresence(IClientAPI client) { + CheckHeartbeat(); AvatarAppearance appearance = null; GetAvatarAppearance(client, out appearance); @@ -2659,6 +2890,7 @@ namespace OpenSim.Region.Framework.Scenes /// public override void RemoveClient(UUID agentID) { + CheckHeartbeat(); bool childagentYN = false; ScenePresence avatar = GetScenePresence(agentID); if (avatar != null) @@ -2926,11 +3158,17 @@ namespace OpenSim.Region.Framework.Scenes if (!agent.child) { - if (agent.startpos.X > (int)Constants.RegionSize - 1) - agent.startpos.X = (int)Constants.RegionSize - 1; + if (TestBorderCross(agent.startpos,Cardinals.E)) + { + Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); + agent.startpos.X = crossedBorder.BorderLine.Z - 1; + } - if (agent.startpos.Y > (int)Constants.RegionSize - 1) - agent.startpos.Y = (int)Constants.RegionSize - 1; + if (TestBorderCross(agent.startpos, Cardinals.N)) + { + Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); + agent.startpos.Y = crossedBorder.BorderLine.Z - 1; + } // Honor parcel landing type and position. ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); @@ -4160,6 +4398,8 @@ namespace OpenSim.Region.Framework.Scenes else return health; + CheckHeartbeat(); + return health; } @@ -4345,5 +4585,14 @@ namespace OpenSim.Region.Framework.Scenes return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; } + + private void CheckHeartbeat() + { + if (m_firstHeartbeat) + return; + + if (System.Environment.TickCount - m_lastUpdate > 2000) + StartTimer(); + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index c6b3f3008f..0827672ec7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -367,6 +367,7 @@ namespace OpenSim.Region.Framework.Scenes string reason = String.Empty; //bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a); + bool regionAccepted = m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a, out reason); if (regionAccepted && newAgent) @@ -384,7 +385,7 @@ namespace OpenSim.Region.Framework.Scenes eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID); eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath); - m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}", + m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}", capsPath, avatar.UUID, avatar.Scene.RegionInfo.RegionName); } else @@ -394,7 +395,9 @@ namespace OpenSim.Region.Framework.Scenes } m_log.Info("[INTERGRID]: Completed inform client about neighbour " + endPoint.ToString()); + } + } public void RequestNeighbors(RegionInfo region) @@ -407,6 +410,65 @@ namespace OpenSim.Region.Framework.Scenes //blah.Port = region.RemotingPort; } + public List RequestNeighbors(Scene pScene, uint pRegionLocX, uint pRegionLocY) + { + Border[] northBorders = pScene.NorthBorders.ToArray(); + Border[] southBorders = pScene.SouthBorders.ToArray(); + Border[] eastBorders = pScene.EastBorders.ToArray(); + Border[] westBorders = pScene.WestBorders.ToArray(); + + // Legacy one region. Provided for simplicity while testing the all inclusive method in the else statement. + if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1) + { + return m_commsProvider.GridService.RequestNeighbours(pRegionLocX, pRegionLocY); + } + else + { + Vector2 extent = Vector2.Zero; + for (int i=0;i extent.X) ? eastBorders[i].BorderLine.Z : extent.X; + } + for (int i=0;i extent.Y) ? northBorders[i].BorderLine.Z : extent.Y; + } + + List neighbourList = new List(); + + // Loss of fraction on purpose + extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1; + extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1; + + int startX = (int) pRegionLocX - 1; + int startY = (int) pRegionLocY - 1; + + int endX = (int) pRegionLocX + (int)extent.X + 1; + int endY = (int) pRegionLocY + (int)extent.Y + 1; + + for (int i=startX;i /// This informs all neighboring regions about agent "avatar". /// Calls an asynchronous method to do so.. so it doesn't lag the sim. @@ -429,7 +491,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_regionInfo != null) { neighbours = - m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); + RequestNeighbors(avatar.Scene,m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); } else { @@ -536,6 +598,16 @@ namespace OpenSim.Region.Framework.Scenes InformClientOfNeighbourCompleted, d); } + + catch (ArgumentOutOfRangeException) + { + m_log.ErrorFormat( + "[REGIONINFO]: Neighbour Regions response included the current region in the neighbor list. The following region will not display to the client: {0} for region {1} ({2}, {3}).", + neighbour.ExternalHostName, + neighbour.RegionHandle, + neighbour.RegionLocX, + neighbour.RegionLocY); + } catch (Exception e) { m_log.ErrorFormat( diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 857dc11267..1024857e29 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -62,6 +62,8 @@ namespace OpenSim.Region.Framework.Scenes public ScriptControlled eventControls; } + public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence); + public class ScenePresence : EntityBase { // ~ScenePresence() @@ -87,12 +89,15 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 lastKnownAllowedPosition; public bool sentMessageAboutRestrictedParcelFlyingDown; + + private bool m_updateflag; private byte m_movementflag; private readonly List m_forcesList = new List(); private short m_updateCount; private uint m_requestedSitTargetID; private UUID m_requestedSitTargetUUID = UUID.Zero; + private SendCourseLocationsMethod m_sendCourseLocationsMethod; private bool m_startAnimationSet; @@ -616,6 +621,7 @@ namespace OpenSim.Region.Framework.Scenes private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) { + m_sendCourseLocationsMethod = SendCoarseLocationsDefault; CreateSceneViewer(); m_regionHandle = reginfo.RegionHandle; m_controllingClient = client; @@ -2457,6 +2463,21 @@ namespace OpenSim.Region.Framework.Scenes } public void SendCoarseLocations() + { + SendCourseLocationsMethod d = m_sendCourseLocationsMethod; + if (d != null) + { + d.Invoke(m_scene.RegionInfo.originRegionID, this); + } + } + + public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) + { + if (d != null) + m_sendCourseLocationsMethod = d; + } + + public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p) { m_perfMonMS = Environment.TickCount; @@ -3302,6 +3323,7 @@ namespace OpenSim.Region.Framework.Scenes { Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); DefaultTexture = textu.GetBytes(); + } public class NewForce @@ -3431,6 +3453,7 @@ namespace OpenSim.Region.Framework.Scenes Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); DefaultTexture = textu.GetBytes(); } + m_sendCourseLocationsMethod = SendCoarseLocationsDefault; CreateSceneViewer(); } diff --git a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs index 2ed177ccb6..8904461a4c 100644 --- a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs +++ b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs @@ -90,31 +90,16 @@ namespace OpenSim.Services.AuthenticationService throw new Exception("Could not find a storage interface in the given module"); } - public virtual byte[] GetPublicKey() - { - return new byte[0]; - } - public bool Verify(UUID principalID, string token, int lifetime) { return m_Database.CheckToken(principalID, token, lifetime); } - public bool VerifyEncrypted(byte[] cyphertext, byte[] key) - { - return false; - } - public virtual bool Release(UUID principalID, string token) { return m_Database.CheckToken(principalID, token, 0); } - public virtual bool ReleaseEncrypted(byte[] cyphertext, byte[] key) - { - return false; - } - protected string GetToken(UUID principalID, int lifetime) { UUID token = UUID.Random(); diff --git a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs index 7fdbbf6eea..6c99b6610b 100644 --- a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs @@ -76,10 +76,5 @@ namespace OpenSim.Services.AuthenticationService return String.Empty; } - - public byte[] AuthenticateEncrypted(byte[] cyphertext, byte[] key) - { - return new byte[0]; - } } } diff --git a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs index 0118c91868..8831c8a0b7 100644 --- a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs @@ -56,10 +56,5 @@ namespace OpenSim.Services.AuthenticationService { return String.Empty; } - - public byte[] AuthenticateEncrypted(byte[] cyphertext, byte[] key) - { - return new byte[0]; - } } } diff --git a/OpenSim/Services/Connectors/User/UserServiceConnector.cs b/OpenSim/Services/Connectors/User/UserServiceConnector.cs index fb03844dad..d4189380d6 100644 --- a/OpenSim/Services/Connectors/User/UserServiceConnector.cs +++ b/OpenSim/Services/Connectors/User/UserServiceConnector.cs @@ -39,7 +39,7 @@ using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class UserServicesConnector : IUserAccountDataService + public class UserServicesConnector : IUserAccountService { private static readonly ILog m_log = LogManager.GetLogger( @@ -81,153 +81,34 @@ namespace OpenSim.Services.Connectors m_ServerURI = serviceURI; } - public UserAccountData GetUserAccountData(UUID scopeID, string firstName, string lastName) + public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) { - string uri = m_ServerURI + "/users/"; - UserAccountData data = new UserAccountData(); - data.FirstName = firstName; - data.LastName = lastName; - data.ScopeID = scopeID; - data.UserID = UUID.Zero; - - try - { - data = SynchronousRestObjectRequester. - MakeRequest("POST", uri, data); - } - catch (Exception e) - { - m_log.WarnFormat("[USER CONNECTOR]: Unable to send request to user server. Reason: {1}", e.Message); - return null; - } - - if (data.UserID == UUID.Zero) - return null; - - return data; + return null; } - public UserAccountData GetUserAccountData(UUID scopeID, UUID userID) + public UserAccount GetUserAccount(UUID scopeID, UUID userID) { - string uri = m_ServerURI + "/users/"; - UserAccountData data = new UserAccountData(); - data.FirstName = String.Empty; - data.LastName = String.Empty; - data.ScopeID = scopeID; - data.UserID = userID; - - try - { - data = SynchronousRestObjectRequester. - MakeRequest("POST", uri, data); - } - catch (Exception e) - { - m_log.WarnFormat("[USER CONNECTOR]: Unable to send request to user server. Reason: {1}", e.Message); - return null; - } - - if (data.UserID == UUID.Zero) - return null; - - return data; + return null; } - public bool SetHomePosition(UserAccountData data, UUID regionID, UUID regionSecret) + public bool SetHomePosition(UserAccount data, UUID regionID, UUID regionSecret) { - string uri = m_ServerURI + "/user/"; - bool result = false; - - UserAccountDataMessage msg = new UserAccountDataMessage(); - - msg.Data = data; - msg.RegionID = regionID; - msg.RegionSecret = regionSecret; - - try - { - result = SynchronousRestObjectRequester. - MakeRequest("POST", uri, msg); - } - catch (Exception e) - { - m_log.WarnFormat("[USER CONNECTOR]: Unable to send request to user server. Reason: {1}", e.Message); - return false; - } - - return result; + return false; } - public bool SetUserAccountData(UserAccountData data, UUID principalID, UUID sessionID) + public bool SetUserAccount(UserAccount data, UUID principalID, string token) { - string uri = m_ServerURI + "/user/"; - bool result = false; - - UserAccountDataMessage msg = new UserAccountDataMessage(); - - msg.Data = data; - msg.PrincipalID = principalID; - msg.SessionID = sessionID; - - try - { - result = SynchronousRestObjectRequester. - MakeRequest("POST", uri, msg); - } - catch (Exception e) - { - m_log.WarnFormat("[USER CONNECTOR]: Unable to send request to user server. Reason: {1}", e.Message); - return false; - } - - return result; + return false; } - public bool CreateUserAccountData(UserAccountData data, UUID principalID, UUID sessionID) + public bool CreateUserAccount(UserAccount data, UUID principalID, string token) { - string uri = m_ServerURI + "/newuser/"; - bool result = false; - - UserAccountDataMessage msg = new UserAccountDataMessage(); - - msg.Data = data; - msg.PrincipalID = principalID; - msg.SessionID = sessionID; - - try - { - result = SynchronousRestObjectRequester. - MakeRequest("POST", uri, msg); - } - catch (Exception e) - { - m_log.WarnFormat("[USER CONNECTOR]: Unable to send request to user server. Reason: {1}", e.Message); - return false; - } - - return result; + return false; } - public List GetUserAccountData(UUID scopeID, string query) + public List GetUserAccount(UUID scopeID, string query) { - string uri = m_ServerURI + "/userlist/"; - UserAccountData data = new UserAccountData(); - data.FirstName = query; - data.ScopeID = scopeID; - List result; - - try - { - result = SynchronousRestObjectRequester. - MakeRequest>("POST", uri, data); - } - catch (Exception e) - { - m_log.WarnFormat("[USER CONNECTOR]: Unable to send request to user server. Reason: {1}", e.Message); - return null; - } - - return result; + return null; } } } diff --git a/OpenSim/Services/Interfaces/IAuthenticationService.cs b/OpenSim/Services/Interfaces/IAuthenticationService.cs index b448a1405c..9225773a30 100644 --- a/OpenSim/Services/Interfaces/IAuthenticationService.cs +++ b/OpenSim/Services/Interfaces/IAuthenticationService.cs @@ -38,40 +38,13 @@ namespace OpenSim.Services.Interfaces // public interface IAuthenticationService { - ////////////////////////////////////////////////////// - // PKI Zone! - // - // HG2 authentication works by using a cryptographic - // exchange. - // This method must provide a public key, the other - // crypto methods must understand hoow to deal with - // messages encrypted to it. - // - // If the public key is of zero length, you will - // get NO encryption and NO security. - // - // For non-HG installations, this is not relevant - // - // Implementors who are not using PKI can treat the - // cyphertext as a string and provide a zero-length - // key. Encryptionless implementations will not - // interoperate with implementations using encryption. - // If one side uses encryption, both must do so. - // - byte[] GetPublicKey(); - ////////////////////////////////////////////////////// // Authentication // // These methods will return a token, which can be used to access // various services. // - // The encrypted versions take the received cyphertext and - // the public key of the peer, which the connector must have - // obtained using a remote GetPublicKey call. - // string Authenticate(UUID principalID, string password, int lifetime); - byte[] AuthenticateEncrypted(byte[] cyphertext, byte[] key); ////////////////////////////////////////////////////// // Verification @@ -81,12 +54,7 @@ namespace OpenSim.Services.Interfaces // Tokens expire after 30 minutes and can be refreshed by // re-verifying. // - // If encrypted authentication was used, encrypted verification - // must be used to refresh. Unencrypted verification is still - // performed, but doesn't refresh token lifetime. - // bool Verify(UUID principalID, string token, int lifetime); - bool VerifyEncrypted(byte[] cyphertext, byte[] key); ////////////////////////////////////////////////////// // Teardown @@ -95,11 +63,7 @@ namespace OpenSim.Services.Interfaces // invalidates it and it can not subsequently be used // or refreshed. // - // Tokens created by encrypted authentication must - // be returned by encrypted release calls; - // bool Release(UUID principalID, string token); - bool ReleaseEncrypted(byte[] cyphertext, byte[] key); ////////////////////////////////////////////////////// // Grid diff --git a/OpenSim/Services/Interfaces/IUserService.cs b/OpenSim/Services/Interfaces/IUserService.cs index 35254a1c54..92bd8ef773 100644 --- a/OpenSim/Services/Interfaces/IUserService.cs +++ b/OpenSim/Services/Interfaces/IUserService.cs @@ -30,13 +30,13 @@ using OpenMetaverse; namespace OpenSim.Services.Interfaces { - public class UserAccountData + public class UserAccount { - public UserAccountData() + public UserAccount() { } - public UserAccountData(UUID userID, UUID homeRegionID, float homePositionX, + public UserAccount(UUID userID, UUID homeRegionID, float homePositionX, float homePositionY, float homePositionZ, float homeLookAtX, float homeLookAtY, float homeLookAtZ) { @@ -78,41 +78,26 @@ namespace OpenSim.Services.Interfaces }; - public class UserAccountDataMessage + public interface IUserAccountService { - public UserAccountData Data; - - // Set to the region's ID and secret when updating home location - // - public UUID RegionID; - public UUID RegionSecret; - - // Set to the auth info of the user requesting creation/update - // - public UUID PrincipalID; - public UUID SessionID; - }; - - public interface IUserAccountDataService - { - UserAccountData GetUserAccountData(UUID scopeID, UUID userID); - UserAccountData GetUserAccountData(UUID scopeID, string FirstName, string LastName); + UserAccount GetUserAccount(UUID scopeID, UUID userID); + UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName); // Returns the list of avatars that matches both the search // criterion and the scope ID passed // - List GetUserAccountData(UUID scopeID, string query); + List GetUserAccount(UUID scopeID, string query); // This will set only the home region portion of the data! // Can't be used to set god level, flags, type or change the name! // - bool SetHomePosition(UserAccountData data, UUID RegionID, UUID RegionSecret); + bool SetHomePosition(UserAccount data, UUID RegionID, UUID RegionSecret); // Update all updatable fields // - bool SetUserAccountData(UserAccountData data, UUID PrincipalID, UUID SessionID); + bool SetUserAccount(UserAccount data, UUID PrincipalID, string token); // Creates a user data record - bool CreateUserAccountData(UserAccountData data, UUID PrincipalID, UUID SessionID); + bool CreateUserAccount(UserAccount data, UUID PrincipalID, string token); } } diff --git a/OpenSim/Services/UserService/UserService.cs b/OpenSim/Services/UserService/UserService.cs index 7879365746..e8b9fc30e7 100644 --- a/OpenSim/Services/UserService/UserService.cs +++ b/OpenSim/Services/UserService/UserService.cs @@ -35,39 +35,39 @@ using OpenMetaverse; namespace OpenSim.Services.UserAccountService { - public class UserAccountService : UserAccountServiceBase, IUserAccountDataService + public class UserAccountService : UserAccountServiceBase, IUserAccountService { public UserAccountService(IConfigSource config) : base(config) { } - public UserAccountData GetUserAccountData(UUID scopeID, string firstName, + public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) { return null; } - public UserAccountData GetUserAccountData(UUID scopeID, UUID userID) + public UserAccount GetUserAccount(UUID scopeID, UUID userID) { return null; } - public bool SetHomePosition(UserAccountData data, UUID regionID, UUID regionSecret) + public bool SetHomePosition(UserAccount data, UUID regionID, UUID regionSecret) { return false; } - public bool SetUserAccountData(UserAccountData data, UUID principalID, UUID sessionID) + public bool SetUserAccount(UserAccount data, UUID principalID, string token) { return false; } - public bool CreateUserAccountData(UserAccountData data, UUID principalID, UUID sessionID) + public bool CreateUserAccount(UserAccount data, UUID principalID, string token) { return false; } - public List GetUserAccountData(UUID scopeID, + public List GetUserAccount(UUID scopeID, string query) { return null; diff --git a/OpenSim/Services/UserService/UserServiceBase.cs b/OpenSim/Services/UserService/UserServiceBase.cs index c982c1a27c..fea8b019ff 100644 --- a/OpenSim/Services/UserService/UserServiceBase.cs +++ b/OpenSim/Services/UserService/UserServiceBase.cs @@ -36,7 +36,7 @@ namespace OpenSim.Services.UserAccountService { public class UserAccountServiceBase: ServiceBase { - protected IUserDataPlugin m_Database = null; + protected IUserAccountData m_Database = null; public UserAccountServiceBase(IConfigSource config) : base(config) { @@ -53,12 +53,12 @@ namespace OpenSim.Services.UserAccountService string connString = userConfig.GetString("ConnectionString", String.Empty); - m_Database = LoadPlugin(dllName); + string realm = userConfig.GetString("Realm", "users"); + + m_Database = LoadPlugin(dllName, new Object[] {connString, realm}); if (m_Database == null) throw new Exception("Could not find a storage interface in the given module"); - - m_Database.Initialise(connString); } } } diff --git a/bin/OpenSim.Server.ini.example b/bin/OpenSim.Server.ini.example index 545d6ce179..5696f079e8 100644 --- a/bin/OpenSim.Server.ini.example +++ b/bin/OpenSim.Server.ini.example @@ -60,3 +60,13 @@ StorageProvider = "OpenSim.Data.MySQL.dll" ConnectionString = "Data Source=localhost;Database=grid;User ID=grid;Password=grid;" ; Realm = "auth" +; * This is the new style user service. +; * "Realm" is the table that is used for user lookup. +; * It defaults to "users", which uses the legacy tables +; * +[UserAccountService] +AuthenticationServiceModule = "OpenSim.Services.UserService.dll:UserAccountService" +StorageProvider = "OpenSim.Data.MySQL.dll" +ConnectionString = "Data Source=localhost;Database=grid;User ID=grid;Password=grid;" +; Realm = "users" + diff --git a/bin/assets/AssetSets.xml b/bin/assets/AssetSets.xml index b80aa26ad3..c13ea422ee 100644 --- a/bin/assets/AssetSets.xml +++ b/bin/assets/AssetSets.xml @@ -1,12 +1,4 @@ - - -
- -
diff --git a/bin/assets/OpenSimAssetSet/4-tile2.jp2 b/bin/assets/OpenSimAssetSet/4-tile2.jp2 deleted file mode 100644 index 8c631046e8..0000000000 Binary files a/bin/assets/OpenSimAssetSet/4-tile2.jp2 and /dev/null differ diff --git a/bin/assets/OpenSimAssetSet/4-tile3.jp2 b/bin/assets/OpenSimAssetSet/4-tile3.jp2 deleted file mode 100644 index 7890364bd0..0000000000 Binary files a/bin/assets/OpenSimAssetSet/4-tile3.jp2 and /dev/null differ diff --git a/bin/assets/OpenSimAssetSet/OpenSimAssetSet.xml b/bin/assets/OpenSimAssetSet/OpenSimAssetSet.xml deleted file mode 100644 index e16f0bd257..0000000000 --- a/bin/assets/OpenSimAssetSet/OpenSimAssetSet.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - diff --git a/bin/assets/OpenSimAssetSet/base_shape.dat b/bin/assets/OpenSimAssetSet/base_shape.dat deleted file mode 100644 index d9a361f346..0000000000 --- a/bin/assets/OpenSimAssetSet/base_shape.dat +++ /dev/null @@ -1,105 +0,0 @@ -LLWearable version 22 -Female Shape and Outfit 3 Shape -Created by system from avatar's appearance. - permissions 0 - { - base_mask 00000000 - owner_mask 00000000 - group_mask 00000000 - everyone_mask 00000000 - next_owner_mask 00000000 - creator_id 11111111-1111-0000-0000-000100bba000 - owner_id 11111111-1111-0000-0000-000100bba000 - last_owner_id 11111111-1111-0000-0000-000100bba000 - group_id 00000000-0000-0000-0000-000000000000 - } - sale_info 0 - { - sale_type not - sale_price 0 - } -type 0 -parameters 82 -1 .21 -2 -.5 -4 -.11 -5 -.1 -6 -.3 -7 -.4 -8 -.5 -10 .7 -11 .34 -12 -.5 -13 0 -14 .04 -15 .58 -17 .56 -18 -.26 -19 -.73 -20 -.34 -21 -.01 -22 1 -23 -.5 -24 -.63 -25 .44 -27 .05 -33 -.24 -34 -.7 -35 -.16 -36 -.2 -37 -.98 -38 -.5 -80 0 -105 .07 -155 -.22 -157 0 -185 -1 -193 .86 -196 -.74 -505 .65 -506 .12 -507 -1.5 -515 0 -517 .16 -518 .8 -629 0 -637 0 -646 .4 -647 1 -649 .36 -650 .85 -652 .49 -653 -1 -656 0 -659 .65 -662 .5 -663 0 -664 0 -665 0 -675 -.15 -676 .26 -678 .28 -682 .27 -683 -.19 -684 -.09 -685 0 -690 .45 -692 .4 -693 -0 -753 -.5 -756 -.08 -758 .24 -759 .6 -760 .11 -764 -.38 -765 -.3 -769 .42 -773 .51 -795 .16 -796 .11 -799 .36 -841 0 -842 -.82 -879 0 -880 0 -textures 0 diff --git a/bin/assets/OpenSimAssetSet/base_skin.dat b/bin/assets/OpenSimAssetSet/base_skin.dat deleted file mode 100644 index 854dd00fbb..0000000000 --- a/bin/assets/OpenSimAssetSet/base_skin.dat +++ /dev/null @@ -1,52 +0,0 @@ -LLWearable version 22 -Sexy - Female Skin - - permissions 0 - { - base_mask 00000000 - owner_mask 00000000 - group_mask 00000000 - everyone_mask 00000000 - next_owner_mask 00000000 - creator_id 11111111-1111-0000-0000-000100bba000 - owner_id 11111111-1111-0000-0000-000100bba000 - last_owner_id 11111111-1111-0000-0000-000100bba000 - group_id 00000000-0000-0000-0000-000000000000 - } - sale_info 0 - { - sale_type not - sale_price 10 - } -type 1 -parameters 26 -108 0 -110 0 -111 0 -116 0 -117 1 -150 0 -162 0 -163 0 -165 0 -700 .01 -701 .5 -702 .26 -703 0 -704 0 -705 .5 -706 .6 -707 0 -708 0 -709 0 -710 0 -711 .5 -712 0 -713 .7 -714 0 -715 0 -775 0 -textures 3 -0 00000000-0000-1111-9999-000000000012 -5 00000000-0000-1111-9999-000000000010 -6 00000000-0000-1111-9999-000000000011 diff --git a/bin/assets/OpenSimAssetSet/brick1_256.jp2 b/bin/assets/OpenSimAssetSet/brick1_256.jp2 deleted file mode 100644 index a632282632..0000000000 Binary files a/bin/assets/OpenSimAssetSet/brick1_256.jp2 and /dev/null differ diff --git a/bin/assets/OpenSimAssetSet/brick2_256.jp2 b/bin/assets/OpenSimAssetSet/brick2_256.jp2 deleted file mode 100644 index efe0a9e0bf..0000000000 Binary files a/bin/assets/OpenSimAssetSet/brick2_256.jp2 and /dev/null differ diff --git a/bin/assets/OpenSimAssetSet/brick_mono.jp2 b/bin/assets/OpenSimAssetSet/brick_mono.jp2 deleted file mode 100644 index b250960162..0000000000 Binary files a/bin/assets/OpenSimAssetSet/brick_mono.jp2 and /dev/null differ diff --git a/bin/assets/OpenSimAssetSet/bricks.jp2 b/bin/assets/OpenSimAssetSet/bricks.jp2 deleted file mode 100644 index 6113881486..0000000000 --- a/bin/assets/OpenSimAssetSet/bricks.jp2 +++ /dev/null @@ -1 +0,0 @@ -OQ\0/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0R\0 \0\0\0\0\0\\\0#"ww\0w\0vo\0o\0ngLgLgdPPPEWWWad\0\0Kakadu-v4.2.1\0\n\0\0\0;q\0Հ,uP;Od13Q.H"i,g-uŇ߄}5 ~H\\ J%IURZ"#:X&xI\0\\\\DK6{0g|aPY-66H8/j-) M04 m\n=&vxWgvr,l7HmaϏ9cqM>'!noj0oP,H4#?PHÇu ?cl2٤V~NCKRL-fѓNqF!CY$5#[7`DvBMܑݘxu`\0XUv)R 6?0GzyodX ԉRb}\\95<.!uUCK]]+=uƔnh)hKe1|3l^:J_hzK>2wxo@#GCN:I+hlmD̹1Bp0K!\nE+Dy+T e\\\0h |GP LF\tq^ g] F=W=*%d8OEujOZw,(z=`Б2K,T۵SNfL4<@\t8fy̥#qW|}3V>Y8E@\0F>\06\0ut")pp+o-t $)7A\0GTY- (Tm*_%aR/Yh#CTsڦNE(Оn:N>0a}|`\nKu0pL dAݩۯa9Q3ѡj1 u*`,+UWkY,6-EI rhhg7w,H!Er'qBP2&VB2I\n,=?sb&[pCγ\0/Dsu#@S.j8nޤw̃!*X4Z՝ʌ̅dDٰEN`x\taGf>P$sϋ,!)yU2x;IJጘ 6ʦ]gp~ \02t>("v~3[;i·w8 rlზWg6}3Sk9Țw#Væ[?=ԖX" |34/x 8s(Xk£s\nPeƭ[FwI֊G\nt.0>x6ObE6Bv8SήǹR;˸0j}'3ޥ)4RlS&SoyV=YxvzVu>tqmy'DUG>wk=\08s Ǫ/,_`am!\t%'CehFK)qKGj7}4(>2uRץiRd'3e1fE`lp;B{d)d3?½سfHn1cQ_TXf]^]lg9 m\nKAxjL\0\t^N77g޴e*.ƥ\t!Zf-wsmr9CKNNTPEl|o}*\t$|AE%"q[Q0@WatWbCa6R 80B>jJ~\n~23Bb3.B@24^K (7RX9ݺ'1knj[%1~Fuke 07X`S#w:Q`t񥋍F#K+!:CյrII0wS݇oNC50HȎeާ\t+5% xR'q!0?.\n4C֌ֵ1RX5Z2Ǜhx ޤ"hUJ]}*@X}a~ f=zL.\0#4V Kh) Mw_5w\\ReI:D-Phs\\9>ThV k=?kU f藱}Ȇq6@:7Oکzgl\tkPT\tvTy!qLA4 d7)T2_#:\0W%F>"#_O^ʇ!Z-}u\\,,UdbcF>>mNX_ThG+0N+<ܱ#8~Юqe$O"M\t˯a6yEz =SotTG\\'|2p*YV)ˑI: c2<}KBJgh 95{a4>5͸ea{F򠯉kfo^7*8YXl#&'at~voyp_ ^;S{`(W8DGD?eh@dz 0+>`#WB\n5s[rL<,s^5x<3'vF\nf(\0ށeϝ5ܓf\0C]Pl\t M@vz^wx\0OQCdҨsøP:w[yg8ff"+g=\0x]wfx\0P@s~_D/A]|QB,HTn=L(). Ac-A:3@E^->AV%Tv]S;_(b=$wU"\nkؿs#cCF L"[\tD[ t̽쎬W/B]4Ҹh='~}lrotx08H˒&\0S\\OgM]Fa \0(iM&J\n|^F=)D 8Q`UYC>@y3ʄ IfWh,O7 yZ^-{}2Zw ?t=ǀN(%\\_\tZWQQ٪bg9M_/IsRk21Vjm2,H4[t߸LP;aX9Ș|G+lyĮhd~\t ۟}虾W3ÇT=b!j;x\0ҪtwϦ|vGkOin= .\07aeD6,n L^X+~kH*׿[Ϊ6vE_Kb#4\0쐦4YEWĔmr[PZ{^f:]ON8Q0|V$J&7功d=D.i (5oh+Qа\tk-΍v20~\nX>\t 4b!%rP2vv읔 ۊ>[]O*Sf~'fbl^]|-r/>UHd\04 {$T>_v8Lb\\v%Uq/(xs\tŊ]Hp% ȺUׇyN{4E,|^D'攆Kb :C?2iaVYM2X 0Q90NYq\\B=\0|GD5ǹY_WETe-,J\0jv}j;uΡS5\0ߔ16-R\0ТDtt"\nD#,pκ (oUkV>;5.f߈vN[wȡ\tޡJ+KR 9F vmN#W= x~ikkWqPA^o5V/-@NT\nk-`]/#!(>Uh,V{6`t`WUf$ķ5Qlqlk}s/4{;}Jm\\)v]Py Y]uƝgXx\0F+P`CNO%Tz)ŀ@fiF;,r"UFւ@4D,S.L{e\\՚8\0P}^_ӃyYq]"'?s=_!"VC8\tƫ89VEr:U tN ؼ\t NlphJ"3CM W ;36$11]9HgqDR}/Cۡǩrw\t͢iT'! )+W"f|--- +\\pۣv2v gT* >zy25\t?`w(FD+~ ޟBBc-}_ގYjKH+t/lY J3=+vvSGoI/ u^q~X3)pBҠ{z\0iKK\0x\0iם`J,T$qޱv = PZ~gC\0=&Cu-亻(%G> _ڧߏ@|Ef`D:…J>';_|.^\nP&%WcvۓR:v?RB4/2C%; i IL~/vR\t%V8U1اpœ9'َKtSS\tm$sS/|$?eC2gIw1Ǫ/RaL~l)HP4_6_SP|f=jwg7LAX\tc\00nt%tzr#4X]h/d8;&ο$2Ʃ iVQJ0\n{EùAGKl¥תm7tVΓ%X&H"ȳòW̚ &Kb 'ml ;%aҪ0Lg\\.ܪaw)T-(]$J=Ș L1\n;Y sr!>>dh0!O [%OEGh9\\&EыɆPB\0ktj=38 h١@M^. NeWF=wo"5\0dg7ר|'{߻@reYF p!RnIq1ݜԈ L+NRV$?rZ1%$d(/@4 I|l |-?M{L2!K2|=7+, ބ{ .N{L{.\\,1,'#6XpDr^̜-\n)جX@8EhDC ŗ\\o‡lpǻ/3?Ҙ هcyƋ=EF.yf0mzþM΄T;$ܝrKjZ&Ar?h7_XiWIfem+ ­y=G:Ɋ|Yz᧸5 U:k񯀷jB#:PB\0ɅM&iWp:Y`E\\ZQ% (L W?JE\\K 5.Fawa;y2r`1=sET<Ų4yvWv˨QcځzwHA&{ BU!͚fOpZJ3(O3Aa9#F;CWA@1ٍ]?F0Ran}L_~\\.OH\nh>$O4$l_\n},]G./pAʲ(vIBb`MM*Mo.(\\D"9-ډ5uتSAydaX= K]G$ޓ@@}}%vYdW>\tƱFڥ?\n^ATE 9kV?,剩&lbÁ!C}rDbY_]L^-Q\\{R_M3S/Cʹxˤyb&I.auC*Jf*$آpqfթ#(N#_:}'mw\tB/&K*P(Em⺀+{vFhQw+UP{|l,߲4'BO!/`Pcl+pk6"{-09ߊB'֩힒ZѤԟTg\\+Cp!_sF<&etÌ8vaS6\nF[JG3.W~_syC<'&O/Ce RtĒ7!FX~\0[/~u-PWENiM$,>kAϔ]UVݣCaAyя-,_S&~\0lO>,@N|t{G\nW^/)`@wTsg(]n?і]6#o R[F3X5{扜W_f Z*Ro>ivt7elt/"W+y-l3|\tPt;@$+tXIOyewe{kʒe7Լ7vb,a8Ό3^| | )Ң)UK8pRpEEÓ|H+Yi廛t׶nPqқіיՆci#\0ݽDBłzHr-E![})HX)݈x "\0^kƿW%,\tPdC/;klō䚴/aTsC#`і5%pʻ]&v7mRX.|iΚ6\0,mǐ;W.j3[j"C\\(ysaޞK^\n7eP`4zL5N!яi 揑k,ٗ"ZI9l c/,?EmĮųД$q]w'!%Vd3qRYLW!oz"wj1z-'4bgUbYvn\\@\n`9JrҺ:DM0V\0ꪵ--U\0$?ZWI9LǓ:4`ST@ZoڞaK/xsa.k4`7e08]XѷՈ!}8Ψ3ۉ/@AYlŵwHF4 -!IC.TDV' tXS7 غNXk_/#O:{d^Hghɿxqt^ޮUރMT=ob[17r"WI?ڲs U6D`"YEJL`ΛeO~~[ܜwbDplηxӌ\tֽ,O YD.z#yzl^(פG2^GG6us1YX`4tfYOT;NC{zP:ydaE~eiCi=y慝)W%MmgYRAr\nE+sE(tZW?\0ZMQc!;#SUaoْ=s-?lr\0nP«8f0-)ƛi\nsppd\nǔ\0\tYPuKϟyk74?vP#F&?ځ-u1S6NV|昝!?o6`x#}050kf5 HD~;c5:lUB:uO0f5J_ UOEXuVxMIi#6N.g悹E.0M`rx[g?H~ *Sia0ЩUN:o.^EbK:7\\!(Ofl- s_mPhiҵ&]c xu`Cnxz/I7Bi\t9!Ft␕qt)iVw,b1Sl6w!I_Ľ>p? zr^Tb==`2gl4~9N>rs*1hʄK ktߣܝc4ݥ9yr}ܐEMߋ-=R˗OTCCa ]z ִV-Ԏ߂; \\`0;b\tV>Ƃu\toeچ\\ -labg:0tdA1ǺWoX<|:?dsvPTi($\\[!QkKճvcY?[I}N|Ω8#Ķf4ѣvTaRȉCwlxWt\\b (-wt힘049VNVR%5xpWX"@Ѓ6Ȯ}D,HH"ijb\tT&˜h;=7,rG1#)e\n1k4 )b_\0E,wѸI՛u.>b©|XuZ'mwVs!N*5Or$@Za'L"?hNX+|/`E4wU" [\\ئU'.v4}nL027I2.Wu/[˃ EtAߥ@3C-swkӭrP8ix^i;beBB;}:}\tjq5"G0Mrɹ1Zi|ʁnYpC>$_J3Aj{i$4.x^fJA83㳒qfG#K۾4?w.c4t'Ґ_ J\\/̊׋Χ2dC"7Іzty)`I.TJ̞XBF/QM:i@쬧v-@Rt2p?se]bۄtf)P娅w)?Qa%gJ4$:{;?*ol+O9 >5ljꚽAiUh$;*<\tyV&cڑD}V& ;DM-pTe PFwgYRy5k۹\\Rir۽_IUjZo1`=Zh4\tu0<ޚ\095LwiIj{dB4~"E֜b+QLBV8dž[dLd\0,ټZ(\0lBM1KSH0/KnIxeK8[Q佅!b\0tP.IƉyyV`\tР& CIm[o.)SI`@Dl@M5fcW5!Fdix 6'wefm} MRzYSk~4W_dIµٶ)RǖĢۀBoCf.@jWߌCC6'RvIRX8=YR-'ꇀuXNj&E@Ss$?WPpmHG阜?vnWrv հ(wcTET\t=`aP^ΑW3u\\2h:5#\\H-2-fc;zWGR%!xj˰7Nh\\Dyޔ;Sƒ/S V-'MwWQ\\:Fo\\qzC"E2@'<B:s31MԚkZ`/h Rr rg?dk"&N\0˻Y4yD0BZTȎ `m:>lpV{x AcGH(7ML'Y&faWEE7"&w{kÅa\n3- ^hw Z.E0jn;'idaZ;jYMf[< !y\0KQG˳}^%̽Y䈗ڤeERE98T?+⺡uv\0CC^lWH0EY%q[~@E1iP\0C-2[Au w!/ cBeX\\*5e%7=A7Ic|PN^UlʼnЖj'kt@F0ii80l+,$E?s+8 v@ M|?RncZޭu4m5آhI%eƎSԜsf{c *;W͸R:?L/|^?m>}D5?\\holUcEnURYF6W=WY Z-Rx/ܯZl?@\\~P>*6!xf:~Gb2Ý湶L8۽I w@EP R&9s\\jY!lٖP[e~<5M?ZDT q\nYfj |_̪z EqPMӼZd.'`'?`NUP``\nae˛'XT\nc \0N_G(Tσ)7a2[fR|Y̙^͒~<v-{'}/$DY5"+Vi-E x\t\0T{NzJAmqL\0ƋD<NjД<i!܁,raN/C"CCbOA\\|1`=\nEt2$qz/jWqظW8t>gp0-F&jPx5?ȸ].xʣ*]G>3EDvxSXR0+"GkxX'!YwAYڵB."`iӁzs%]?#Ea}ŧ52t`$;XJ8A.\th.s?kkָjj83eYlkVY K+ǟ}.PݮT^/+VV{cb!T:x|֘4 ~xk]vEpl*htgq&jtRG6"y~r[rܯGTF7x֘Sч\\o,s]O\\'CZ@ܲ]G\th=Uioс.ab\\e]IX=$3#0;B\\ =@ߖpOXt!+k\\gls[W!{C x߈47e~r\0h<n?aAFfhweN`S`:{QJ.C)FۖDeD,&V]3h=[gt 0Y S@!_A=N}#yOjc\0$U^If\0ш\\J@{hW\t.zXf+$C$\\^\t '#+揻T7lO´|j RZzRy<B(@!?X 7Dﺸ5@\t쬤 7vg 6#\nohQg[pvNt7G!| k%idȀgl`F=m/Q:.va`@- 7n_DyٺkE{VJ%THAǓiqFr㙥?\to2vN iM>OV>G%]Hx"W\n[ys:cE|莏\0=_ ;{n2N.JL\\<:Jt<^pO]r5UF\nzmyAN!EfڻTPH*8|X^wb>8aBޡE,bM_cZ^2s1u7`K(O F`J'ZT\t8KaT)B3~ʓQ<б-1 RFXa0cGz\ta<,[69_: 9^VJ2z͍*s2dQkdZi)\n\n^M[B\n_G%o!nQ?sr?7-MS_5ddq1wDW|\ta\\Up|=I{q\0u7:?d.~jAy`>VUؖF4`H5PԾД*`f dO)fvR1ZݟL9K2jQTH^-jumMga[bTBp 7 D]"ɺl'xKC1l[\\#wg-EwN /p2pyO} ;q!vCBs\nG+|D:i/vPmn"N\\=~\nE}]~۽B,{g-S.Y4OkSwQ&U35<{%,\\Gi@o(\tԓ "ODGnd[Gc 3!W!InՆ\04tDtb]Qp+yٍͿ^\n=3?nK9jRCpC{<v.lKCkpRʘ)쐂BYc9N=W>f%.tKLn^E3@,6h` kJ9{4:a>7M.{|*f5T>24+^͒ZO ^oMJPae W vyF*Ɇ< Rt4E6 ݯb䩋Yl,) \nfy_"Yg~{<2e?TfbpMN wc ިKYw(ꡉeg6zň+íM yDlcָTZS-PgȄ\\u4ɔD[5zv:[;)__@¡$@|Ώ+4[p@x Tkc=3*TC,-*;~bɮx_[TLb;_Ӹ?@zre> 6NCRzLϣ̳+|NT,+!?U9r3@X=m`"B-mVۢ .'mϼXí̖7P=/W|M*!\0MB\t&=I#$/ vkŠ ߰l49?;/g}--nCt.6iLf!dI3Abi VH !0t,FjD)ЮVK]G{Z0f\0}j2,C'#!/?iҒ믞0Q~pLs+%E?kVvwFL`٦)}UρcdF1u/\t4ص/妧ˑ(Zl?anԂ=&`ٟ_~_f?E`*c;LH QԐ;˵А:L,pXy.-ueK5 )'{]GJd8'̦sשaF# E0IqoB\0yv(72@eg< \t\\fYK+\\ܒe{T-h]7^ӫ p2D"1pyG6Vl&EͲ5#_]3\n|\n9B!\t'n:fkũ,Vz@\n|qP~8CA WN9v1/0w NC tMU_*`vr@hW̜p:/.Z@lYTV,Hێ]( F~iԶ{ŸEaˆ'߅ع|p\\M ǰuer!7$[k=I(RƺVlC<ȗmf$.c_mc\0o^iHZx RXwdW1|c{~,g@~TJY}LqN{VM}Jp뺥=;-C Em;B"Pě5f`tZoFOtI۶^ixk*ruVJ/񊂒em\n{ =aJgM7\t[,HCLgs' NIl*E˺Ucvz ALS-/H21XSpD-]˛5h6Ya h?vڷkmĔcu7xr>!Z#-a^''?6?{&|LCNֲ\0̭x7~ocAFU_`t~5[ϗh5ecl`ޕ\\'  &VhzFr.X4x;ZԦJb-e:1n\0Rn!jr&s{54(Kl ~<'ׁҽ=K Q^ZJߵzJ'֍(,d8+LAډg+D$u=-.gmZa!^GXD*&TOM",Ur٥x6PŁbB=š;\n,^][Y+{eV|E+&7Xk ꌡ> rApߘp{ih X G'lX2Rt&?p\tG];OK[{@wP mۗS9,i]9BH)K3 <sqhՅ[u,=Y_14B]C|ߛ^7m9ot'TS»]_V"xCb0eVSʽ3GdrTou:"|c5rO0\0Y'DldZ}5Vʺ1zmSoЎ\0$P"VUvƊ> a/S0̜o+C}[=[/l|\t, g=cz/TBJmdžLn?WdFqi|ZOdxL59'S-\nJs&ben!!-m?>@Q6x֩^@)X91bv9]?\t$儫?#[LV T/x5bR&Ҷ ޫyg13괝@\\-\\IHhįDJF Jn,9FIJϼf6vZ|#C4l儣`Ń2Wc|/Oc)@{8ysG#:ԣ !yOə܀v٬[UA?{5c\\FA'j.Rf> =D>V=ݥh>?G^y{pȂe3.Xp76*\\iy5.8p3tZC|H8͇ ke.|?$]$Ak֣F߀k"rN&mUji'63WKGZ uB %/= ݦ?ₚώ#=$R.C+GL; \\AƇt0CJwuPP皩ag,#@p0(%O#qG, ,WfPh\nEfDxz5"^ ua{{☹sf[LF:\0,q~5\0ږ`T ZP_\0[{\tZҀ4VPbEʮQOSosmNvpЭv\\\\Ki|=!}Ub_J[\\p bM%o "Fg!^L1r(Mʴ]qHf\n47M9iGVv0TϵU{|XZU\\zHoi`|te<MR|=x G#)?k9P[\tNNY?uN3M(%_^)Y=WzV_}DQmJ?>QhXtVlT\\v{$sKjOR뮴nCd{mU$3i`\\dΧWB9\n@v, Bʼ=::6I(c-\0`ȥ\n[V>6-^ o?wi+EYZOs,ZY3<vF׾P(o6PI?lA6ODdAl <8YfFH0PSMFFDAdG.zWcUC-$-WHɃol?jsa0XjlJt}ra_m@nϬOB|@5ħ9^ݕӾ8!LHS\0bz)F&/ P\\US-YWR%.n{ rglj\n0@F^4-EfIPmXOW1F:} {lљ&sEaxQG[\\vt~2![\no}aGJ4\n0'pCCS3N1&D×Ȅ*ed5ȟQ37*'IFYsEOI"Ӻ@z P*k!H9u3H&.>#?by/8Ic /k/V4]u#:UWC؅"!"c= ?\0ؓ1uK U//b'CCGČĨs`'d ZzN\no7\ttKWz~lu7D-`'{%(T sDsܕkJH]K2A(8\n ȲESr;IR!=xMT9}%)ԯ()(QVI,dޚ) "،~P>fS'ɔw>Ml,׻D r eϓNP\tuksvxF  ȣL9\n&-)e6XLWrgURTHDaxul1'-ʵ4i$Mxl/{EXZApHTy<͕k64vE~r9 iٌDLR#⤗޻6?q͗X'TF>zU_)0t8 V:vhSBϗT)"8a:jS >:T.fH4gS55V7wˣyhCpa.2j\0密@lj?4Mq0-_1}گZ\tA cp´gexP@o$<x_ҞL'>\0S=zwWA_ |Sɳ;0@z_z5' {M< UI>cݸ}ɴAbT9rr[Pi'V9;H!d%SE7NiZP: pNg&/J݄YI+@oX3ITY5X~8}(0&vx?R4JP3ڕh~ͼ(whn w/aHU\\`(T6 >$=Ba=\tvSR@,!m?%Mc@zK^tк{7nk\tp95\0󳰀U$i" c.ׂdX󄌘 ns}|}c7{NBmq'Sc [H.B2$7Li'&4Y., l$2^z,\tf IrTw95S(j,!\\S,t.|V=4ˈϪ1̝\0e+.ŀV)\0RR`YiG ,.%~4;U$oQ40e)(`wIJ'L]uiWH4`1g\nO]AS(yk tPEd {Wfv\t,!D^pT~_7 $ zfK3FkAf˳LPOз3L |^IȇT{@ U#^1?HϷ}ڭ%{):A0$@;Bg18\\Zش u mw92.΋n;K4 x5RDmRATp޲@HS hOL#}OYN :/l3v9[jj>~{ݞUyS5Sm\nIҊ\t١湭\\UU2Q^2Yyp |27Mٌa\tWނa4p@yah\n~Fؾe`85[R:hbEE^`LvcBg~6bf~Iȃ.f݊|z2Q@hh_*\0S(+!\0;z4`gh=\t)S@W),Vm):GZd!qWT+וD/B:W\\|%f﯄x&\t|GV2ӕUKvSȒQaPpYswje*XaANAISAH[F`ɜ\tz$Xp' FVYVD+|$4k i=8}j%QbZXssƑ伸^LI:'! H,jه[%"yb CE]@bC>3h< +s$-o7]҅f,NJ찏q:oh~Y%\n~$p*)m;$l\\BE->) EMVuk( 6iq)D~*n\0r#o=QdhyVHO̙ROQ^r'\n N >q\ttf!hwβAGjhԡg_zXf]3SF-OVs-%1-c_\nZ-wF(W\n01?DAO_t%~^0"+<|A4L \nŪ:*iʌWto{*0({v*®_01\0.m]Lz(;-S)qМ7·fhyE*^;=OrO-`r뒹h>mKYBtdiG-!,ŲqdHEVb`'g{B@Xgo-Ljnz[oa&/')Ҫg?NxIBJE{P\022 6t\twO>9{rv|8RbNnE39l? [ l-2vwi^J3r0TX!b޺@Zt4\\<1wBu=.kYg]\tay0y~qhVƦf8~27'NXkED:1lBs\t&]zdȩr//W> igfk됎%pKrIjpMy0o|])|'9}QwF7,)1m~$rl[pۙar`t>ӹA%UX(+k'cat7vX[M\\@_7$HDi/{Љ`vP1f'`lD\0hCBmb3f#D;a/Oν ܺ9y\\(03٘D9rB-5@'c-=ͼ -'Vڂb6qNM\\%Cx/62/y*ˈ<\\ԗWl@ahXKNX}7X'!_z\\wTa4IFS_\t;ԠpcsZJ.ye$zZ+Z= ۻmO\n3/#0fšM{^Ot d؝bE?O?~@z+%jM7\tnIދh{_n<6Cx衦;j|lM0\0\nJ\t4v8 H_*bE$xUMAKrR0ꐠ;A!RV?y 46FvaEd_Pmjjۢc̸o3c,McnhF1<-F\\nJTNŚs9|#6I:o4++L<*kz+ZpߠOfB HtpsݦK3T|$͸ܝ*#Ir+nv|JwIbzx3VVfm9-wۺD\n\0:L=*J\0ŧL@.\tna»Pr%%8ͳ!]Lq#gne2"5$@WpyJե\\t|{Vh8}(->.&ҋOϰ}kg|5\0.1k _dҥӺe|=`,_J{U9=/|1L##ތ+BΈMu5g5&F.}6a_[!E4Z XfAˡiNQvw\n-eofnXxbSNb]RӬCWg`s^sW+̿+H1D\n%LabiR,f趼1ӺN^Ef$yXx3Fx*}\0\\J[O϶iiD R(0aFիVe< +5\\QH[GPb\0\t8%4Lc&iAiO3YsW:E$bsIIZBF,t~cu) TLF+r A\0*bW=fcWLAZ_r pCI\tr=l%h /;A71{ķȏnk?Ga 9mnBį~BJAM<7krVLE/7>6Ҽ\t&Ou ,] MUTDR6q5B:u}\\H:>`f3 I*E-77[[ "@\\X/@PœY2EQ**5X}e'G̓hSn9_\\C٠}k#q} PuB,]])HݗZy_h{>c\\b7ztgý2Crʥ;X̮3%߬mlqH$Lp1G~tm;KNN@wgbR"bQ{DV\020bq<:uj.\t Q7we:ÿ)2ңFȝ9JF?"FNPMeqל\\#*\tÑƎ7~N㟀W.QГ΂BF|KS˽.SڵzW%Z* d7(0l؂b\\jXKs-Ḟ)U' EMVG#q1zOFC5_,V }J/Q1")ќ}$\t%=]̀WfCg2JZp0֨1&@vXp\nH[\npAQ3d3VyNSn_蘢󠤗l# 8L|0q@\nSqEL\tER`\nFez@ip+԰z3&T]q HeA%llVT+sK[C9B3{=j&MF}4n: V3PH=L8@y=g|>a=d!+,fv aUڠ^R^˱FziƥԉM44}7I={Kk|drw_\\EVNju\t5J8ُjKX=?v4׷{^4 lu#13l¬!w%D|~x-Dl3pD˂,*#XXuC I)\t^n.eP4KVlq@xӓ ZϛCˀwxE\n^vrf @Z5NZn&tI_GcU[j"ڲ1<~>7%PFUhS5>;1&bϢJRu%4_ug.—#? ౸U >{];i˴t{J,h:xcޚtwIաL!)Č@iUJIx,ƢdJgd oW E}lW^E P$fvFF3 [X[svP6!k3U.'n9-"Ty`+Hiz@=Ij:D͠*% T3]~8)=YoDbPfu\0j Em1ZТo0)(-ѽH:|idl`^:H=rI Q~Α-?^ϖ~{_3ku(l .4`j"B=Y*v-rk#[W:E skn߯cee QJ&\nfg+luC^[\\k!={ٜd4+Mωk\0CpFdtTd Va\t6޻9ʠK(`3ᘪ0 ^lu-ÿG&%4>WK>"όKbΕHZahk}e!f.kta=?]PTAA^)_:l O\nVk =CvF"K90XH`rҚp`)ͨC"Phd'ډI4R <rpބQ.I* Pf*p,>ܦA*_43FTd|N+CDAq}t(kx E-^bګpBvӼ߫I\0\t5]?K6g)17OIuV/zکL ugBrYjx"VQ69ZX"1kW@NT1#mr\\ם4ΦqA"I>VZ/3JHͥ'^`Wm4}?޿llh>!`p6cD;/B)hF@~Y0`T]\\:d=(?-񂖻 JTo~%t׬~:='-nTPK9-Su0:Ƽc-FoqM$KFc(9(axr}8+%+Z?[i +5l)#DrxTB ^n삦'UDnhc8@&7tpllSl^O/NF$|%W\\fj1DGCTx'w!DJjPptM:j̅}et `y PC/#E;dp߇>.}.ЧBީZ5 nĂOagC7nKj[v\nQ29tz?}L҃d̐ å\\n\tх__& `pGa+OqAP{8EG؄2Ъ쪶|\0%+h1vE΅>t.IS#¢\nU;OzrW-\tkz䖒t](ӷ8|3\0U ?\n'3|j;} e aYQmᇤ"bXfJk0H\t\0iQcO\\qS sa0m ;:aeEm\ta6PZB]K%\0zEc H"'̟^;ذnUUM.p\\;;{HL=}mVt+g5pϡ:\0<ǧ>WWUɥ}˜WTq.8`jb\n=1U\t0hGB(򢺔uwv*Mf$rBWf߁\tq\08/ǫE|e#sT9%!\0QďF)г_6>ZG%˗\0{.Aga(0NxgsƆVT=eh$ޫ*5:+eKHךi5U+ Ԧ^ϸ),9%+-#rU@G/1,dyq4YFy<⍩WtB\\N0GhP`R*EY/NLj+IDҾgm/;t z ~G$4ˉ:R+r\t&ÅVaK xn6=$Gڶ|P(}x9Z_hEx52ސl\nZ\0}[7S($T{$g'*6=!a^9E%FW;[|ٺ(4X+)=\tn'J'Yr`~Nc\\ylEs')}2Sz\t9֚i30sNwI|%M[wLB.QK2dٕ%JEuK%\0\nh0ӕ8-eWX\\eLO!4ܒXRtw<0…= 23:ȾT)I\0RMEf'Ru$rpP!@<cߦ8?2gU9PɁ&2ﴀ;GҀB.+D>ѳVW.-u{n\n'\0\tCpB "j+Xk:TZT?6JR-\ni3sU\0O+2\\+ƬsZ={v<0݊Iu垅'qLO-1gM̤TȞ^6tp3Ѐm~ɭPYAQpV=Eq DjM"0ᕋg/|Ývȓ\tLGEZLX~A{P鉤!{]v-)[բ@Π\nd& #gq"]`rIN}vg8@#;kOM%7]Ta>rkue)|9ҼK]wɲ-dQ-%O{iRu@!NP%j˄&PfC,XYüUe}@M@/XFí;ڏ;v^zp\tߗ^ZBv_ވuR$@j,J<:+WTC`NeYO#|eG/T}AM}%(Ёeֲ>?\\dpx W.D5#\\r.𸈵II)^\\ˊxN5z4s.%U칪G#Ā/!~0M\nR:ds]Oc:bN)X Xa\nbے7EXd&/z4!]ϭѬBV zzWFtkyVoo{+xKaLp.:WyaQSoR#x 6Mk@~e`Jō)tu EsezGY`s4N nBf`0?3;2;cq,DoEf']չEE\n}4ZvL:6\0$`F؉TLyPF 0jxu&\n\0@u}5VIG6*-O(زlGaBx7Ɠ(X0Xyo*E&?/ܗwtj$7+ц p&ԤhΜ$USO؁>Ix5R.; $nmAB$#.,CZV0Tć|- ޷ AM3 J3h=Q)D6֑z[>{\t}qbWeE?SL\t̩%іY< myq[lB^`PIs䳑%W > 0D32~k=>-cH{moJaÆ)hv#Հ ¤.J&G8\\t:as #%w)lbII|n%P}0?giu1캓?JT$\0׻:}Z SpY6ғ5XgK}noP?{a/,֘ПM,h"ye1qM?v/q[%0󊤀ʈMh@[ D4~[%Ў~F'u+Sq)x=.֤9\t#]\\o7J\\,^]@Nm 듹cu!z)ĹX@c VC"^์P\tECñ^V":Pa. Ⱥ"ۛܠeϤJoIkOC8IK;+PBg~,.I녣W(e )_x0j\0ڱ~w/n'XBQWNUa8/ݒ2/oV9o|)ӈ,gΫ>2:8>Q'>!6^zRp'Y0g ,<^PG"E?REnjLŸ? ⹈?p0\tkqirXxY+WO^?8+S\\,k"2ވe$0ʧ/ya0Q}</e&YyA.7采[ߑGR{'/Sم\nTxʦǸ!p'ߠC]>9-LbjLy6MпA/ytMGmcmbƜFb\08x"jଫhOn+l/bC XO2BքpccCO\t?zmЂ t|L›l{>92j~/CK`8כolVg6G6n|&,^ASx`P(s^hdIBojP!3Z!6B/ުl0E=fW hS$f=%Ÿ32P(pQU5iﺩVʍ8X f,q+2fOPȵ:2du$h?01TUifLMg5|>uI\0#{A'.;^̸m_TھMXB"4|&1Vor2ܸb\nύzهbvm1\03uףd}a`>s @Yc#ΡRb—F7l) 5'*'8#<{n3oF8aW/ѦH|o# ($'#[\nXO.7!j!g,bӞS@cYK9=*J'{*Nʄ(Yl+ךAlܟXo~{%O($(pjj\0wD/Zn|0o9Q4V2':@Ѹ y׮hHf?>*t3{_{$V%$S>sY%v]q5#'CGv8-H\nqymV\\Z>ƒ ù?yeYk6)!RihX|!qt#tl^A%|]0^GtP_vZ%)֮N|KH\0D0WESrcMHCU/ݭ |\tL9w V;:;1Пb}4)\nSʱ#lEgxqŞbJ6+31-ͭd|}"CGikw)29Gqe8DT#O7dOO5 ioXDexJI9*/gbW+Vx_4~2Z2O΄%@ANAW>V??V5ۣecG(! !!QP\tGǂu5IprIJو#u׋7@ ,0AĜPz")?܄b5{r-4MmRȧ%'>]4xejhs*oD2©6ޣpl_z=6gbSÉZ"ÇT/Ң/Wla֓HKU2FZ]嶀mE4\\%ulidzM\\.w@L8knלo xi$Y{ݎN+9/Z\n[+FBN1Ω@#~-+*x+8!_xB~$14 ~=/ 8%c[$qIGp#S(ࠖƜ^U!\0'qr#Uܦ.i:D^}8śMYj$;a7 +ͥdt lcSl@F~敪VB졗A\0z<ޏnw*:yc ~qXP#ḏ]}u b%+CKF2sZ~uEd6ZlAOnLWezabbts pؠtA詭d{ΛhAeھ&Z%[qlST&}Z0%?Xu<^݇KǸڷk):H=xgH n?07|'FoiX9,3gKAv/l/8i{s٢' vFkQ"2Xx=R _I)aAaqpQ\nȲl>0]lUf`PV>F|$\n-qIS  Sh.{{S9".xLlW8FQ_+y+]hVKXEc&;=4]\0J/v\t> rnSZ9\0\n1`P&2G ?cI(&͚e] P\0jUk"He{.nJ.m3?%'}-Lް]"rĉ~5~ِAO+RM]zeL 6:=M1M*a褭5z;~&yO[jr}e^p2(rM HA,Ai rPB9p`t^F>$j{KxHjy1p9\t4Vė*s>2rܠ͐[\n\0\n*B7J\0l2(ƙ((kmg&k9jN'A%:0~ώEе'|ʕcyU67d&O ^f3ȿ:_I[PE3PFO3%Qtf'j6Sp<Ԁpp!Y̼1;;Fdyr_k 8#BЌ߹9V\tR]ȎzefIT(pC wuYHxN)-l_Y}刽a\nJ5&>FDV'g?CgE_>w0#p6V.9$Cjr۰8\0N$u~ɢ.6.€ R|y1&Juta=fԡʱel`J}UZ2%mF 1Cn41r{$\\Y@%3 Au`mnagCO=ז9CBu^8-DV\0 ^xdx3N4> &jy E(-"o"Z.Dc|op1n6&[Ty#['{06#LqkNOlRJj8%2憆7#~.>ALχW:\\JD;oyt,Dƙw{p?6uvx+KZᖀAWbYo6`6̠y͖xҖeřڔ>T^;\0i!4T[wC P3J>\nx;"\t`N}HiS'h;R^e2ĎY+7צ h臘߁n-MyO]n2_yBCbi蝂"'kdIOE!K733A@Y,Os$:~0g2HyCjOEg:Q|\\Wr@S;S~4̉ZJ[ԾSf@}\tbg@+GxqQ\\^d\nk3n{&yrtlfYM@,9~E hOQJ^v\n)5Z3o}x XA;0]:6Y\tsCM=c\nE =r&/z_u;ʅԀ\tiGuV1-/IR]pߢvi\09FAґ\0lc"0.Rx4yΩqt4yb&×1ev>4tpM["tL\tT>I'|4%bD \\=t3/ !?f=dGҍԲ{s\0G\t}ɇ)=J.(I=;a2_bo@4ʋߏn5Fܬh-L"\t\\r~D?I^u\\>I4ْoErTieO߮SZdœ9:vNۻS&xh_3rlby8%c@Ev z >0.yەT78B2fמSX Ęp eG6u膘656r 2 u=>2p@T@$pXEсyL[\0V41lF\n<,2;a̛{ ?#9Jpu+nI~D[D&F2Έ2?sZ,ZrIjwX;UK(՜T%'Sa|\n1RoQYO9\ti 80Ɖ^X&ˢL[L\t B(^\\W=M7*\n* N~2oj+h3tTMze@n4ɑY1X>5ͧ3@`*Ȟ9҇Ђx^reYQ7dq{F h\t4|b\\[UAGtO;\0* hF/6X~'I>b0s\0M9/uhE\nS ؜#f)dn(AhE)g{Z|C<ؙlaEx(ف \\1;YEA`VY$eMCݫݨ}\n8^qŪnO,̽*Dm{CA>.AzHPQ wO9 L2\0z"Rb\t#2!=׸]~z"Ity?׈GX&$9,_2yߒ$@qR43 #zyZ#sPKa&7]M8+ǝ@hnwt0Y5@ۼC?@gqk {K3WlvJq&uEo_o\\(t1i,bXi:j׈{x;l^ OJ Fq{=!MD{Dr+``q}ngOFƩ-OP\nܗS3B)9"žiH/C{4u#j(:>8#3a`Plyb /BeE goiQe\twBWKLi HE//\nܳkgOreHcāv)j&\tmWEU }iٱLh#qoV bmN+_~@/UnvIFXϜ'|n#QŴa\\fUS'IO1gSC#~QXe [wg@f#LwzcEj 5"VYfمMUuv6 ;_(3炼Rp|sSjmvi3`閆b;.ā߼iFϗ7t?M6;0U\t\nYspCt4n/\nl!]h?b0JC7^05n`ɧUV\\(aϠ(ISb'>ؠ;&?PU|Sua[yv򽽗ztm,82=eK7p6YLrˢ۴aFE052e|oqGb-'x{,+i?҆W1>iJtS/yXcMU'@Пz4pt1-G)Gڏ'[.u۲j-6=H_48$?"ݵǜλr`nNIJ FO)ȧD,-QUYT 4&'b|]eND}Wf:iFu'kY$s+KA4ʹxn/g}pHmWFCtyΌ@j6»$u?D![)3a=vk:Yeat` 29\njDLA\tW3-Ym:8b;KiTOۄpkVq1#\t\tGw&rLR3Rc GeDPoR\tk{RqS|'ت=kfqE5[8S\\X9\0$<xuU7\tv?֡Ѧ/Ŏ kPu,ƛ~<~o"D1O=bK輻!IKboV)Ihp.|:`&wA=Ny$^g}2׋,{! 9XתYT򯑈lQZ21+AIHABTUg}*/EiY|a |7sN%lJ^Ie)(嵖0]t2BGF2z1{|ڽ2/%e₫rOM4)FJqkPpŒL;?r]](lj\\ڶPSԆ7QN׎l㩆4/{- E/8ݨw銉]|"qZf^f_9-؃F)cMa(@v S>(oWQ⊐[v%$|d+QYaduu"vN \nP{"4/sNyQGKiŞI'\\lh˴#+f"9 3[m-T?P }U,:-ؚtRpnH}QX_8j/a-qe4;^XT3i,U3Ϸu[T@g\\ؓa@)Hɔ+PՙH2nې\nhO!kS{6WGV2h?T+,ʬ4썳l$=KPߢ|ODo+3cOOK9,}Qׁ#(P?B%a3u3BnB5n\tGwA9mvЉbxe m|a\0Y!({(s7kHQܛu2%1EQcW8WHc *$ j$0/T2(\nATW9i*PajI $bX\\u|Cw:U! R_5\tЯ)q%Cx6%Nߏ˟W7kaZT5l;gRȝǻظAJo|_o>7sC6ڂ[6Y{gO5h /;.V(e#BC4u@Nu߰w-wj*ØT0żuP6_1wA_9(V)UAST]w$`A\0Q-]wdx6ws@q DW^ϐtYn r< 0yי|WuhHYۋ h\0sGkcTHP7&ԉrf_;*w9eu܈\0b +EuF$iKS.Ќmgچf$=;MLRV0}F6^fNBK:i5֦Y-(.36e"Frv AGػq%\0SVʖ#xO.Ȯxs7čSyuuw$xm\\5tdbZ_b-]w/]J`.S?9xdiD>GМ-obaCy\0KgIPrrg DzJ@}՜hk"$@i%@w/sL1=H?V-\08%o'z B!?ف {hre3*`HںLfQDQͣX,(^YVoFgo~1Gh Leʶc~R'J9էa\t4~PK({"iv?G[lmS7khSP$!YyV2~v[ qh.,ă(4b=8C$@鲍&Xndtl.Yb0QN*U,'=AŰ`USIK-ևCӄAhyk4p\n0 }7'Hbr":RkXBs>0UMl^c}ۤE{G'<hBT`\\ja9cXB\0Rц!X_Ooؓ"]A/U[XׯA{G47mZ"VG?}' s> \\bE4\0|%?pJ|ǘe#Ї7%cLR`=L-Ml2~Β9]O?8/^S*Ij\te I`:]58"QF9j'&B=Q775e;6sa|>* tAO$RݖŠ3>z쟷 ۍ=JpuBr)FY<|h)\tůiKj q&l~:D{_ibcцSn9'ZpfB|K :6mhux=\0Ѻ]W_Ԕ)k5G2䓐M`EU;ݫmqs_z)@ˌ|T{I4mjGS_)oxt$"͛l0,qB&p)T B3p\n&Vҏ 5l\n.ReRӜ|8[#($^^\0"sK\n=bzT2og8o^8\nή$4WɔS88l4HZ,?vs-܌矺hE2ٚsu,~˼T1YˮnDŽxM RW|+<R}wv.$b8[/NtD\\qͱ['a'0*F91N09\n!mꄆ^a v^PKO2X\nFV, e')B8XCI6؂.1N$˕OƖr1ҁr&Wh$)PW2=8u% ȏx ϛM2V+\01&%22?o'K1/_o~@P7V(Mty:TYfAT%f!B$ѕ=cAi$4nH LG7.T3DL}1NZypXkh%,̕V:_uz~:۰U"-0-*4ݽ12p/|H "ȲD٫ҤE$/\\"΂y)<~{XD)6\\ \tÐvڕZ&L, 4} {D@œѼjA٘=e#]1OӬǠ~ Li nZ>~< giN^4fmaQFZC}m)#]Eҿ?2h oCv[?== XsFqKgZmBEߞ(2ks9`~gCBSGմ9:lB4ĻT@GWF26(2ߜC?L\0#1}C2+O\0?rCT0x0ӎ͐3jzlDuEAixo^{w2_\nY!hU8"(t<imz [ϓy *'TE'A|7AZ|\n5 ^XGHK=šfJ p!͞0qG>3*nΚ!0h8yrL s'X4X['\\u|?'D2 Šʨh1>i~R4vFMh!5{S'H7F+\t\0韂C5vEUL'h[kΒ\0;̗W w=\0*`u(>@!>٘Wp'{%LYSQPC--YqY g|v%]f^x6˾?[t.9Cq B[X2z&7\n}݇Se Qa JNֶY=!6;AU&jAm-XB.2hJS4Ǥbyzl/ׁO\tzӒdwfF{(\nYBo+!C%0垄,XZ\tha:7``9!7XJuK o/&$Ց"⊜`\nHF5X_aA14a⋱Uښ_LX\\bR ,_ؔzP3VQhE^pF\n杶uʱ5!| XWܸNԯ߯#d/ϛ)4L`d2X3LgU+M?SʊoRYޟUХcn!]`TDySI4"f'ؼa\0{RA8 r.B8,_"eٲ@#C˓5'ARPE<))%A͜`\0P,W99i=x͑B۽ VKfWpiaZ+Y׊*wX3 ]15*He?Cm;yPo|epӨnEqA!fd]t\\-ma/ͦ\\ZCT$nبc{݃OqoaDkl<\0DĴ!2p3T~;R4`  dt-P-e$^iՌЎI$-'Yˬzn[o\nHy/\nz2aM <7=t>v7@rr(w֔rʬQXB4c2= DmP*^gmAcwPXͭBfr;XI09Zw]XX+")x:0sts~a? |>f'boֿ#|>>χ{?{O}e>~sqn~A{|;{WzͿ[P=zK~֟ߗחzX\0s#67tw&\twީ\\kю0wyj齪Qȱ^!@SMZf"+E6zBH0cW:EƵ"n*5.Sxja/In$XGwa!dD_5qX||+O(L4Qvƍk%n?=5RfKv 1LfHkzSHWJO-N&`g|*' [ۑ!Z@xI#m'/SrdQ1?M>5g#V!. *ڀH%^VAJ\04Ĭgy\n}0]σw[/Q0uT-m9%U+aH H27o}3 <\0?(Kr;<%4P"9.Ḵ ӤtfOt|ɠAq,q%}X$\0eV&̘fjMM{\\wζC9@<\\m37K3lg2E|Jj3t;S9儏My|GVkA~;1ml 4>{.VbNN2 k_<-T=Kʤ; v?F4qYPjem:gmnc%"蟄lf7)YLfQqwC\0PB^0-T8\\\nA=j_%B{0E*`XxmdVGSF!{A. c^c'ߪ]?Xu|$llْ򒡎ӲÿB͎AQ'>ۑ-O\tzk1khAm3o 3S'ܗZP]䔾f%<\0ǑsFg?;KS%ؐfSF1,l8; |YfLu~uw:QV̼WXKK2*cvu;[aP:aBm; `Vl\tښyU#y"${8)QI #U!QUjlE\n\\ʄ6Pm[7UO٪I c[33`9^ד2}2^I9Iܚɶ]q(=5\nٕvGNM^"\0\n7!i\0klOxn;Dx6Q\t^,e#2A0LqFbզ[jR)t~C>MNbnpjuȮ˟[m=e%D!L^/\ty>cYWAi!@-W< NiϰyK*(}pC2]Uץt;"y,")g~{!Ut\\X)UČ#;5/ƒ<͵N\\.hF&Zw|͏ DONtb$pk_7T;PO&K[.-ѱKė4"l΅NlPmQ6D rr[ F-J0Nӓ5\0g+:آ \\3mC" \tj]);q۹qE-duݐyb\0)bΦvWB ;IT|MJ:e\0:>-i'53PZ͙,.]Tv!0 ċ7c},!Ph'eUAZ#]X~k):K%0B%& ?AV&!#Y̬}2by=5ߔ{e\06o\\rD(M5{}{"ס\tr|'u&n|H쉗}"e~o"g^H͘,\\o\t3H85*z> ^2*Ed-Lڑ1JJ +1tɆ;b"=<)M w=KG4T\0tkWQMpP=aD\\V8Vȱw"}te#^2LHMYr:#%+ L\t!>N98W \\CKV1WEd'~ab_=BZfzaJfa/XQJ&eGPN}\t].h{+=$t4hϓS s~9V* m59I\0Y²qreF~@C!j|AυWDOz/qbbZnΝ%^l Ԭ[f,4W;a^航-{WB>8qt 7a:uXtZon!vJRo.gvoڢmwe~e#8M{y{`G&7|sV,y^pUso}n]cK͕%yO*H@\n>z @\nl)O)"rR^\\JN3u4"mC\\_o$/eu\0]4Uz|h ): ۱<ޗ\tG1!|2CI/yE>+q"Cҫ< a[~ O,_nPk~@;M1{g!6ZɱTm.^]߬T hG&>Ӷ8\n8:]f\n [+^"&-'s,L*%Ip.NÖ->R }歅FAbҰqY]!Y@%5+qkc4mfʜVɑra0 P(2elK΁&ße]Ae@i8y>LQic>5SaֽSp'?Yd-U.~\n&7q@2RBsiSɗڽ%rܩW'~s-VJO{>=h%GM!k{%fүpmϫ' eنOp\t٢K\t ȴ`Vv@zNP~oR<)3d^fP5Φ,$o@vK9ߨ$U\0_)oޘ0xH0?!2fwS-Vy)v \0-\\e ;-gܚe`n  z\n江Of@@\t&8,U{pe+L~\tfƨYO2m%:$P IDWjH]3reKgG/|t¡,\0z?"͇9/Id@(\nxNHp:/)1I WT2"0&ɷ|fޔx~TVhBX֌9,kO-2fd{S2ˋRx--̑>j=hZCƬAF8 WA;f\0I]<(r.#E2٣zN?U-X"_uwW'`0r_0aSܱ$Ƹi Qo ؚwꤽbS7_y:)iG|V`L+$ b\twii9gR%F0R*ROpTRoХĈ\\#_=\\Uo4TyKI;87B0M˂Sr^w=:g?ֆ^A\n"\\hUҏBzF$c~EbbI'{ XBs[42wQ~cwԖkj$^꒡61*ZAn\06?:\\9RBSQ~K%VTl(f5_;!JχMiv@ dYY^o\nfp\tnKTyPWsExu, <`{JE_) 3N=/\nhJBkO$g?h6Jk|lըmC33'5u~%.2[^nlG'Y4DQµ|c ԙ2S!]E@Fp2gX}[*󡀽*\tWv3V$w6?PfPFV- K $s_Z2:wV=.|dɭx9\t] >rbW%jo6\\C=":[%Y#F4@swA~=X?{MmHO\n~=DL݄\\fSr\0}1q&#V󈋏49٥6Ab:ז5H \nKsc-I\0`~q>`a(bscpH>t:c'G;"H]}( &I:XȡhIƀpz ,^b̀1`XS)I`!kEY{hY>W3mЂs)G@)?& ,2%:':țrhԈ汒Gfy25͒ H}exLK߷^<*l>?wX,[bLdkEpքX.o\0>`< U\t(iSYWȊ2yHkħrXYD{\\޷C&u/T$pﺋ ϗ͞~侵M> {qo8\\)iU_jԻ[ўC6zu,%Gcv~WtdG2usxtqyJ<T瓈c)-X٪|2._uJ4"ǍFŗ!Fo;<[{?{H:9pjH=TyFvEY5G(l[8!0ܴNIj]ͮ-B{E-o"j2|\\GLuA@[fy}?wiN8f-$$0+F݌I81cD|Pnx‚։y7y/&/4@;7YV<(&\t_a!]ձOVI2Fc\0YhӞ<}鯵J{s>We i7o-ut`ϷR]@@(azg%{rHdzFܦhښl$F,prwZ)2+v\n.t̴<o.?bSU7]¯`:"!l<c/\nuw_ikt:) -2㈥ (_AfE=\\ݬ9)^=޳>VI.qa"">bZZIkC{YX$M\nH} 4l_yvښ]\tP)֥F O1EhhcRq! A89wQp'M*yQKlE'Fu6_GZ>Z\n=检<#A5rc2=-Un)xxMif[HK=B-'mŏW1IkQ+ze 1Wv?>s3vY,rl7W4,Rq.pbO ר2aLڂ-@;@wRs\0D ^ΈSVz\t!o<ʜXmqE̘X5cr/FB:~?,KE4Ku-S0F=}e)8`EbT`G cu"2丧o^֢)ro_7`s1zJNWHx5$,L\n=fMd51O_ppᯇx)%u|^s&w1Tw {w8PwY{jἧ&h%ZN~wUz'/glEffIum,W%5*ZgVIZ(2XGp\tnX6;NXR VZP3OBL6w-\t {5_Y8p6 \n3zy232[mn0t ,"8E`J..݂W4Teya'<6LΔQ\n[>ݨa\01ngbHxS=Acs{ A\nP0*gwAHHWf,wOGUA `s5=1t" iV_2{/÷2p`1δT^id%5\0~1l[^%iNմ9IM3$~ScbZ%Lj~XO]Ac6^p\toBvصJ;\t𮊰FMi9òuZ^F:эbWc&;ϋ&Xk*UB`vseu Zz>7DF02\0ss4+2UdxHܢŝ@7&\0DرN~AgfվM7)[>\tAq'IrnhR9v\0T/ɪx w"yhk=htrևa!U"M!&LQp&q70K%m,9cxsmga@8̗ȨnXO=Z5nC2)Y%gXalwNK4\0 Ę,41 Uʛםǜ?>Rw3mzҽb\0L͢ԷIXW7(\\EB $Qޕ/#FE"`ߕ#({d٤WIqNNgn|iTǦX{4gbP``nF=2/#GIM4ɤ+ !K^ժWSAdܝ;C\nn#Lt;nZaXD3rUg' /F fm?yv-\\Ed.vbYɆ+ثrУ+`",f]͒Ջav=|o!0.Ʊ6v8`V2LwPa3H}Sk8 509y 6pJWX_HV6zC2Jf< zGT=}t>D)\t%Hu6tfIH݃")iTJ" \\6ĶǖȅUSWm` Ldr^vL_|Ģ#pS7+26d6Wҡ/Gu7/ i|oQwl0\\wQs?O6߿}‚B֣(fxx@"[h;ۖ3} W#5'^mߦ-\n+0\n%&W)e/xgbj˂YI ǶFlۊÍ)]3Y= a: maghAy݋;5[{;z+!2*@6s0@u^6OS*s0!3,OI]\0:'WOJ^ټ,/mE c8~g$\0zj(z=[\0":F:5w=J3$$kcP?BVL`lL0N=v㝡^!vߌ>ǫa@|Ak1rklݭ$t +$ǁTb8/$W;`f>Y2՘c$?kۮgqw. |\n鄖ϰ7{K)t8K=U Ht*f|!~lWb$sh#'. . o/wAnW=~oWER|\tBlx;ӺgAitf|5*%Snykc&ŕ12@ɹD? D-@i9BЉ>'s\nֱO5 E)hxc-eߕՅǑ\0sOgy$BfC% aX?L/F)Ȱ*5L En9 LB|HNݕzt17h9iD2'øTz20#@S%f Q5ٱs"FĤP51"R Ds/^Fb@2v|oIOjB!!0[Y*6k_eժ(HB4Mx!L1Qnl,q !)=(&U"[-Qnt^^8ԵP1ԙ-ܻm+z!$AOr%y_q]sʉݺ:Hk1W1jn\nF抓IN/R\0έQz7(f+}۩"廟B1y\\ʒN1qr1 `|NZ^ޏ:G)ls/K\tFAWq컥@u`0\0;cnd}0<6k_FyI~[Iw c%1hwT3+hβ0:ZҎ"֏"]\nGO]yWpf|ϼ,L'䴳C_E*V ,T6dP*/,ރ\\FY3â'0/TX]./V8#A~CwEa7lqAxޣNB-8^.]|G5 \nD~(}ww.*fN )XGmھX$b\\?-^Vծ$\n|\t3~{ZL|nB1pox AdE0߾k;Ơ.ct:;VɅ|"e+@;vO+%QjH)0afs-VF"ky{\n#(rRtDgIV"; a斩WtM$u'CrF, n;{z7CaOJ#4_,\\W(C⒵;XV;r=׆Fѿ"\nR~\n9Mfl4G(=\t\\kɌz:s2$8|!YG͐Xd1`DZB"QȚˠ?V&gh^,z\tMɟv+|%4nrb\tne\n{P˿Mo/S|̪I+i\tCmro2m 8ՌP^oeS }[Da1e7sS_3keA㕾ZNwwǴ= AaV\nV E&VOֵoQCr)Œ;Ѳ/WGef.;zbl!gCϪj <}Z}uh*meU[#̽r\\|73Q$I f0\n'XS`<uh _Q6-DF S+<"-!J2J)|Sb:`{?;͖mB Scψ*MX? eYkk]8s4E\n(ks֗ΣUv6_&sȏUvNHi >S6\0~Fb*sxt}mQi rPCΜTq94uh+'P4Z//c~@\\%oI\0 UC<{nOذH7Qd4Z~ǩzKrL܀cȤܠuEcÇ8YJ\0,A1-PcE=Y(V/~WY?(B*9aYadtUD/6]:HX Z6,5 $yR$)YU:ݣnMI4o\0GNP>Q_RaΨdG3ɯPkZ#-1cw\t3=7 ]\t"Qʯ3;y\0/gk\\6 }κvn~zWeSB,'Sg=uO혅O!Z+L^HzϹ^O!Yx7{x^c,8PZc1g nC%y_|5F7L zA+tBdhSt"/@9bavҗh_w*r8T(NtI4AfXCBŤI}`W#%\nϟ\\W(:IhX,28ˈ1\0mp Ńt0շ@m89^-(UDAmFc)Q/ٚƨڂq]2Q"0iM^.Vϙ4?#1M̆<ȡ0\t*[?뫎Jc@Jl.HAHx,_3/7Az>\0 rE?J8,bGcXo-$ϧkRf4Mm_i=u!-+EZp',}x5Noml/Ss Q%㜀`$x ]TZ><ňUo:V3"}Pn㘏q!Vvvz5^ny*+|%%%4:111]1CӮۅ!k^vp\tAQn"}ztzXI?N|ݤCVh7_`1BTBJ6glg=dCScse [.M-hM7\02n AyyoK1\tT6ny-TIí08@Ȇ ti@" d"6Я)5ԕ@8;+mPR([_ OO4:>\tӽ/hM/GciT< "(–+ǃ,KWгh6tlYF{ ٫uG#%*  R'3?b܍VSˎ!g5W=XT.qjH=LTF \tY^$7Vf~X~tE`^6 .8ⴐX\0a$?s_xớA˥i'uJgFKia& {,|'g6!\\9̭Qxi|u<`HY]_/W\t6#(F-t}AccI-FT X\0hw@Zc(KrHL,7T$Xbzra=z ?|(q*RY=HfTBs' 2φDøZ1PTӈ*f|6;k@ɻD{n^Ez0 EWc]$ݴ[TsRl^oEݱގ?FzՊK\t G{Q&tUܴ%2.\nFָC[]&}XGSq VڦAűQq>Eg OKΖA(v_R1AGYm] v!-[EHi41d[׿aQLzY#el|.@TN YV1KMbaY!Sy Hgվ?~9 \\\nb6sV!3;"\nsӊb1,R%04K Z∗Jz>Z+ "dt~D_T_  wzaD#*8d<q}L(%q+gW_ʕcCo$hdV/A?+93*#ˌ~(p,ZXәg)kJQKK7F>Т ȅecխM>aBq:Z]ŐJkh*w1DMsWկ]ױRQMV/(˿@U\nlgRh8*:\\WZ3ЯB`t/87b%Nvnʷr޻JKXzgTgd=Y.YG S]`/iqoMOCy0FJ*/yK\n_X#"]3&ڑ{? _b%Jk;}N_"6T!2YO K +ug?\t΅3+-eZySTu#fC_(.z! (qD%Ÿ\\y^2̡X NtN^w:3R~|L tg -)PVN\0.qBmŀ̽}tƩ2MOSe iY\0όo7ӟg~`s3ɽÐt\tᢆ=@acÚblV Fcj/jϳV ?j(7\n{X]]~\t+NpA)8#&q_-OO\\|p[A:OE>Olˌ};<!/IJ?\\ GNK4d^$݂C" %/)DFu[ϑVAQ5@{OC)8GmQ QSg<\tl\nUiNീGNN6=E,6gGQchi1ɾM>Ι)VqX6VޔLsddMN5d\tǘ3>K9y5~b'^70# ̆ݭ[\nP8=X|ga_wVedhSV]@\tS8\tGy,-FfᮘtR .Nci.6εZeYL vZJܺFeL\n^>Y"+s' oMJi愙hp_x$ꅢvZܒJH'R$PARWE'D_+%z̴P$ IJU`ƚ_Su12̸#k#n}n)Z[cy*PTn\0UBS":p#g'3֢@lQwyCCr)5Z"8іP\\Q?o]XK]e53ix(WS;}4N\t\\<4֫leĮϥ[,V.a44y&:v"oG0i ʅW\t+6 8ms4G`PE)\\m5Ja[G0 L~ǥǒ(0(Gr?@o#?˄!L?[QI KOiXБeрBŞjCdž12 F=\0⦉[*8>zC;;uՔ[1!ujkWSm?ڸ*#i lG-i䴯tSAn-??UQ;3B Crrm&x5QZ?|id9; _ש+.7`I=d>~/\0X:twKSh""7%q. mSMaExyIg~bJXf*fgB4:wqʎώ:,blⓩ\nB@&\0@;C-M9]Հ0s2ןw\0Rht]YÅ2t#pg;\tC)VvG=\nŹҐ2BwuE5f?Jto"OޠN-tdoctNïHҝ2?gF\0nZݽ XI&l g(xYl-C &FD{-82=DXsmB.\0'<~0U|JnS`b:jli';:H=Nl\n,Rn%j6Cb)"sp];Xvm  8`64KO\nÃK.^ ӤՠTۓ|͊3WSVO#8KE,tausUVݩH<hMa%)8}Btuj ƀK+b.\tQ&Xݥr6(.q$d%Rkygos, <-pAF &@\0TgR\nh5K#FJ6t֔B\\b85l&O $q~;-p<>yb2]YͰm8\t|k'z+>I S|U*\tܑ=sj+* b0Д]g9B&Cya,@ɽm3/\0Osai/>%R)Qe % q r>(Hnb'})d$Q֫]y98Z\0M`+);VP,AET!^vWB\t@lBD`/։MjSO~v$z$ |A(Qj;OVVVmM+C>+f<,hkֹn n@!ߟ@E\\E6QAWi*mzWM6%aS^h9Vfח$G'\\Igk.ޤ9QDuhɇ&\\ebEP)$`]H Vroie*G1)gQx\t4bH'1$`|emCU\nȖDcS&fLh,{F@m#F\0Zj~DN>QKX|Dy#a'Bʇ</gTz^;S4hNJdPmT2z7V!ShS&/"/) X*\0,yx]hjG|ƪ2h(Pn0A5#AQ#&ZKp 4aJӹg'%fh_X;g_(G`Ff2' \0NؙPwk ӆ;:f@5G;v^@%DU*=0\n> cdEVWuXIՉ"ukwX[IL;ZauN,g4$~rw}\\:O_/~CU:ZWFEPhN*wڹkX\nȍ\0B DUŠՓRG !53_ > _;`\0||*nM0}QA(;'?Cll J,Id78 ZS2*10SO^IJ4 q| .3ΣshdIw=$"%GһO\tļZ"*9b_(OaCaԐZ-pAIFW *GōfH^xWq"ʍ`^?vR5cs`ڊmRh-X냾Hs"82}us#O1:T9J:<>V$w_u zcȧ^_(^<S*\nV>QaR l4b)$UsiBq.쥉NJ$kPH]\\cu`kqUPaL$縧>F|,U$;KORض=mT@ (ҝ8O{*P~U LfʺsͱyJxao:1"=a{u}h$˩Ei\nk83^l#dz]ûM3Y0UY n83FZ1V|5z:R9\t>88|I8&tXtQX\\8cuc)xEClpa_pJBen!%$[L N\n0!Xݘ[w/Ÿ-ؙ0ǜ^8Zۉ7zWF\t{i[L0LsΉ?3 Ƴ4DH%Ē5S>W#w1LxcD\njUro~h\t|naƦqkgL.\\gǾi۫¢uk[I-n<(TO\0ZܰeKKdl ,sJ}E ;Fi\0g8\\ʽ"JϷ(Bg+e$p{\naש=Csע=G0BE\taF=$rmO\\1i\n$!*vSx[`++ KX&PYsMsx\n<|[_S(/x| 7Na*">*YuΨa'}˙RKKy 73{u$\nrQqT*k\nT++t@W(~1~g]6ޡia\0E׳-zP~*j|p]{]\nY3}32W\n.) *1[䐄⣽PYRb#ld>\04G,7FLt\0avDW.;| `z@23zjQCڕx<)Sq&,4\nQ$ٿ*,ت0y~Ц@,=^B\0WZ\t:arT\t[Ujk+Ovī!#qᩏ`lfaY•O~%=ӓetɆ7+Xx sy) UZބ3rkRwE\\슱j7f.|^ \tdB6\tGy!ņ=[s"빒ov8^.3Vg9{=4|\n72s^^~*3sg:F7Ӥ=EqyJ\nÈ&\n\0F%e\t>oa؄+ iXt[N_Fjv2 RqW&[#?Kvȫ\tFjb5pozвG}аY'w)m yzS0J+g\0]JXm@?SCb!؁rnJ\tY\\0pnӚ"R" Rc 0sIDK74"h)WTi,'n_E= #W2QUϭ}Η? ~5TNL NG,[Cr;tK_L&}ͱ~1-\0r +͕lfULg*O%S+m6q1ЏD(aOq޺GBvk2f==z$ gMB x"3ښ:y{kݮV{ wU-'ǑFE/7?k r-қnVA"Nb5w'bL20FXryZnLHSU8[WU}2UptߓعeLxNu-ULYb7m\tX.HWeX/r,p9u3RslWðYR],F͑ml qۨq:%)HHQE+|zx3d\\C1puZrlO}#-x‘f((VP$+S9t| R',mfKMEGY9vR8=CSMA!6 \nc`wGՐb-=׷nZKy3)Y9}OTrm0pÄ8K] Bn6k=Jj@z~^/Kޱ'Lޏ=wf۽^/n*52׮ ӹ,C<眉\t^ÊDŽ JZ!/զ0A!x-CR.4r`\n@~ a_&M,,Y2Cǜ\t\0m\0dONLi8p\n- Q]Uw۲9sh+ԕ(KpH2F]~:\\\\!2yS72sl|8M42/>Z>w;wo\n-V9],!WH=ٕt\0Ҫ͝'P_`:;J㖾Zi/q&5k5r⛭pY{IǍ8^ɇ^Q|?V"{ g d boc{ڌW@`k2~%p #ve*p\nK5Dcys~E'' VY|TQOWJ\0xLnV2Tb:<9gCl`Am@3==UqG"b&-;JhָmP)_}@ {Aip+Wey^{jGbm2C& 65+=W\00f3tgCHء^JtexC q}gz'V>LP %ȴVhA{`4ɛpܺpvT]F͌\nzxxfw:y_u&ajVk ]R+4->\tB+uն ^F̎wT ts\nEV9£uEg ӇN?\t/ͯQJdюz)ƭ 3Q6rV;dV>сTC1 r~H|\\I}bYZcVzXʓh~P\\a*;$[_*h|CFE~k_=_lΈJ/Q>"ٷƵ7¡|7y?A+onoNIŠAa,ViN|U (VK-k(TKylG(1tjƘpN4lZ}a7>¶AA̡PkYqKwngu'333^\nLѢ_C<&ܙkLdiϚYEgXQ\nLA[+O$4K~'86$yܽUTk.'iuW zN;kw~;w׫W vkއOt7zW5uWQPW\0=n@6.@V\\>1۬mySW7\t}YʎT7Z2)”,5z$Xfx6$'凝L'Tn*  o4:.B.>[f֫0rBy~5a[xz24Z\te_ǒ :-8Ts1E 't=G.)q#߯McԲbkk,j^ x"pOKMI9wh\tѿX\nWD\tةL4xl(""vۡ,y>up `S+%6% "8׵%^ ;NfI2 %%m.lmV'œ_IN4=NuҹCH^[R@f14Iܰ Azu>/Wf)7;96BF uNMNJ戓f%66;f2_ ҿYM$Ȳ\0 af2nKu\nvVI7)rHwY"5mAKAPjcW[|!+#{b!f*e?Z+rq(p*rv̳Ø_9cx:BVRLcz1i!rjF [&m|a40"Nnd%eQb#X5"fJ\\3ZL~3$V#ֶyu\\4ԸUH لjGBD%ŋn{@'J`Ffv`u*9G?t̂ȕn 0GL^|tO\t1f!NnzL\t[2bIE\0/s7OjrK@/gO\n`{L9!/1lKyyAmhw_*B.:=9L 8="O7ЭZAOf-ekMb~ih4B[.6#+\nb:Wc%%e<;u'a}{\0 EA4]S^O7Wa'skzǑYqzړֱPLyrz91]s F1eA)L-2Z%գ: GS m;\\'u,0_`+\0g>UWr/2|TYh)QF\tFLj8RZx#A7^}n%if& U|[Be 8TMAwryI稐 rk<[>Վ#l)jp+R);E_EҌZ+ڭ7@{J`8"Pm+NM!vYhI1ʗ-A8\nUrr6C|,2@j/d ڷ(U巋hGW{ԓicyұoRg܎bfL#W"dI+rRV{f盱 "Rr+,x\ts[26[v:%8$$Բw‚nC+;̏zYZClJ>ޟuבDjHO^}KoQѨ._'r\\`\0KvԍU s?jTq!`{0>lKW>;" :wO\\E<=v|,2u$f?S{e5E%<Ώ\n-RT{8vԾ~Uķ @\0cm3\nkot"6$|BrG_T%R(v=.b~scZbҋ2 nkm>{IKvN8ڥۧE* зP7+O3}^ HKOohz/R1 Q^OםSUGS=SA TT'!noj0oP,H4#?PHÇu ?cl2٤V~NCKRL-fѓNqF!CY$5#[7`DvBMܑݘxu`\0XUv)R 6?0GzyodX ԉRb}\\95<.!uUCK]]+=uƔnh)hKe1|3l^:J_hzK>2wxo@#GCN:I+hlmD̹1Bp0K!\nE+Dy+T e\\\0h |GP LF\tq^ g] F=W=*%d8OEujOZw,(z=`Б2K,T۵SNfL4<@\t8fy̥#qW|}3V>Y8E@\0F>\06\0ut")pp+o-t $)7A\0GTY- (Tm*_%aR/Yh#CTsڦNE(Оn:N>0a}|`\nKu0pL dAݩۯa9Q3ѡj1 u*`,+UWkY,6-EI rhhg7w,H!Er'qBP2&VB2I\n,=?sb&[pCγ\0/Dsu#@S.j8nޤw̃!*X4Z՝ʌ̅dDٰEN`x\taGf>P$sϋ,!)yU2x;IJጘ 6ʦ]gp~ \02t>("v~3[;i·w8 rlზWg6}3Sk9Țw#Væ[?=ԖX" |34/x 8s(Xk£s\nPeƭ[FwI֊G\nt.0>x6ObE6Bv8SήǹR;˸0j}'3ޥ)4RlS&SoyV=YxvzVu>tqmy'DUG>wk=\08s Ǫ/,_`am!\t%'CehFK)qKGj7}4(>2uRץiRd'3e1fE`lp;B{d)d3?½سfHn1cQ_TXf]^]lg9 m\nKAxjL\0\t^N77g޴e*.ƥ\t!Zf-wsmr9CKNNTPEl|o}*\t$|AE%"q[Q0@WatWbCa6R 80B>jJ~\n~23Bb3.B@24^K (7RX9ݺ'1knj[%1~Fuke 07X`S#w:Q`t񥋍F#K+!:CյrII0wS݇oNC50HȎeާ\t+5% xR'q!0?.\n4C֌ֵ1RX5Z2Ǜhx ޤ"hUJ]}*@X}a~ f=zL.\0#4V Kh) Mw_5w\\ReI:D-Phs\\9>ThV k=?kU f藱}Ȇq6@:7Oکzgl\tkPT\tvTy!qLA4 d7)T2_#:\0W%F>"#_O^ʇ!Z-}u\\,,UdbcF>>mNX_ThG+0N+<ܱ#8~Юqe$O"M\t˯a6yEz =SotTG\\'|2p*YV)ˑI: c2<}KBJgh 95{a4>5͸ea{F򠯉kfo^7*8YXl#&'at~voyp_ ^;S{`(W8DGD?eh@dz 0+>`#WB\n5s[rL<,s^5x<3'vF\nf(\0ށeϝ5ܓf\0C]Pl\t M@vz^wx\0OQCdҨsøP:w[yg8ff"+g=\0x]wfx\0P@s~_D/A]|QB,HTn=L(). Ac-A:3@E^->AV%Tv]S;_(b=$wU"\nkؿs#cCF L"[\tD[ t̽쎬W/B]4Ҹh='~}lrotx08H˒&\0S\\OgM]Fa \0(iM&J\n|^F=)D 8Q`UYC>@y3ʄ IfWh,O7 yZ^-{}2Zw ?t=ǀN(%\\_\tZWQQ٪bg9M_/IsRk21Vjm2,H4[t߸LP;aX9Ș|G+lyĮhd~\t ۟}虾W3ÇT=b!j;x\0ҪtwϦ|vGkOin= .\07aeD6,n L^X+~kH*׿[Ϊ6vE_Kb#4\0쐦4YEWĔmr[PZ{^f:]ON8Q0|V$J&7功d=D.i (5oh+Qа\tk-΍v20~\nX>\t 4b!%rP2vv읔 ۊ>[]O*Sf~'fbl^]|-r/>UHd\04 {$T>_v8Lb\\v%Uq/(xs\tŊ]Hp% ȺUׇyN{4E,|^D'攆Kb :C?2iaVYM2X 0Q90NYq\\B=\0|GD5ǹY_WETe-,J\0jv}j;uΡS5\0ߔ16-R\0ТDtt"\nD#,pκ (oUkV>;5.f߈vN[wȡ\tޡJ+KR 9F vmN#W= x~ikkWqPA^o5V/-@NT\nk-`]/#!(>Uh,V{6`t`WUf$ķ5Qlqlk}s/4{;}Jm\\)v]Py Y]uƝgXx\0F+P`CNO%Tz)ŀ@fiF;,r"UFւ@4D,S.L{e\\՚8\0P}^_ӃyYq]"'?s=_!"VC8\tƫ89VEr:U tN ؼ\t NlphJ"3CM W ;36$11]9HgqDR}/Cۡǩrw\t͢iT'! )+W"f|--- +\\pۣv2v gT* >zy25\t?`w(FD+~ ޟBBc-}_ގYjKH+t/lY J3=+vvSGoI/ u^q~X3)pBҠ{z\0iKK\0x\0iם`J,T$qޱv = PZ~gC\0=&Cu-亻(%G> _ڧߏ@|Ef`D:…J>';_|.^\nP&%WcvۓR:v?RB4/2C%; i IL~/vR\t%V8U1اpœ9'َKtSS\tm$sS/|$?eC2gIw1Ǫ/RaL~l)HP4_6_SP|f=jwg7LAX\tc\00nt%tzr#4X]h/d8;&ο$2Ʃ iVQJ0\n{EùAGKl¥תm7tVΓ%X&H"ȳòW̚ &Kb 'ml ;%aҪ0Lg\\.ܪaw)T-(]$J=Ș L1\n;Y sr!>>dh0!O [%OEGh9\\&EыɆPB\0ktj=38 h١@M^. NeWF=wo"5\0dg7ר|'{߻@reYF p!RnIq1ݜԈ L+NRV$?rZ1%$d(/@4 I|l |-?M{L2!K2|=7+, ބ{ .N{L{.\\,1,'#6XpDr^̜-\n)جX@8EhDC ŗ\\o‡lpǻ/3?Ҙ هcyƋ=EF.yf0mzþM΄T;$ܝrKjZ&Ar?h7_XiWIfem+ ­y=G:Ɋ|Yz᧸5 U:k񯀷jB#:PB\0ɅM&iWp:Y`E\\ZQ% (L W?JE\\K 5.Fawa;y2r`1=sET<Ų4yvWv˨QcځzwHA&{ BU!͚fOpZJ3(O3Aa9#F;CWA@1ٍ]?F0Ran}L_~\\.OH\nh>$O4$l_\n},]G./pAʲ(vIBb`MM*Mo.(\\D"9-ډ5uتSAydaX= K]G$ޓ@@}}%vYdW>\tƱFڥ?\n^ATE 9kV?,剩&lbÁ!C}rDbY_]L^-Q\\{R_M3S/Cʹxˤyb&I.auC*Jf*$آpqfթ#(N#_:}'mw\tB/&K*P(Em⺀+{vFhQw+UP{|l,߲4'BO!/`Pcl+pk6"{-09ߊB'֩힒ZѤԟTg\\+Cp!_sF<&etÌ8vaS6\nF[JG3.W~_syC<'&O/Ce RtĒ7!FX~\0[/~u-PWENiM$,>kAϔ]UVݣCaAyя-,_S&~\0lO>,@N|t{G\nW^/)`@wTsg(]n?і]6#o R[F3X5{扜W_f Z*Ro>ivt7elt/"W+y-l3|\tPt;@$+tXIOyewe{kʒe7Լ7vb,a8Ό3^| | )Ң)UK8pRpEEÓ|H+Yi廛t׶nPqқіיՆci#\0ݽDBłzHr-E![})HX)݈x "\0^kƿW%,\tPdC/;klō䚴/aTsC#`і5%pʻ]&v7mRX.|iΚ6\0,mǐ;W.j3[j"C\\(ysaޞK^\n7eP`4zL5N!яi 揑k,ٗ"ZI9l c/,?EmĮųД$q]w'!%Vd3qRYLW!oz"wj1z-'4bgUbYvn\\@\n`9JrҺ:DM0V\0ꪵ--U\0$?ZWI9LǓ:4`ST@ZoڞaK/xsa.k4`7e08]XѷՈ!}8Ψ3ۉ/@AYlŵwHF4 -!IC.TDV' tXS7 غNXk_/#O:{d^Hghɿxqt^ޮUރMT=ob[17r"WI?ڲs U6D`"YEJL`ΛeO~~[ܜwbDplηxӌ\tֽ,O YD.z#yzl^(פG2^GG6us1YX`4tfYOT;NC{zP:ydaE~eiCi=y慝)W%MmgYRAr\nE+sE(tZW?\0ZMQc!;#SUaoْ=s-?lr\0nP«8f0-)ƛi\nsppd\nǔ\0\tYPuKϟyk74?vP#F&?ځ-u1S6NV|昝!?o6`x#}050kf5 HD~;c5:lUB:uO0f5J_ UOEXuVxMIi#6N.g悹E.0M`rx[g?H~ *Sia0ЩUN:o.^EbK:7\\!(Ofl- s_mPhiҵ&]c xu`Cnxz/I7Bi\t9!Ft␕qt)iVw,b1Sl6w!I_Ľ>p? zr^Tb==`2gl4~9N>rs*1hʄK ktߣܝc4ݥ9yr}ܐEMߋ-=R˗OTCCa ]z ִV-Ԏ߂; \\`0;b\tV>Ƃu\toeچ\\ -labg:0tdA1ǺWoX<|:?dsvPTi($\\[!QkKճvcY?[I}N|Ω8#Ķf4ѣvTaRȉCwlxWt\\b (-wt힘049VNVR%5xpWX"@Ѓ6Ȯ}D,HH"ijb\tT&˜h;=7,rG1#)e\n1k4 )b_\0E,wѸI՛u.>b©|XuZ'mwVs!N*5Or$@Za'L"?hNX+|/`E4wU" [\\ئU'.v4}nL027I2.Wu/[˃ EtAߥ@3C-swkӭrP8ix^i;beBB;}:}\tjq5"G0Mrɹ1Zi|ʁnYpC>$_J3Aj{i$4.x^fJA83㳒qfG#K۾4?w.c4t'Ґ_ J\\/̊׋Χ2dC"7Іzty)`I.TJ̞XBF/QM:i@쬧v-@Rt2p?se]bۄtf)P娅w)?Qa%gJ4$:{;?*ol+O9 >5ljꚽAiUh$;*<\tyV&cڑD}V& ;DM-pTe PFwgYRy5k۹\\Rir۽_IUjZo1`=Zh4\tu0<ޚ\095LwiIj{dB4~"E֜b+QLBV8dž[dLd\0,ټZ(\0lBM1KSH0/KnIxeK8[Q佅!b\0tP.IƉyyV`\tР& CIm[o.)SI`@Dl@M5fcW5!Fdix 6'wefm} MRzYSk~4W_dIµٶ)RǖĢۀBoCf.@jWߌCC6'RvIRX8=YR-'ꇀuXNj&E@Ss$?WPpmHG阜?vnWrv հ(wcTET\t=`aP^ΑW3u\\2h:5#\\H-2-fc;zWGR%!xj˰7Nh\\Dyޔ;Sƒ/S V-'MwWQ\\:Fo\\qzC"E2@'<B:s31MԚkZ`/h Rr rg?dk"&N\0˻Y4yD0BZTȎ `m:>lpV{x AcGH(7ML'Y&faWEE7"&w{kÅa\n3- ^hw Z.E0jn;'idaZ;jYMf[< !y\0KQG˳}^%̽Y䈗ڤeERE98T?+⺡uv\0CC^lWH0EY%q[~@E1iP\0C-2[Au w!/ cBeX\\*5e%7=A7Ic|PN^UlʼnЖj'kt@F0ii80l+,$E?s+8 v@ M|?RncZޭu4m5آhI%eƎSԜsf{c *;W͸R:?L/|^?m>}D5?\\holUcEnURYF6W=WY Z-Rx/ܯZl?@\\~P>*6!xf:~Gb2Ý湶L8۽I w@EP R&9s\\jY!lٖP[e~<5M?ZDT q\nYfj |_̪z EqPMӼZd.'`'?`NUP``\nae˛'XT\nc \0N_G(Tσ)7a2[fR|Y̙^͒~<v-{'}/$DY5"+Vi-E x\t\0T{NzJAmqL\0ƋD<NjД<i!܁,raN/C"CCbOA\\|1`=\nEt2$qz/jWqظW8t>gp0-F&jPx5?ȸ].xʣ*]G>3EDvxSXR0+"GkxX'!YwAYڵB."`iӁzs%]?#Ea}ŧ52t`$;XJ8A.\th.s?kkָjj83eYlkVY K+ǟ}.PݮT^/+VV{cb!T:x|֘4 ~xk]vEpl*htgq&jtRG6"y~r[rܯGTF7x֘Sч\\o,s]O\\'CZ@ܲ]G\th=Uioс.ab\\e]IX=$3#0;B\\ =@ߖpOXt!+k\\gls[W!{C x߈47e~r\0h<n?aAFfhweN`S`:{QJ.C)FۖDeD,&V]3h=[gt 0Y S@!_A=N}#yOjc\0$U^If\0ш\\J@{hW\t.zXf+$C$\\^\t '#+揻T7lO´|j RZzRy<B(@!?X 7Dﺸ5@\t쬤 7vg 6#\nohQg[pvNt7G!| k%idȀgl`F=m/Q:.va`@- 7n_DyٺkE{VJ%THAǓiqFr㙥?\to2vN iM>OV>G%]Hx"W\n[ys:cE|莏\0=_ ;{n2N.JL\\<:Jt<^pO]r5UF\nzmyAN!EfڻTPH*8|X^wb>8aBޡE,bM_cZ^2s1u7`K(O F`J'ZT\t8KaT)B3~ʓQ<б-1 RFXa0cGz\ta<,[69_: 9^VJ2z͍*s2dQkdZi)\n\n^M[B\n_G%o!nQ?sr?7-MS_5ddq1wDW|\ta\\Up|=I{q\0u7:?d.~jAy`>VUؖF4`H5PԾД*`f dO)fvR1ZݟL9K2jQTH^-jumMga[bTBp 7 D]"ɺl'xKC1l[\\#wg-EwN /p2pyO} ;q!vCBs\nG+|D:i/vPmn"N\\=~\nE}]~۽B,{g-S.Y4OkSwQ&U35<{%,\\Gi@o(\tԓ "ODGnd[Gc 3!W!InՆ\04tDtb]Qp+yٍͿ^\n=3?nK9jRCpC{<v.lKCkpRʘ)쐂BYc9N=W>f%.tKLn^E3@,6h` kJ9{4:a>7M.{|*f5T>24+^͒ZO ^oMJPae W vyF*Ɇ< Rt4E6 ݯb䩋Yl,) \nfy_"Yg~{<2e?TfbpMN wc ިKYw(ꡉeg6zň+íM yDlcָTZS-PgȄ\\u4ɔD[5zv:[;)__@¡$@|Ώ+4[p@x Tkc=3*TC,-*;~bɮx_[TLb;_Ӹ?@zre> 6NCRzLϣ̳+|NT,+!?U9r3@X=m`"B-mVۢ .'mϼXí̖7P=/W|M*!\0MB\t&=I#$/ vkŠ ߰l49?;/g}--nCt.6iLf!dI3Abi VH !0t,FjD)ЮVK]G{Z0f\0}j2,C'#!/?iҒ믞0Q~pLs+%E?kVvwFL`٦)}UρcdF1u/\t4ص/妧ˑ(Zl?anԂ=&`ٟ_~_f?E`*c;LH QԐ;˵А:L,pXy.-ueK5 )'{]GJd8'̦sשaF# E0IqoB\0yv(72@eg< \t\\fYK+\\ܒe{T-h]7^ӫ p2D"1pyG6Vl&EͲ5#_]3\n|\n9B!\t'n:fkũ,Vz@\n|qP~8CA WN9v1/0w NC tMU_*`vr@hW̜p:/.Z@lYTV,Hێ]( F~iԶ{ŸEaˆ'߅ع|p\\M ǰuer!7$[k=I(RƺVlC<ȗmf$.c_mc\0o^iHZx RXwdW1|c{~,g@~TJY}LqN{VM}Jp뺥=;-C Em;B"Pě5f`tZoFOtI۶^ixk*ruVJ/񊂒em\n{ =aJgM7\t[,HCLgs' NIl*E˺Ucvz ALS-/H21XSpD-]˛5h6Ya h?vڷkmĔcu7xr>!Z#-a^''?6?{&|LCNֲ\0̭x7~ocAFU_`t~5[ϗh5ecl`ޕ\\'  &VhzFr.X4x;ZԦJb-e:1n\0Rn!jr&s{54(Kl ~<'ׁҽ=K Q^ZJߵzJ'֍(,d8+LAډg+D$u=-.gmZa!^GXD*&TOM",Ur٥x6PŁbB=š;\n,^][Y+{eV|E+&7Xk ꌡ> rApߘp{ih X G'lX2Rt&?p\tG];OK[{@wP mۗS9,i]9BH)K3 <sqhՅ[u,=Y_14B]C|ߛ^7m9ot'TS»]_V"xCb0eVSʽ3GdrTou:"|c5rO0\0Y'DldZ}5Vʺ1zmSoЎ\0$P"VUvƊ> a/S0̜o+C}[=[/l|\t, g=cz/TBJmdžLn?WdFqi|ZOdxL59'S-\nJs&ben!!-m?>@Q6x֩^@)X91bv9]?\t$儫?#[LV T/x5bR&Ҷ ޫyg13괝@\\-\\IHhįDJF Jn,9FIJϼf6vZ|#C4l儣`Ń2Wc|/Oc)@{8ysG#:ԣ !yOə܀v٬[UA?{5c\\FA'j.Rf> =D>V=ݥh>?G^y{pȂe3.Xp76*\\iy5.8p3tZC|H8͇ ke.|?$]$Ak֣F߀k"rN&mUji'63WKGZ uB %/= ݦ?ₚώ#=$R.C+GL; \\AƇt0CJwuPP皩ag,#@p0(%O#qG, ,WfPh\nEfDxz5"^ ua{{☹sf[LF:\0,q~5\0ږ`T ZP_\0[{\tZҀ4VPbEʮQOSosmNvpЭv\\\\Ki|=!}Ub_J[\\p bM%o "Fg!^L1r(Mʴ]qHf\n47M9iGVv0TϵU{|XZU\\zHoi`|te<MR|=x G#)?k9P[\tNNY?uN3M(%_^)Y=WzV_}DQmJ?>QhXtVlT\\v{$sKjOR뮴nCd{mU$3i`\\dΧWB9\n@v, Bʼ=::6I(c-\0`ȥ\n[V>6-^ o?wi+EYZOs,ZY3<vF׾P(o6PI?lA6ODdAl <8YfFH0PSMFFDAdG.zWcUC-$-WHɃol?jsa0XjlJt}ra_m@nϬOB|@5ħ9^ݕӾ8!LHS\0bz)F&/ P\\US-YWR%.n{ rglj\n0@F^4-EfIPmXOW1F:} {lљ&sEaxQG[\\vt~2![\no}aGJ4\n0'pCCS3N1&D×Ȅ*ed5ȟQ37*'IFYsEOI"Ӻ@z P*k!H9u3H&.>#?by/8Ic /k/V4]u#:UWC؅"!"c= ?\0ؓ1uK U//b'CCGČĨs`'d ZzN\no7\ttKWz~lu7D-`'{%(T sDsܕkJH]K2A(8\n ȲESr;IR!=xMT9}%)ԯ()(QVI,dޚ) "،~P>fS'ɔw>Ml,׻D r eϓNP\tuksvxF  ȣL9\n&-)e6XLWrgURTHDaxul1'-ʵ4i$Mxl/{EXZApHTy<͕k64vE~r9 iٌDLR#⤗޻6?q͗X'TF>zU_)0t8 V:vhSBϗT)"8a:jS >:T.fH4gS55V7wˣyhCpa.2j\0密@lj?4Mq0-_1}گZ\tA cp´gexP@o$<x_ҞL'>\0S=zwWA_ |Sɳ;0@z_z5' {M< UI>cݸ}ɴAbT9rr[Pi'V9;H!d%SE7NiZP: pNg&/J݄YI+@oX3ITY5X~8}(0&vx?R4JP3ڕh~ͼ(whn w/aHU\\`(T6 >$=Ba=\tvSR@,!m?%Mc@zK^tк{7nk\tp95\0󳰀U$i" c.ׂdX󄌘 ns}|}c7{NBmq'Sc [H.B2$7Li'&4Y., l$2^z,\tf IrTw95S(j,!\\S,t.|V=4ˈϪ1̝\0e+.ŀV)\0RR`YiG ,.%~4;U$oQ40e)(`wIJ'L]uiWH4`1g\nO]AS(yk tPEd {Wfv\t,!D^pT~_7 $ zfK3FkAf˳LPOз3L |^IȇT{@ U#^1?HϷ}ڭ%{):A0$@;Bg18\\Zش u mw92.΋n;K4 x5RDmRATp޲@HS hOL#}OYN :/l3v9[jj>~{ݞUyS5Sm\nIҊ\t١湭\\UU2Q^2Yyp |27Mٌa\tWނa4p@yah\n~Fؾe`85[R:hbEE^`LvcBg~6bf~Iȃ.f݊|z2Q@hh_*\0S(+!\0;z4`gh=\t)S@W),Vm):GZd!qWT+וD/B:W\\|%f﯄x&\t|GV2ӕUKvSȒQaPpYswje*XaANAISAH[F`ɜ\tz$Xp' FVYVD+|$4k i=8}j%QbZXssƑ伸^LI:'! H,jه[%"yb CE]@bC>3h< +s$-o7]҅f,NJ찏q:oh~Y%\n~$p*)m;$l\\BE->) EMVuk( 6iq)D~*n\0r#o=QdhyVHO̙ROQ^r'\n N >q\ttf!hwβAGjhԡg_zXf]3SF-OVs-%1-c_\nZ-wF(W\n01?DAO_t%~^0"+<|A4L \nŪ:*iʌWto{*0({v*®_01\0.m]Lz(;-S)qМ7·fhyE*^;=OrO-`r뒹h>mKYBtdiG-!,ŲqdHEVb`'g{B@Xgo-Ljnz[oa&/')Ҫg?NxIBJE{P\022 6t\twO>9{rv|8RbNnE39l? [ l-2vwi^J3r0TX!b޺@Zt4\\<1wBu=.kYg]\tay0y~qhVƦf8~27'NXkED:1lBs\t&]zdȩr//W> igfk됎%pKrIjpMy0o|])|'9}QwF7,)1m~$rl[pۙar`t>ӹA%UX(+k'cat7vX[M\\@_7$HDi/{Љ`vP1f'`lD\0hCBmb3f#D;a/Oν ܺ9y\\(03٘D9rB-5@'c-=ͼ -'Vڂb6qNM\\%Cx/62/y*ˈ<\\ԗWl@ahXKNX}7X'!_z\\wTa4IFS_\t;ԠpcsZJ.ye$zZ+Z= ۻmO\n3/#0fšM{^Ot d؝bE?O?~@z+%jM7\tnIދh{_n<6Cx衦;j|lM0\0\nJ\t4v8 H_*bE$xUMAKrR0ꐠ;A!RV?y 46FvaEd_Pmjjۢc̸o3c,McnhF1<-F\\nJTNŚs9|#6I:o4++L<*kz+ZpߠOfB HtpsݦK3T|$͸ܝ*#Ir+nv|JwIbzx3VVfm9-wۺD\n\0:L=*J\0ŧL@.\tna»Pr%%8ͳ!]Lq#gne2"5$@WpyJե\\t|{Vh8}(->.&ҋOϰ}kg|5\0.1k _dҥӺe|=`,_J{U9=/|1L##ތ+BΈMu5g5&F.}6a_[!E4Z XfAˡiNQvw\n-eofnXxbSNb]RӬCWg`s^sW+̿+H1D\n%LabiR,f趼1ӺN^Ef$yXx3Fx*}\0\\J[O϶iiD R(0aFիVe< +5\\QH[GPb\0\t8%4Lc&iAiO3YsW:E$bsIIZBF,t~cu) TLF+r A\0*bW=fcWLAZ_r pCI\tr=l%h /;A71{ķȏnk?Ga 9mnBį~BJAM<7krVLE/7>6Ҽ\t&Ou ,] MUTDR6q5B:u}\\H:>`f3 I*E-77[[ "@\\X/@PœY2EQ**5X}e'G̓hSn9_\\C٠}k#q} PuB,]])HݗZy_h{>c\\b7ztgý2Crʥ;X̮3%߬mlqH$Lp1G~tm;KNN@wgbR"bQ{DV\020bq<:uj.\t Q7we:ÿ)2ңFȝ9JF?"FNPMeqל\\#*\tÑƎ7~N㟀W.QГ΂BF|KS˽.SڵzW%Z* d7(0l؂b\\jXKs-Ḟ)U' EMVG#q1zOFC5_,V }J/Q1")ќ}$\t%=]̀WfCg2JZp0֨1&@vXp\nH[\npAQ3d3VyNSn_蘢󠤗l# 8L|0q@\nSqEL\tER`\nFez@ip+԰z3&T]q HeA%llVT+sK[C9B3{=j&MF}4n: V3PH=L8@y=g|>a=d!+,fv aUڠ^R^˱FziƥԉM44}7I={Kk|drw_\\EVNju\t5J8ُjKX=?v4׷{^4 lu#13l¬!w%D|~x-Dl3pD˂,*#XXuC I)\t^n.eP4KVlq@xӓ ZϛCˀwxE\n^vrf @Z5NZn&tI_GcU[j"ڲ1<~>7%PFUhS5>;1&bϢJRu%4_ug.—#? ౸U >{];i˴t{J,h:xcޚtwIաL!)Č@iUJIx,ƢdJgd oW E}lW^E P$fvFF3 [X[svP6!k3U.'n9-"Ty`+Hiz@=Ij:D͠*% T3]~8)=YoDbPfu\0j Em1ZТo0)(-ѽH:|idl`^:H=rI Q~Α-?^ϖ~{_3ku(l .4`j"B=Y*v-rk#[W:E skn߯cee QJ&\nfg+luC^[\\k!={ٜd4+Mωk\0CpFdtTd Va\t6޻9ʠK(`3ᘪ0 ^lu-ÿG&%4>WK>"όKbΕHZahk}e!f.kta=?]PTAA^)_:l O\nVk =CvF"K90XH`rҚp`)ͨC"Phd'ډI4R <rpބQ.I* Pf*p,>ܦA*_43FTd|N+CDAq}t(kx E-^bګpBvӼ߫I\0\t5]?K6g)17OIuV/zکL ugBrYjx"VQ69ZX"1kW@NT1#mr\\ם4ΦqA"I>VZ/3JHͥ'^`Wm4}?޿llh>!`p6cD;/B)hF@~Y0`T]\\:d=(?-񂖻 JTo~%t׬~:='-nTPK9-Su0:Ƽc-FoqM$KFc(9(axr}8+%+Z?[i +5l)#DrxTB ^n삦'UDnhc8@&7tpllSl^O/NF$|%W\\fj1DGCTx'w!DJjPptM:j̅}et `y PC/#E;dp߇>.}.ЧBީZ5 nĂOagC7nKj[v\nQ29tz?}L҃d̐ å\\n\tх__& `pGa+OqAP{8EG؄2Ъ쪶|\0%+h1vE΅>t.IS#¢\nU;OzrW-\tkz䖒t](ӷ8|3\0U ?\n'3|j;} e aYQmᇤ"bXfJk0H\t\0iQcO\\qS sa0m ;:aeEm\ta6PZB]K%\0zEc H"'̟^;ذnUUM.p\\;;{HL=}mVt+g5pϡ:\0<ǧ>WWUɥ}˜WTq.8`jb\n=1U\t0hGB(򢺔uwv*Mf$rBWf߁\tq\08/ǫE|e#sT9%!\0QďF)г_6>ZG%˗\0{.Aga(0NxgsƆVT=eh$ޫ*5:+eKHךi5U+ Ԧ^ϸ),9%+-#rU@G/1,dyq4YFy<⍩WtB\\N0GhP`R*EY/NLj+IDҾgm/;t z ~G$4ˉ:R+r\t&ÅVaK xn6=$Gڶ|P(}x9Z_hEx52ސl\nZ\0}[7S($T{$g'*6=!a^9E%FW;[|ٺ(4X+)=\tn'J'Yr`~Nc\\ylEs')}2Sz\t9֚i30sNwI|%M[wLB.QK2dٕ%JEuK%\0\nh0ӕ8-eWX\\eLO!4ܒXRtw<0…= 23:ȾT)I\0RMEf'Ru$rpP!@<cߦ8?2gU9PɁ&2ﴀ;GҀB.+D>ѳVW.-u{n\n'\0\tCpB "j+Xk:TZT?6JR-\ni3sU\0O+2\\+ƬsZ={v<0݊Iu垅'qLO-1gM̤TȞ^6tp3Ѐm~ɭPYAQpV=Eq DjM"0ᕋg/|Ývȓ\tLGEZLX~A{P鉤!{]v-)[բ@Π\nd& #gq"]`rIN}vg8@#;kOM%7]Ta>rkue)|9ҼK]wɲ-dQ-%O{iRu@!NP%j˄&PfC,XYüUe}@M@/XFí;ڏ;v^zp\tߗ^ZBv_ވuR$@j,J<:+WTC`NeYO#|eG/T}AM}%(Ёeֲ>?\\dpx W.D5#\\r.𸈵II)^\\ˊxN5z4s.%U칪G#Ā/!~0M\nR:ds]Oc:bN)X Xa\nbے7EXd&/z4!]ϭѬBV zzWFtkyVoo{+xKaLp.:WyaQSoR#x 6Mk@~e`Jō)tu EsezGY`s4N nBf`0?3;2;cq,DoEf']չEE\n}4ZvL:6\0$`F؉TLyPF 0jxu&\n\0@u}5VIG6*-O(زlGaBx7Ɠ(X0Xyo*E&?/ܗwtj$7+ц p&ԤhΜ$USO؁>Ix5R.; $nmAB$#.,CZV0Tć|- ޷ AM3 J3h=Q)D6֑z[>{\t}qbWeE?SL\t̩%іY< myq[lB^`PIs䳑%W > 0D32~k=>-cH{moJaÆ)hv#Հ ¤.J&G8\\t:as #%w)lbII|n%P}0?giu1캓?JT$\0׻:}Z SpY6ғ5XgK}noP?{a/,֘ПM,h"ye1qM?v/q[%0󊤀ʈMh@[ D4~[%Ў~F'u+Sq)x=.֤9\t#]\\o7J\\,^]@Nm 듹cu!z)ĹX@c VC"^์P\tECñ^V":Pa. Ⱥ"ۛܠeϤJoIkOC8IK;+PBg~,.I녣W(e )_x0j\0ڱ~w/n'XBQWNUa8/ݒ2/oV9o|)ӈ,gΫ>2:8>Q'>!6^zRp'Y0g ,<^PG"E?REnjLŸ? ⹈?p0\tkqirXxY+WO^?8+S\\,k"2ވe$0ʧ/ya0Q}</e&YyA.7采[ߑGR{'/Sم\nTxʦǸ!p'ߠC]>9-LbjLy6MпA/ytMGmcmbƜFb\08x"jଫhOn+l/bC XO2BքpccCO\t?zmЂ t|L›l{>92j~/CK`8כolVg6G6n|&,^ASx`P(s^hdIBojP!3Z!6B/ުl0E=fW hS$f=%Ÿ32P(pQU5iﺩVʍ8X f,q+2fOPȵ:2du$h?01TUifLMg5|>uI\0#{A'.;^̸m_TھMXB"4|&1Vor2ܸb\nύzهbvm1\03uףd}a`>s @Yc#ΡRb—F7l) 5'*'8#<{n3oF8aW/ѦH|o# ($'#[\nXO.7!j!g,bӞS@cYK9=*J'{*Nʄ(Yl+ךAlܟXo~{%O($(pjj\0wD/Zn|0o9Q4V2':@Ѹ y׮hHf?>*t3{_{$V%$S>sY%v]q5#'CGv8-H\nqymV\\Z>ƒ ù?yeYk6)!RihX|!qt#tl^A%|]0^GtP_vZ%)֮N|KH\0D0WESrcMHCU/ݭ |\tL9w V;:;1Пb}4)\nSʱ#lEgxqŞbJ6+31-ͭd|}"CGikw)29Gqe8DT#O7dOO5 ioXDexJI9*/gbW+Vx_4~2Z2O΄%@ANAW>V??V5ۣecG(! !!QP\tGǂu5IprIJو#u׋7@ ,0AĜPz")?܄b5{r-4MmRȧ%'>]4xejhs*oD2©6ޣpl_z=6gbSÉZ"ÇT/Ң/Wla֓HKU2FZ]嶀mE4\\%ulidzM\\.w@L8knלo xi$Y{ݎN+9/Z\n[+FBN1Ω@#~-+*x+8!_xB~$14 ~=/ 8%c[$qIGp#S(ࠖƜ^U!\0'qr#Uܦ.i:D^}8śMYj$;a7 +ͥdt lcSl@F~敪VB졗A\0z<ޏnw*:yc ~qXP#ḏ]}u b%+CKF2sZ~uEd6ZlAOnLWezabbts pؠtA詭d{ΛhAeھ&Z%[qlST&}Z0%?Xu<^݇KǸڷk):H=xgH n?07|'FoiX9,3gKAv/l/8i{s٢' vFkQ"2Xx=R _I)aAaqpQ\nȲl>0]lUf`PV>F|$\n-qIS  Sh.{{S9".xLlW8FQ_+y+]hVKXEc&;=4]\0J/v\t> rnSZ9\0\n1`P&2G ?cI(&͚e] P\0jUk"He{.nJ.m3?%'}-Lް]"rĉ~5~ِAO+RM]zeL 6:=M1M*a褭5z;~&yO[jr}e^p2(rM HA,Ai rPB9p`t^F>$j{KxHjy1p9\t4Vė*s>2rܠ͐[\n\0\n*B7J\0l2(ƙ((kmg&k9jN'A%:0~ώEе'|ʕcyU67d&O ^f3ȿ:_I[PE3PFO3%Qtf'j6Sp<Ԁpp!Y̼1;;Fdyr_k 8#BЌ߹9V\tR]ȎzefIT(pC wuYHxN)-l_Y}刽a\nJ5&>FDV'g?CgE_>w0#p6V.9$Cjr۰8\0N$u~ɢ.6.€ R|y1&Juta=fԡʱel`J}UZ2%mF 1Cn41r{$\\Y@%3 Au`mnagCO=ז9CBu^8-DV\0 ^xdx3N4> &jy E(-"o"Z.Dc|op1n6&[Ty#['{06#LqkNOlRJj8%2憆7#~.>ALχW:\\JD;oyt,Dƙw{p?6uvx+KZᖀAWbYo6`6̠y͖xҖeřڔ>T^;\0i!4T[wC P3J>\nx;"\t`N}HiS'h;R^e2ĎY+7צ h臘߁n-MyO]n2_yBCbi蝂"'kdIOE!K733A@Y,Os$:~0g2HyCjOEg:Q|\\Wr@S;S~4̉ZJ[ԾSf@}\tbg@+GxqQ\\^d\nk3n{&yrtlfYM@,9~E hOQJ^v\n)5Z3o}x XA;0]:6Y\tsCM=c\nE =r&/z_u;ʅԀ\tiGuV1-/IR]pߢvi\09FAґ\0lc"0.Rx4yΩqt4yb&×1ev>4tpM["tL\tT>I'|4%bD \\=t3/ !?f=dGҍԲ{s\0G\t}ɇ)=J.(I=;a2_bo@4ʋߏn5Fܬh-L"\t\\r~D?I^u\\>I4ْoErTieO߮SZdœ9:vNۻS&xh_3rlby8%c@Ev z >0.yەT78B2fמSX Ęp eG6u膘656r 2 u=>2p@T@$pXEсyL[\0V41lF\n<,2;a̛{ ?#9Jpu+nI~D[D&F2Έ2?sZ,ZrIjwX;UK(՜T%'Sa|\n1RoQYO9\ti 80Ɖ^X&ˢL[L\t B(^\\W=M7*\n* N~2oj+h3tTMze@n4ɑY1X>5ͧ3@`*Ȟ9҇Ђx^reYQ7dq{F h\t4|b\\[UAGtO;\0* hF/6X~'I>b0s\0M9/uhE\nS ؜#f)dn(AhE)g{Z|C<ؙlaEx(ف \\1;YEA`VY$eMCݫݨ}\n8^qŪnO,̽*Dm{CA>.AzHPQ wO9 L2\0z"Rb\t#2!=׸]~z"Ity?׈GX&$9,_2yߒ$@qR43 #zyZ#sPKa&7]M8+ǝ@hnwt0Y5@ۼC?@gqk {K3WlvJq&uEo_o\\(t1i,bXi:j׈{x;l^ OJ Fq{=!MD{Dr+``q}ngOFƩ-OP\nܗS3B)9"žiH/C{4u#j(:>8#3a`Plyb /BeE goiQe\twBWKLi HE//\nܳkgOreHcāv)j&\tmWEU }iٱLh#qoV bmN+_~@/UnvIFXϜ'|n#QŴa\\fUS'IO1gSC#~QXe [wg@f#LwzcEj 5"VYfمMUuv6 ;_(3炼Rp|sSjmvi3`閆b;.ā߼iFϗ7t?M6;0U\t\nYspCt4n/\nl!]h?b0JC7^05n`ɧUV\\(aϠ(ISb'>ؠ;&?PU|Sua[yv򽽗ztm,82=eK7p6YLrˢ۴aFE052e|oqGb-'x{,+i?҆W1>iJtS/yXcMU'@Пz4pt1-G)Gڏ'[.u۲j-6=H_48$?"ݵǜλr`nNIJ FO)ȧD,-QUYT 4&'b|]eND}Wf:iFu'kY$s+KA4ʹxn/g}pHmWFCtyΌ@j6»$u?D![)3a=vk:Yeat` 29\njDLA\tW3-Ym:8b;KiTOۄpkVq1#\t\tGw&rLR3Rc GeDPoR\tk{RqS|'ت=kfqE5[8S\\X9\0$<xuU7\tv?֡Ѧ/Ŏ kPu,ƛ~<~o"D1O=bK輻!IKboV)Ihp.|:`&wA=Ny$^g}2׋,{! 9XתYT򯑈lQZ21+AIHABTUg}*/EiY|a |7sN%lJ^Ie)(嵖0]t2BGF2z1{|ڽ2/%e₫rOM4)FJqkPpŒL;?r]](lj\\ڶPSԆ7QN׎l㩆4/{- E/8ݨw銉]|"qZf^f_9-؃F)cMa(@v S>(oWQ⊐[v%$|d+QYaduu"vN \nP{"4/sNyQGKiŞI'\\lh˴#+f"9 3[m-T?P }U,:-ؚtRpnH}QX_8j/a-qe4;^XT3i,U3Ϸu[T@g\\ؓa@)Hɔ+PՙH2nې\nhO!kS{6WGV2h?T+,ʬ4썳l$=KPߢ|ODo+3cOOK9,}Qׁ#(P?B%a3u3BnB5n\tGwA9mvЉbxe m|a\0Y!({(s7kHQܛu2%1EQcW8WHc *$ j$0/T2(\nATW9i*PajI $bX\\u|Cw:U! R_5\tЯ)q%Cx6%Nߏ˟W7kaZT5l;gRȝǻظAJo|_o>7sC6ڂ[6Y{gO5h /;.V(e#BC4u@Nu߰w-wj*ØT0żuP6_1wA_9(V)UAST]w$`A\0Q-]wdx6ws@q DW^ϐtYn r< 0yי|WuhHYۋ h\0sGkcTHP7&ԉrf_;*w9eu܈\0b +EuF$iKS.Ќmgچf$=;MLRV0}F6^fNBK:i5֦Y-(.36e"Frv AGػq%\0SVʖ#xO.Ȯxs7čSyuuw$xm\\5tdbZ_b-]w/]J`.S?9xdiD>GМ-obaCy\0KgIPrrg DzJ@}՜hk"$@i%@w/sL1=H?V-\08%o'z B!?ف {hre3*`HںLfQDQͣX,(^YVoFgo~1Gh Leʶc~R'J9էa\t4~PK({"iv?G[lmS7khSP$!YyV2~v[ qh.,ă(4b=8C$@鲍&Xndtl.Yb0QN*U,'=AŰ`USIK-ևCӄAhyk4p\n0 }7'Hbr":RkXBs>0UMl^c}ۤE{G'<hBT`\\ja9cXB\0Rц!X_Ooؓ"]A/U[XׯA{G47mZ"VG?}' s> \\bE4\0|%?pJ|ǘe#Ї7%cLR`=L-Ml2~Β9]O?8/^S*Ij\te I`:]58"QF9j'&B=Q775e;6sa|>* tAO$RݖŠ3>z쟷 ۍ=JpuBr)FY<|h)\tůiKj q&l~:D{_ibcцSn9'ZpfB|K :6mhux=\0Ѻ]W_Ԕ)k5G2䓐M`EU;ݫmqs_z)@ˌ|T{I4mjGS_)oxt$"͛l0,qB&p)T B3p\n&Vҏ 5l\n.ReRӜ|8[#($^^\0"sK\n=bzT2og8o^8\nή$4WɔS88l4HZ,?vs-܌矺hE2ٚsu,~˼T1YˮnDŽxM RW|+<R}wv.$b8[/NtD\\qͱ['a'0*F91N09\n!mꄆ^a v^PKO2X\nFV, e')B8XCI6؂.1N$˕OƖr1ҁr&Wh$)PW2=8u% ȏx ϛM2V+\01&%22?o'K1/_o~@P7V(Mty:TYfAT%f!B$ѕ=cAi$4nH LG7.T3DL}1NZypXkh%,̕V:_uz~:۰U"-0-*4ݽ12p/|H "ȲD٫ҤE$/\\"΂y)<~{XD)6\\ \tÐvڕZ&L, 4} {D@œѼjA٘=e#]1OӬǠ~ Li nZ>~< giN^4fmaQFZC}m)#]Eҿ?2h oCv[?== XsFqKgZmBEߞ(2ks9`~gCBSGմ9:lB4ĻT@GWF26(2ߜC?L\0#1}C2+O\0?rCT0x0ӎ͐3jzlDuEAixo^{w2_\nY!hU8"(t<imz [ϓy *'TE'A|7AZ|\n5 ^XGHK=šfJ p!͞0qG>3*nΚ!0h8yrL s'X4X['\\u|?'D2 Šʨh1>i~R4vFMh!5{S'H7F+\t\0韂C5vEUL'h[kΒ\0;̗W w=\0*`u(>@!>٘Wp'{%LYSQPC--YqY g|v%]f^x6˾?[t.9Cq B[X2z&7\n}݇Se Qa JNֶY=!6;AU&jAm-XB.2hJS4Ǥbyzl/ׁO\tzӒdwfF{(\nYBo+!C%0垄,XZ\tha:7``9!7XJuK o/&$Ց"⊜`\nHF5X_aA14a⋱Uښ_LX\\bR ,_ؔzP3VQhE^pF\n杶uʱ5!| XWܸNԯ߯#d/ϛ)4L`d2X3LgU+M?SʊoRYޟUХcn!]`TDySI4"f'ؼa\0{RA8 r.B8,_"eٲ@#C˓5'ARPE<))%A͜`\0P,W99i=x͑B۽ VKfWpiaZ+Y׊*wX3 ]15*He?Cm;yPo|epӨnEqA!fd]t\\-ma/ͦ\\ZCT$nبc{݃OqoaDkl<\0DĴ!2p3T~;R4`  dt-P-e$^iՌЎI$-'Yˬzn[o\nHy/\nz2aM <7=t>v7@rr(w֔rʬQXB4c2= DmP*^gmAcwPXͭBfr;XI09Zw]XX+")x:0sts~a? |>f'boֿ#|>>χ{?{O}e>~sqn~A{|;{WzͿ[P=zK~֟ߗחzX\0s#67tw&\twީ\\kю0wyj齪Qȱ^!@SMZf"+E6zBH0cW:EƵ"n*5.Sxja/In$XGwa!dD_5qX||+O(L4Qvƍk%n?=5RfKv 1LfHkzSHWJO-N&`g|*' [ۑ!Z@xI#m'/SrdQ1?M>5g#V!. *ڀH%^VAJ\04Ĭgy\n}0]σw[/Q0uT-m9%U+aH H27o}3 <\0?(Kr;<%4P"9.Ḵ ӤtfOt|ɠAq,q%}X$\0eV&̘fjMM{\\wζC9@<\\m37K3lg2E|Jj3t;S9儏My|GVkA~;1ml 4>{.VbNN2 k_<-T=Kʤ; v?F4qYPjem:gmnc%"蟄lf7)YLfQqwC\0PB^0-T8\\\nA=j_%B{0E*`XxmdVGSF!{A. c^c'ߪ]?Xu|$llْ򒡎ӲÿB͎AQ'>ۑ-O\tzk1khAm3o 3S'ܗZP]䔾f%<\0ǑsFg?;KS%ؐfSF1,l8; |YfLu~uw:QV̼WXKK2*cvu;[aP:aBm; `Vl\tښyU#y"${8)QI #U!QUjlE\n\\ʄ6Pm[7UO٪I c[33`9^ד2}2^I9Iܚɶ]q(=5\nٕvGNM^"\0\n7!i\0klOxn;Dx6Q\t^,e#2A0LqFbզ[jR)t~C>MNbnpjuȮ˟[m=e%D!L^/\ty>cYWAi!@-W< NiϰyK*(}pC2]Uץt;"y,")g~{!Ut\\X)UČ#;5/ƒ<͵N\\.hF&Zw|͏ DONtb$pk_7T;PO&K[.-ѱKė4"l΅NlPmQ6D rr[ F-J0Nӓ5\0g+:آ \\3mC" \tj]);q۹qE-duݐyb\0)bΦvWB ;IT|MJ:e\0:>-i'53PZ͙,.]Tv!0 ċ7c},!Ph'eUAZ#]X~k):K%0B%& ?AV&!#Y̬}2by=5ߔ{e\06o\\rD(M5{}{"ס\tr|'u&n|H쉗}"e~o"g^H͘,\\o\t3H85*z> ^2*Ed-Lڑ1JJ +1tɆ;b"=<)M w=KG4T\0tkWQMpP=aD\\V8Vȱw"}te#^2LHMYr:#%+ L\t!>N98W \\CKV1WEd'~ab_=BZfzaJfa/XQJ&eGPN}\t].h{+=$t4hϓS s~9V* m59I\0Y²qreF~@C!j|AυWDOz/qbbZnΝ%^l Ԭ[f,4W;a^航-{WB>8qt 7a:uXtZon!vJRo.gvoڢmwe~e#8M{y{`G&7|sV,y^pUso}n]cK͕%yO*H@\n>z @\nl)O)"rR^\\JN3u4"mC\\_o$/eu\0]4Uz|h ): ۱<ޗ\tG1!|2CI/yE>+q"Cҫ< a[~ O,_nPk~@;M1{g!6ZɱTm.^]߬T hG&>Ӷ8\n8:]f\n [+^"&-'s,L*%Ip.NÖ->R }歅FAbҰqY]!Y@%5+qkc4mfʜVɑra0 P(2elK΁&ße]Ae@i8y>LQic>5SaֽSp'?Yd-U.~\n&7q@2RBsiSɗڽ%rܩW'~s-VJO{>=h%GM!k{%fүpmϫ' eنOp\t٢K\t ȴ`Vv@zNP~oR<)3d^fP5Φ,$o@vK9ߨ$U\0_)oޘ0xH0?!2fwS-Vy)v \0-\\e ;-gܚe`n  z\n江Of@@\t&8,U{pe+L~\tfƨYO2m%:$P IDWjH]3reKgG/|t¡,\0z?"͇9/Id@(\nxNHp:/)1I WT2"0&ɷ|fޔx~TVhBX֌9,kO-2fd{S2ˋRx--̑>j=hZCƬAF8 WA;f\0I]<(r.#E2٣zN?U-X"_uwW'`0r_0aSܱ$Ƹi Qo ؚwꤽbS7_y:)iG|V`L+$ b\twii9gR%F0R*ROpTRoХĈ\\#_=\\Uo4TyKI;87B0M˂Sr^w=:g?ֆ^A\n"\\hUҏBzF$c~EbbI'{ XBs[42wQ~cwԖkj$^꒡61*ZAn\06?:\\9RBSQ~K%VTl(f5_;!JχMiv@ dYY^o\nfp\tnKTyPWsExu, <`{JE_) 3N=/\nhJBkO$g?h6Jk|lըmC33'5u~%.2[^nlG'Y4DQµ|c ԙ2S!]E@Fp2gX}[*󡀽*\tWv3V$w6?PfPFV- K $s_Z2:wV=.|dɭx9\t] >rbW%jo6\\C=":[%Y#F4@swA~=X?{MmHO\n~=DL݄\\fSr\0}1q&#V󈋏49٥6Ab:ז5H \nKsc-I\0`~q>`a(bscpH>t:c'G;"H]}( &I:XȡhIƀpz ,^b̀1`XS)I`!kEY{hY>W3mЂs)G@)?& ,2%:':țrhԈ汒Gfy25͒ H}exLK߷^<*l>?wX,[bLdkEpքX.o\0>`< U\t(iSYWȊ2yHkħrXYD{\\޷C&u/T$pﺋ ϗ͞~侵M> {qo8\\)iU_jԻ[ўC6zu,%Gcv~WtdG2usxtqyJ<T瓈c)-X٪|2._uJ4"ǍFŗ!Fo;<[{?{H:9pjH=TyFvEY5G(l[8!0ܴNIj]ͮ-B{E-o"j2|\\GLuA@[fy}?wiN8f-$$0+F݌I81cD|Pnx‚։y7y/&/4@;7YV<(&\t_a!]ձOVI2Fc\0YhӞ<}鯵J{s>We i7o-ut`ϷR]@@(azg%{rHdzFܦhښl$F,prwZ)2+v\n.t̴<o.?bSU7]¯`:"!l<c/\nuw_ikt:) -2㈥ (_AfE=\\ݬ9)^=޳>VI.qa"">bZZIkC{YX$M\nH} 4l_yvښ]\tP)֥F O1EhhcRq! A89wQp'M*yQKlE'Fu6_GZ>Z\n=检<#A5rc2=-Un)xxMif[HK=B-'mŏW1IkQ+ze 1Wv?>s3vY,rl7W4,Rq.pbO ר2aLڂ-@;@wRs\0D ^ΈSVz\t!o<ʜXmqE̘X5cr/FB:~?,KE4Ku-S0F=}e)8`EbT`G cu"2丧o^֢)ro_7`s1zJNWHx5$,L\n=fMd51O_ppᯇx)%u|^s&w1Tw {w8PwY{jἧ&h%ZN~wUz'/glEffIum,W%5*ZgVIZ(2XGp\tnX6;NXR VZP3OBL6w-\t {5_Y8p6 \n3zy232[mn0t ,"8E`J..݂W4Teya'<6LΔQ\n[>ݨa\01ngbHxS=Acs{ A\nP0*gwAHHWf,wOGUA `s5=1t" iV_2{/÷2p`1δT^id%5\0~1l[^%iNմ9IM3$~ScbZ%Lj~XO]Ac6^p\toBvصJ;\t𮊰FMi9òuZ^F:эbWc&;ϋ&Xk*UB`vseu Zz>7DF02\0ss4+2UdxHܢŝ@7&\0DرN~AgfվM7)[>\tAq'IrnhR9v\0T/ɪx w"yhk=htrևa!U"M!&LQp&q70K%m,9cxsmga@8̗ȨnXO=Z5nC2)Y%gXalwNK4\0 Ę,41 Uʛםǜ?>Rw3mzҽb\0L͢ԷIXW7(\\EB $Qޕ/#FE"`ߕ#({d٤WIqNNgn|iTǦX{4gbP``nF=2/#GIM4ɤ+ !K^ժWSAdܝ;C\nn#Lt;nZaXD3rUg' /F fm?yv-\\Ed.vbYɆ+ثrУ+`",f]͒Ջav=|o!0.Ʊ6v8`V2LwPa3H}Sk8 509y 6pJWX_HV6zC2Jf< zGT=}t>D)\t%Hu6tfIH݃")iTJ" \\6ĶǖȅUSWm` Ldr^vL_|Ģ#pS7+26d6Wҡ/Gu7/ i|oQwl0\\wQs?O6߿}‚B֣(fxx@"[h;ۖ3} W#5'^mߦ-\n+0\n%&W)e/xgbj˂YI ǶFlۊÍ)]3Y= a: maghAy݋;5[{;z+!2*@6s0@u^6OS*s0!3,OI]\0:'WOJ^ټ,/mE c8~g$\0zj(z=[\0":F:5w=J3$$kcP?BVL`lL0N=v㝡^!vߌ>ǫa@|Ak1rklݭ$t +$ǁTb8/$W;`f>Y2՘c$?kۮgqw. |\n鄖ϰ7{K)t8K=U Ht*f|!~lWb$sh#'. . o/wAnW=~oWER|\tBlx;ӺgAitf|5*%Snykc&ŕ12@ɹD? D-@i9BЉ>'s\nֱO5 E)hxc-eߕՅǑ\0sOgy$BfC% aX?L/F)Ȱ*5L En9 LB|HNݕzt17h9iD2'øTz20#@S%f Q5ٱs"FĤP51"R Ds/^Fb@2v|oIOjB!!0[Y*6k_eժ(HB4Mx!L1Qnl,q !)=(&U"[-Qnt^^8ԵP1ԙ-ܻm+z!$AOr%y_q]sʉݺ:Hk1W1jn\nF抓IN/R\0έQz7(f+}۩"廟B1y\\ʒN1qr1 `|NZ^ޏ:G)ls/K\tFAWq컥@u`0\0;cnd}0<6k_FyI~[Iw c%1hwT3+hβ0:ZҎ"֏"]\nGO]yWpf|ϼ,L'䴳C_E*V ,T6dP*/,ރ\\FY3â'0/TX]./V8#A~CwEa7lqAxޣNB-8^.]|G5 \nD~(}ww.*fN )XGmھX$b\\?-^Vծ$\n|\t3~{ZL|nB1pox AdE0߾k;Ơ.ct:;VɅ|"e+@;vO+%QjH)0afs-VF"ky{\n#(rRtDgIV"; a斩WtM$u'CrF, n;{z7CaOJ#4_,\\W(C⒵;XV;r=׆Fѿ"\nR~\n9Mfl4G(=\t\\kɌz:s2$8|!YG͐Xd1`DZB"QȚˠ?V&gh^,z\tMɟv+|%4nrb\tne\n{P˿Mo/S|̪I+i\tCmro2m 8ՌP^oeS }[Da1e7sS_3keA㕾ZNwwǴ= AaV\nV E&VOֵoQCr)Œ;Ѳ/WGef.;zbl!gCϪj <}Z}uh*meU[#̽r\\|73Q$I f0\n'XS`<uh _Q6-DF S+<"-!J2J)|Sb:`{?;͖mB Scψ*MX? eYkk]8s4E\n(ks֗ΣUv6_&sȏUvNHi >S6\0~Fb*sxt}mQi rPCΜTq94uh+'P4Z//c~@\\%oI\0 UC<{nOذH7Qd4Z~ǩzKrL܀cȤܠuEcÇ8YJ\0,A1-PcE=Y(V/~WY?(B*9aYadtUD/6]:HX Z6,5 $yR$)YU:ݣnMI4o\0GNP>Q_RaΨdG3ɯPkZ#-1cw\t3=7 ]\t"Qʯ3;y\0/gk\\6 }κvn~zWeSB,'Sg=uO혅O!Z+L^HzϹ^O!Yx7{x^c,8PZc1g nC%y_|5F7L zA+tBdhSt"/@9bavҗh_w*r8T(NtI4AfXCBŤI}`W#%\nϟ\\W(:IhX,28ˈ1\0mp Ńt0շ@m89^-(UDAmFc)Q/ٚƨڂq]2Q"0iM^.Vϙ4?#1M̆<ȡ0\t*[?뫎Jc@Jl.HAHx,_3/7Az>\0 rE?J8,bGcXo-$ϧkRf4Mm_i=u!-+EZp',}x5Noml/Ss Q%㜀`$x ]TZ><ňUo:V3"}Pn㘏q!Vvvz5^ny*+|%%%4:111]1CӮۅ!k^vp\tAQn"}ztzXI?N|ݤCVh7_`1BTBJ6glg=dCScse [.M-hM7\02n AyyoK1\tT6ny-TIí08@Ȇ ti@" d"6Я)5ԕ@8;+mPR([_ OO4:>\tӽ/hM/GciT< "(–+ǃ,KWгh6tlYF{ ٫uG#%*  R'3?b܍VSˎ!g5W=XT.qjH=LTF \tY^$7Vf~X~tE`^6 .8ⴐX\0a$?s_xớA˥i'uJgFKia& {,|'g6!\\9̭Qxi|u<`HY]_/W\t6#(F-t}AccI-FT X\0hw@Zc(KrHL,7T$Xbzra=z ?|(q*RY=HfTBs' 2φDøZ1PTӈ*f|6;k@ɻD{n^Ez0 EWc]$ݴ[TsRl^oEݱގ?FzՊK\t G{Q&tUܴ%2.\nFָC[]&}XGSq VڦAűQq>Eg OKΖA(v_R1AGYm] v!-[EHi41d[׿aQLzY#el|.@TN YV1KMbaY!Sy Hgվ?~9 \\\nb6sV!3;"\nsӊb1,R%04K Z∗Jz>Z+ "dt~D_T_  wzaD#*8d<q}L(%q+gW_ʕcCo$hdV/A?+93*#ˌ~(p,ZXәg)kJQKK7F>Т ȅecխM>aBq:Z]ŐJkh*w1DMsWկ]ױRQMV/(˿@U\nlgRh8*:\\WZ3ЯB`t/87b%Nvnʷr޻JKXzgTgd=Y.YG S]`/iqoMOCy0FJ*/yK\n_X#"]3&ڑ{? _b%Jk;}N_"6T!2YO K +ug?\t΅3+-eZySTu#fC_(.z! (qD%Ÿ\\y^2̡X NtN^w:3R~|L tg -)PVN\0.qBmŀ̽}tƩ2MOSe iY\0όo7ӟg~`s3ɽÐt\tᢆ=@acÚblV Fcj/jϳV ?j(7\n{X]]~\t+NpA)8#&q_-OO\\|p[A:OE>Olˌ};<!/IJ?\\ GNK4d^$݂C" %/)DFu[ϑVAQ5@{OC)8GmQ QSg<\tl\nUiNീGNN6=E,6gGQchi1ɾM>Ι)VqX6VޔLsddMN5d\tǘ3>K9y5~b'^70# ̆ݭ[\nP8=X|ga_wVedhSV]@\tS8\tGy,-FfᮘtR .Nci.6εZeYL vZJܺFeL\n^>Y"+s' oMJi愙hp_x$ꅢvZܒJH'R$PARWE'D_+%z̴P$ IJU`ƚ_Su12̸#k#n}n)Z[cy*PTn\0UBS":p#g'3֢@lQwyCCr)5Z"8іP\\Q?o]XK]e53ix(WS;}4N\t\\<4֫leĮϥ[,V.a44y&:v"oG0i ʅW\t+6 8ms4G`PE)\\m5Ja[G0 L~ǥǒ(0(Gr?@o#?˄!L?[QI KOiXБeрBŞjCdž12 F=\0⦉[*8>zC;;uՔ[1!ujkWSm?ڸ*#i lG-i䴯tSAn-??UQ;3B Crrm&x5QZ?|id9; _ש+.7`I=d>~/\0X:twKSh""7%q. mSMaExyIg~bJXf*fgB4:wqʎώ:,blⓩ\nB@&\0@;C-M9]Հ0s2ןw\0Rht]YÅ2t#pg;\tC)VvG=\nŹҐ2BwuE5f?Jto"OޠN-tdoctNïHҝ2?gF\0nZݽ XI&l g(xYl-C &FD{-82=DXsmB.\0'<~0U|JnS`b:jli';:H=Nl\n,Rn%j6Cb)"sp];Xvm  8`64KO\nÃK.^ ӤՠTۓ|͊3WSVO#8KE,tausUVݩH<hMa%)8}Btuj ƀK+b.\tQ&Xݥr6(.q$d%Rkygos, <-pAF &@\0TgR\nh5K#FJ6t֔B\\b85l&O $q~;-p<>yb2]YͰm8\t|k'z+>I S|U*\tܑ=sj+* b0Д]g9B&Cya,@ɽm3/\0Osai/>%R)Qe % q r>(Hnb'})d$Q֫]y98Z\0M`+);VP,AET!^vWB\t@lBD`/։MjSO~v$z$ |A(Qj;OVVVmM+C>+f<,hkֹn n@!ߟ@E\\E6QAWi*mzWM6%aS^h9Vfח$G'\\Igk.ޤ9QDuhɇ&\\ebEP)$`]H Vroie*G1)gQx\t4bH'1$`|emCU\nȖDcS&fLh,{F@m#F\0Zj~DN>QKX|Dy#a'Bʇ</gTz^;S4hNJdPmT2z7V!ShS&/"/) X*\0,yx]hjG|ƪ2h(Pn0A5#AQ#&ZKp 4aJӹg'%fh_X;g_(G`Ff2' \0NؙPwk ӆ;:f@5G;v^@%DU*=0\n> cdEVWuXIՉ"ukwX[IL;ZauN,g4$~rw}\\:O_/~CU:ZWFEPhN*wڹkX\nȍ\0B DUŠՓRG !53_ > _;`\0||*nM0}QA(;'?Cll J,Id78 ZS2*10SO^IJ4 q| .3ΣshdIw=$"%GһO\tļZ"*9b_(OaCaԐZ-pAIFW *GōfH^xWq"ʍ`^?vR5cs`ڊmRh-X냾Hs"82}us#O1:T9J:<>V$w_u zcȧ^_(^<S*\nV>QaR l4b)$UsiBq.쥉NJ$kPH]\\cu`kqUPaL$縧>F|,U$;KORض=mT@ (ҝ8O{*P~U LfʺsͱyJxao:1"=a{u}h$˩Ei\nk83^l#dz]ûM3Y0UY n83FZ1V|5z:R9\t>88|I8&tXtQX\\8cuc)xEClpa_pJBen!%$[L N\n0!Xݘ[w/Ÿ-ؙ0ǜ^8Zۉ7zWF\t{i[L0LsΉ?3 Ƴ4DH%Ē5S>W#w1LxcD\njUro~h\t|naƦqkgL.\\gǾi۫¢uk[I-n<(TO\0ZܰeKKdl ,sJ}E ;Fi\0g8\\ʽ"JϷ(Bg+e$p{\naש=Csע=G0BE\taF=$rmO\\1i\n$!*vSx[`++ KX&PYsMsx\n<|[_S(/x| 7Na*">*YuΨa'}˙RKKy 73{u$\nrQqT*k\nT++t@W(~1~g]6ޡia\0E׳-zP~*j|p]{]\nY3}32W\n.) *1[䐄⣽PYRb#ld>\04G,7FLt\0avDW.;| `z@23zjQCڕx<)Sq&,4\nQ$ٿ*,ت0y~Ц@,=^B\0WZ\t:arT\t[Ujk+Ovī!#qᩏ`lfaY•O~%=ӓetɆ7+Xx sy) UZބ3rkRwE\\슱j7f.|^ \tdB6\tGy!ņ=[s"빒ov8^.3Vg9{=4|\n72s^^~*3sg:F7Ӥ=EqyJ\nÈ&\n\0F%e\t>oa؄+ iXt[N_Fjv2 RqW&[#?Kvȫ\tFjb5pozвG}аY'w)m yzS0J+g\0]JXm@?SCb!؁rnJ\tY\\0pnӚ"R" Rc 0sIDK74"h)WTi,'n_E= #W2QUϭ}Η? ~5TNL NG,[Cr;tK_L&}ͱ~1-\0r +͕lfULg*O%S+m6q1ЏD(aOq޺GBvk2f==z$ gMB x"3ښ:y{kݮV{ wU-'ǑFE/7?k r-қnVA"Nb5w'bL20FXryZnLHSU8[WU}2UptߓعeLxNu-ULYb7m\tX.HWeX/r,p9u3RslWðYR],F͑ml qۨq:%)HHQE+|zx3d\\C1puZrlO}#-x‘f((VP$+S9t| R',mfKMEGY9vR8=CSMA!6 \nc`wGՐb-=׷nZKy3)Y9}OTrm0pÄ8K] Bn6k=Jj@z~^/Kޱ'Lޏ=wf۽^/n*52׮ ӹ,C<眉\t^ÊDŽ JZ!/զ0A!x-CR.4r`\n@~ a_&M,,Y2Cǜ\t\0m\0dONLi8p\n- Q]Uw۲9sh+ԕ(KpH2F]~:\\\\!2yS72sl|8M42/>Z>w;wo\n-V9],!WH=ٕt\0Ҫ͝'P_`:;J㖾Zi/q&5k5r⛭pY{IǍ8^ɇ^Q|?V"{ g d boc{ڌW@`k2~%p #ve*p\nK5Dcys~E'' VY|TQOWJ\0xLnV2Tb:<9gCl`Am@3==UqG"b&-;JhָmP)_}@ {Aip+Wey^{jGbm2C& 65+=W\00f3tgCHء^JtexC q}gz'V>LP %ȴVhA{`4ɛpܺpvT]F͌\nzxxfw:y_u&ajVk ]R+4->\tB+uն ^F̎wT ts\nEV9£uEg ӇN?\t/ͯQJdюz)ƭ 3Q6rV;dV>сTC1 r~H|\\I}bYZcVzXʓh~P\\a*;$[_*h|CFE~k_=_lΈJ/Q>"ٷƵ7¡|7y?A+onoNIŠAa,ViN|U (VK-k(TKylG(1tjƘpN4lZ}a7>¶AA̡PkYqKwngu'333^\nLѢ_C<&ܙkLdiϚYEgXQ\nLA[+O$4K~'86$yܽUTk.'iuW zN;kw~;w׫W vkއOt7zW5uWQPW\0=n@6.@V\\>1۬mySW7\t}YʎT7Z2)”,5z$Xfx6$'凝L'Tn*  o4:.B.>[f֫0rBy~5a[xz24Z\te_ǒ :-8Ts1E 't=G.)q#߯McԲbkk,j^ x"pOKMI9wh\tѿX\nWD\tةL4xl(""vۡ,y>up `S+%6% "8׵%^ ;NfI2 %%m.lmV'œ_IN4=NuҹCH^[R@f14Iܰ Azu>/Wf)7;96BF uNMNJ戓f%66;f2_ ҿYM$Ȳ\0 af2nKu\nvVI7)rHwY"5mAKAPjcW[|!+#{b!f*e?Z+rq(p*rv̳Ø_9cx:BVRLcz1i!rjF [&m|a40"Nnd%eQb#X5"fJ\\3ZL~3$V#ֶyu\\4ԸUH لjGBD%ŋn{@'J`Ffv`u*9G?t̂ȕn 0GL^|tO\t1f!NnzL\t[2bIE\0/s7OjrK@/gO\n`{L9!/1lKyyAmhw_*B.:=9L 8="O7ЭZAOf-ekMb~ih4B[.6#+\nb:Wc%%e<;u'a}{\0 EA4]S^O7Wa'skzǑYqzړֱPLyrz91]s F1eA)L-2Z%գ: GS m;\\'u,0_`+\0g>UWr/2|TYh)QF\tFLj8RZx#A7^}n%if& U|[Be 8TMAwryI稐 rk<[>Վ#l)jp+R);E_EҌZ+ڭ7@{J`8"Pm+NM!vYhI1ʗ-A8\nUrr6C|,2@j/d ڷ(U巋hGW{ԓicyұoRg܎bfL#W"dI+rRV{f盱 "Rr+,x\ts[26[v:%8$$Բw‚nC+;̏zYZClJ>ޟuבDjHO^}KoQѨ._'r\\`\0KvԍU s?jTq!`{0>lKW>;" :wO\\E<=v|,2u$f?S{e5E%<Ώ\n-RT{8vԾ~Uķ @\0cm3\nkot"6$|BrG_T%R(v=.b~scZbҋ2 nkm>{IKvN8ڥۧE* зP7+O3}^ HKOohz/R1 Q^OםSUGS=SA TT'!noj0oP,H4#?PHÇu ?cl2٤V~NCKRL-fѓNqF!CY$5#[7`DvBMܑݘxu`\0XUv)R 6?0GzyodX ԉRb}\\95<.!uUCK]]+=uƔnh)hKe1|3l^:J_hzK>2wxo@#GCN:I+hlmD̹1Bp0K!\nE+Dy+T e\\\0h |GP LF\tq^ g] F=W=*%d8OEujOZw,(z=`Б2K,T۵SNfL4<@\t8fy̥#qW|}3V>Y8E@\0F>\06\0ut")pp+o-t $)7A\0GTY- (Tm*_%aR/Yh#CTsڦNE(Оn:N>0a}|`\nKu0pL dAݩۯa9Q3ѡj1 u*`,+UWkY,6-EI rhhg7w,H!Er'qBP2&VB2I\n,=?sb&[pCγ\0/Dsu#@S.j8nޤw̃!*X4Z՝ʌ̅dDٰEN`x\taGf>P$sϋ,!)yU2x;IJጘ 6ʦ]gp~ \02t>("v~3[;i·w8 rlზWg6}3Sk9Țw#Væ[?=ԖX" |34/x 8s(Xk£s\nPeƭ[FwI֊G\nt.0>x6ObE6Bv8SήǹR;˸0j}'3ޥ)4RlS&SoyV=YxvzVu>tqmy'DUG>wk=\08s Ǫ/,_`am!\t%'CehFK)qKGj7}4(>2uRץiRd'3e1fE`lp;B{d)d3?½سfHn1cQ_TXf]^]lg9 m\nKAxjL\0\t^N77g޴e*.ƥ\t!Zf-wsmr9CKNNTPEl|o}*\t$|AE%"q[Q0@WatWbCa6R 80B>jJ~\n~23Bb3.B@24^K (7RX9ݺ'1knj[%1~Fuke 07X`S#w:Q`t񥋍F#K+!:CյrII0wS݇oNC50HȎeާ\t+5% xR'q!0?.\n4C֌ֵ1RX5Z2Ǜhx ޤ"hUJ]}*@X}a~ f=zL.\0#4V Kh) Mw_5w\\ReI:D-Phs\\9>ThV k=?kU f藱}Ȇq6@:7Oکzgl\tkPT\tvTy!qLA4 d7)T2_#:\0W%F>"#_O^ʇ!Z-}u\\,,UdbcF>>mNX_ThG+0N+<ܱ#8~Юqe$O"M\t˯a6yEz =SotTG\\'|2p*YV)ˑI: c2<}KBJgh 95{a4>5͸ea{F򠯉kfo^7*8YXl#&'at~voyp_ ^;S{`(W8DGD?eh@dz 0+>`#WB\n5s[rL<,s^5x<3'vF\nf(\0ށeϝ5ܓf\0C]Pl\t M@vz^wx\0OQCdҨsøP:w[yg8ff"+g=\0x]wfx\0P@s~_D/A]|QB,HTn=L(). Ac-A:3@E^->AV%Tv]S;_(b=$wU"\nkؿs#cCF L"[\tD[ t̽쎬W/B]4Ҹh='~}lrotx08H˒&\0S\\OgM]Fa \0(iM&J\n|^F=)D 8Q`UYC>@y3ʄ IfWh,O7 yZ^-{}2Zw ?t=ǀN(%\\_\tZWQQ٪bg9M_/IsRk21Vjm2,H4[t߸LP;aX9Ș|G+lyĮhd~\t ۟}虾W3ÇT=b!j;x\0ҪtwϦ|vGkOin= .\07aeD6,n L^X+~kH*׿[Ϊ6vE_Kb#4\0쐦4YEWĔmr[PZ{^f:]ON8Q0|V$J&7功d=D.i (5oh+Qа\tk-΍v20~\nX>\t 4b!%rP2vv읔 ۊ>[]O*Sf~'fbl^]|-r/>UHd\04 {$T>_v8Lb\\v%Uq/(xs\tŊ]Hp% ȺUׇyN{4E,|^D'攆Kb :C?2iaVYM2X 0Q90NYq\\B=\0|GD5ǹY_WETe-,J\0jv}j;uΡS5\0ߔ16-R\0ТDtt"\nD#,pκ (oUkV>;5.f߈vN[wȡ\tޡJ+KR 9F vmN#W= x~ikkWqPA^o5V/-@NT\nk-`]/#!(>Uh,V{6`t`WUf$ķ5Qlqlk}s/4{;}Jm\\)v]Py Y]uƝgXx\0F+P`CNO%Tz)ŀ@fiF;,r"UFւ@4D,S.L{e\\՚8\0P}^_ӃyYq]"'?s=_!"VC8\tƫ89VEr:U tN ؼ\t NlphJ"3CM W ;36$11]9HgqDR}/Cۡǩrw\t͢iT'! )+W"f|--- +\\pۣv2v gT* >zy25\t?`w(FD+~ ޟBBc-}_ގYjKH+t/lY J3=+vvSGoI/ u^q~X3)pBҠ{z\0iKK\0x\0iם`J,T$qޱv = PZ~gC\0=&Cu-亻(%G> _ڧߏ@|Ef`D:…J>';_|.^\nP&%WcvۓR:v?RB4/2C%; i IL~/vR\t%V8U1اpœ9'َKtSS\tm$sS/|$?eC2gIw1Ǫ/RaL~l)HP4_6_SP|f=jwg7LAX\tc\00nt%tzr#4X]h/d8;&ο$2Ʃ iVQJ0\n{EùAGKl¥תm7tVΓ%X&H"ȳòW̚ &Kb 'ml ;%aҪ0Lg\\.ܪaw)T-(]$J=Ș L1\n;Y sr!>>dh0!O [%OEGh9\\&EыɆPB\0ktj=38 h١@M^. NeWF=wo"5\0dg7ר|'{߻@reYF p!RnIq1ݜԈ L+NRV$?rZ1%$d(/@4 I|l |-?M{L2!K2|=7+, ބ{ .N{L{.\\,1,'#6XpDr^̜-\n)جX@8EhDC ŗ\\o‡lpǻ/3?Ҙ هcyƋ=EF.yf0mzþM΄T;$ܝrKjZ&Ar?h7_XiWIfem+ ­y=G:Ɋ|Yz᧸5 U:k񯀷jB#:PB\0ɅM&iWp:Y`E\\ZQ% (L W?JE\\K 5.Fawa;y2r`1=sET<Ų4yvWv˨QcځzwHA&{ BU!͚fOpZJ3(O3Aa9#F;CWA@1ٍ]?F0Ran}L_~\\.OH\nh>$O4$l_\n},]G./pAʲ(vIBb`MM*Mo.(\\D"9-ډ5uتSAydaX= K]G$ޓ@@}}%vYdW>\tƱFڥ?\n^ATE 9kV?,剩&lbÁ!C}rDbY_]L^-Q\\{R_M3S/Cʹxˤyb&I.auC*Jf*$آpqfթ#(N#_:}'mw\tB/&K*P(Em⺀+{vFhQw+UP{|l,߲4'BO!/`Pcl+pk6"{-09ߊB'֩힒ZѤԟTg\\+Cp!_sF<&etÌ8vaS6\nF[JG3.W~_syC<'&O/Ce RtĒ7!FX~\0[/~u-PWENiM$,>kAϔ]UVݣCaAyя-,_S&~\0lO>,@N|t{G\nW^/)`@wTsg(]n?і]6#o R[F3X5{扜W_f Z*Ro>ivt7elt/"W+y-l3|\tPt;@$+tXIOyewe{kʒe7Լ7vb,a8Ό3^| | )Ң)UK8pRpEEÓ|H+Yi廛t׶nPqқіיՆci#\0ݽDBłzHr-E![})HX)݈x "\0^kƿW%,\tPdC/;klō䚴/aTsC#`і5%pʻ]&v7mRX.|iΚ6\0,mǐ;W.j3[j"C\\(ysaޞK^\n7eP`4zL5N!яi 揑k,ٗ"ZI9l c/,?EmĮųД$q]w'!%Vd3qRYLW!oz"wj1z-'4bgUbYvn\\@\n`9JrҺ:DM0V\0ꪵ--U\0$?ZWI9LǓ:4`ST@ZoڞaK/xsa.k4`7e08]XѷՈ!}8Ψ3ۉ/@AYlŵwHF4 -!IC.TDV' tXS7 غNXk_/#O:{d^Hghɿxqt^ޮUރMT=ob[17r"WI?ڲs U6D`"YEJL`ΛeO~~[ܜwbDplηxӌ\tֽ,O YD.z#yzl^(פG2^GG6us1YX`4tfYOT;NC{zP:ydaE~eiCi=y慝)W%MmgYRAr\nE+sE(tZW?\0ZMQc!;#SUaoْ=s-?lr\0nP«8f0-)ƛi\nsppd\nǔ\0\tYPuKϟyk74?vP#F&?ځ-u1S6NV|昝!?o6`x#}050kf5 HD~;c5:lUB:uO0f5J_ UOEXuVxMIi#6N.g悹E.0M`rx[g?H~ *Sia0ЩUN:o.^EbK:7\\!(Ofl- s_mPhiҵ&]c xu`Cnxz/I7Bi\t9!Ft␕qt)iVw,b1Sl6w!I_Ľ>p? zr^Tb==`2gl4~9N>rs*1hʄK ktߣܝc4ݥ9yr}ܐEMߋ-=R˗OTCCa ]z ִV-Ԏ߂; \\`0;b\tV>Ƃu\toeچ\\ -labg:0tdA1ǺWoX<|:?dsvPTi($\\[!QkKճvcY?[I}N|Ω8#Ķf4ѣvTaRȉCwlxWt\\b (-wt힘049VNVR%5xpWX"@Ѓ6Ȯ}D,HH"ijb\tT&˜h;=7,rG1#)e\n1k4 )b_\0E,wѸI՛u.>b©|XuZ'mwVs!N*5Or$@Za'L"?hNX+|/`E4wU" [\\ئU'.v4}nL027I2.Wu/[˃ EtAߥ@3C-swkӭrP8ix^i;beBB;}:}\tjq5"G0Mrɹ1Zi|ʁnYpC>$_J3Aj{i$4.x^fJA83㳒qfG#K۾4?w.c4t'Ґ_ J\\/̊׋Χ2dC"7Іzty)`I.TJ̞XBF/QM:i@쬧v-@Rt2p?se]bۄtf)P娅w)?Qa%gJ4$:{;?*ol+O9 >5ljꚽAiUh$;*<\tyV&cڑD}V& ;DM-pTe PFwgYRy5k۹\\Rir۽_IUjZo1`=Zh4\tu0<ޚ\095LwiIj{dB4~"E֜b+QLBV8dž[dLd\0,ټZ(\0lBM1KSH0/KnIxeK8[Q佅!b\0tP.IƉyyV`\tР& CIm[o.)SI`@Dl@M5fcW5!Fdix 6'wefm} MRzYSk~4W_dIµٶ)RǖĢۀBoCf.@jWߌCC6'RvIRX8=YR-'ꇀuXNj&E@Ss$?WPpmHG阜?vnWrv հ(wcTET\t=`aP^ΑW3u\\2h:5#\\H-2-fc;zWGR%!xj˰7Nh\\Dyޔ;Sƒ/S V-'MwWQ\\:Fo\\qzC"E2@'<B:s31MԚkZ`/h Rr rg?dk"&N\0˻Y4yD0BZTȎ `m:>lpV{x AcGH(7ML'Y&faWEE7"&w{kÅa\n3- ^hw Z.E0jn;'idaZ;jYMf[< !y\0KQG˳}^%̽Y䈗ڤeERE98T?+⺡uv\0CC^lWH0EY%q[~@E1iP\0C-2[Au w!/ cBeX\\*5e%7=A7Ic|PN^UlʼnЖj'kt@F0ii80l+,$E?s+8 v@ M|?RncZޭu4m5آhI%eƎSԜsf{c *;W͸R:?L/|^?m>}D5?\\holUcEnURYF6W=WY Z-Rx/ܯZl?@\\~P>*6!xf:~Gb2Ý湶L8۽I w@EP R&9s\\jY!lٖP[e~<5M?ZDT q\nYfj |_̪z EqPMӼZd.'`'?`NUP``\nae˛'XT\nc \0N_G(Tσ)7a2[fR|Y̙^͒~<v-{'}/$DY5"+Vi-E x\t\0T{NzJAmqL\0ƋD<NjД<i!܁,raN/C"CCbOA\\|1`=\nEt2$qz/jWqظW8t>gp0-F&jPx5?ȸ].xʣ*]G>3EDvxSXR0+"GkxX'!YwAYڵB."`iӁzs%]?#Ea}ŧ52t`$;XJ8A.\th.s?kkָjj83eYlkVY K+ǟ}.PݮT^/+VV{cb!T:x|֘4 ~xk]vEpl*htgq&jtRG6"y~r[rܯGTF7x֘Sч\\o,s]O\\'CZ@ܲ]G\th=Uioс.ab\\e]IX=$3#0;B\\ =@ߖpOXt!+k\\gls[W!{C x߈47e~r\0h<n?aAFfhweN`S`:{QJ.C)FۖDeD,&V]3h=[gt 0Y S@!_A=N}#yOjc\0$U^If\0ш\\J@{hW\t.zXf+$C$\\^\t '#+揻T7lO´|j RZzRy<B(@!?X 7Dﺸ5@\t쬤 7vg 6#\nohQg[pvNt7G!| k%idȀgl`F=m/Q:.va`@- 7n_DyٺkE{VJ%THAǓiqFr㙥?\to2vN iM>OV>G%]Hx"W\n[ys:cE|莏\0=_ ;{n2N.JL\\<:Jt<^pO]r5UF\nzmyAN!EfڻTPH*8|X^wb>8aBޡE,bM_cZ^2s1u7`K(O F`J'ZT\t8KaT)B3~ʓQ<б-1 RFXa0cGz\ta<,[69_: 9^VJ2z͍*s2dQkdZi)\n\n^M[B\n_G%o!nQ?sr?7-MS_5ddq1wDW|\ta\\Up|=I{q\0u7:?d.~jAy`>VUؖF4`H5PԾД*`f dO)fvR1ZݟL9K2jQTH^-jumMga[bTBp 7 D]"ɺl'xKC1l[\\#wg-EwN /p2pyO} ;q!vCBs\nG+|D:i/vPmn"N\\=~\nE}]~۽B,{g-S.Y4OkSwQ&U35<{%,\\Gi@o(\tԓ "ODGnd[Gc 3!W!InՆ\04tDtb]Qp+yٍͿ^\n=3?nK9jRCpC{<v.lKCkpRʘ)쐂BYc9N=W>f%.tKLn^E3@,6h` kJ9{4:a>7M.{|*f5T>24+^͒ZO ^oMJPae W vyF*Ɇ< Rt4E6 ݯb䩋Yl,) \nfy_"Yg~{<2e?TfbpMN wc ިKYw(ꡉeg6zň+íM yDlcָTZS-PgȄ\\u4ɔD[5zv:[;)__@¡$@|Ώ+4[p@x Tkc=3*TC,-*;~bɮx_[TLb;_Ӹ?@zre> 6NCRzLϣ̳+|NT,+!?U9r3@X=m`"B-mVۢ .'mϼXí̖7P=/W|M*!\0MB\t&=I#$/ vkŠ ߰l49?;/g}--nCt.6iLf!dI3Abi VH !0t,FjD)ЮVK]G{Z0f\0}j2,C'#!/?iҒ믞0Q~pLs+%E?kVvwFL`٦)}UρcdF1u/\t4ص/妧ˑ(Zl?anԂ=&`ٟ_~_f?E`*c;LH QԐ;˵А:L,pXy.-ueK5 )'{]GJd8'̦sשaF# E0IqoB\0yv(72@eg< \t\\fYK+\\ܒe{T-h]7^ӫ p2D"1pyG6Vl&EͲ5#_]3\n|\n9B!\t'n:fkũ,Vz@\n|qP~8CA WN9v1/0w NC tMU_*`vr@hW̜p:/.Z@lYTV,Hێ]( F~iԶ{ŸEaˆ'߅ع|p\\M ǰuer!7$[k=I(RƺVlC<ȗmf$.c_mc\0o^iHZx RXwdW1|c{~,g@~TJY}LqN{VM}Jp뺥=;-C Em;B"Pě5f`tZoFOtI۶^ixk*ruVJ/񊂒em\n{ =aJgM7\t[,HCLgs' NIl*E˺Ucvz ALS-/H21XSpD-]˛5h6Ya h?vڷkmĔcu7xr>!Z#-a^''?6?{&|LCNֲ\0̭x7~ocAFU_`t~5[ϗh5ecl`ޕ\\'  &VhzFr.X4x;ZԦJb-e:1n\0Rn!jr&s{54(Kl ~<'ׁҽ=K Q^ZJߵzJ'֍(,d8+LAډg+D$u=-.gmZa!^GXD*&TOM",Ur٥x6PŁbB=š;\n,^][Y+{eV|E+&7Xk ꌡ> rApߘp{ih X G'lX2Rt&?p\tG];OK[{@wP mۗS9,i]9BH)K3 <sqhՅ[u,=Y_14B]C|ߛ^7m9ot'TS»]_V"xCb0eVSʽ3GdrTou:"|c5rO0\0Y'DldZ}5Vʺ1zmSoЎ\0$P"VUvƊ> a/S0̜o+C}[=[/l|\t, g=cz/TBJmdžLn?WdFqi|ZOdxL59'S-\nJs&ben!!-m?>@Q6x֩^@)X91bv9]?\t$儫?#[LV T/x5bR&Ҷ ޫyg13괝@\\-\\IHhįDJF Jn,9FIJϼf6vZ|#C4l儣`Ń2Wc|/Oc)@{8ysG#:ԣ !yOə܀v٬[UA?{5c\\FA'j.Rf> =D>V=ݥh>?G^y{pȂe3.Xp76*\\iy5.8p3tZC|H8͇ ke.|?$]$Ak֣F߀k"rN&mUji'63WKGZ uB %/= ݦ?ₚώ#=$R.C+GL; \\AƇt0CJwuPP皩ag,#@p0(%O#qG, ,WfPh\nEfDxz5"^ ua{{☹sf[LF:\0,q~5\0ږ`T ZP_\0[{\tZҀ4VPbEʮQOSosmNvpЭv\\\\Ki|=!}Ub_J[\\p bM%o "Fg!^L1r(Mʴ]qHf\n47M9iGVv0TϵU{|XZU\\zHoi`|te<MR|=x G#)?k9P[\tNNY?uN3M(%_^)Y=WzV_}DQmJ?>QhXtVlT\\v{$sKjOR뮴nCd{mU$3i`\\dΧWB9\n@v, Bʼ=::6I(c-\0`ȥ\n[V>6-^ o?wi+EYZOs,ZY3<vF׾P(o6PI?lA6ODdAl <8YfFH0PSMFFDAdG.zWcUC-$-WHɃol?jsa0XjlJt}ra_m@nϬOB|@5ħ9^ݕӾ8!LHS\0bz)F&/ P\\US-YWR%.n{ rglj\n0@F^4-EfIPmXOW1F:} {lљ&sEaxQG[\\vt~2![\no}aGJ4\n0'pCCS3N1&D×Ȅ*ed5ȟQ37*'IFYsEOI"Ӻ@z P*k!H9u3H&.>#?by/8Ic /k/V4]u#:UWC؅"!"c= ?\0ؓ1uK U//b'CCGČĨs`'d ZzN\no7\ttKWz~lu7D-`'{%(T sDsܕkJH]K2A(8\n ȲESr;IR!=xMT9}%)ԯ()(QVI,dޚ) "،~P>fS'ɔw>Ml,׻D r eϓNP\tuksvxF  ȣL9\n&-)e6XLWrgURTHDaxul1'-ʵ4i$Mxl/{EXZApHTy<͕k64vE~r9 iٌDLR#⤗޻6?q͗X'TF>zU_)0t8 V:vhSBϗT)"8a:jS >:T.fH4gS55V7wˣyhCpa.2j\0密@lj?4Mq0-_1}گZ\tA cp´gexP@o$<x_ҞL'>\0S=zwWA_ |Sɳ;0@z_z5' {M< UI>cݸ}ɴAbT9rr[Pi'V9;H!d%SE7NiZP: pNg&/J݄YI+@oX3ITY5X~8}(0&vx?R4JP3ڕh~ͼ(whn w/aHU\\`(T6 >$=Ba=\tvSR@,!m?%Mc@zK^tк{7nk\tp95\0󳰀U$i" c.ׂdX󄌘 ns}|}c7{NBmq'Sc [H.B2$7Li'&4Y., l$2^z,\tf IrTw95S(j,!\\S,t.|V=4ˈϪ1̝\0e+.ŀV)\0RR`YiG ,.%~4;U$oQ40e)(`wIJ'L]uiWH4`1g\nO]AS(yk tPEd {Wfv\t,!D^pT~_7 $ zfK3FkAf˳LPOз3L |^IȇT{@ U#^1?HϷ}ڭ%{):A0$@;Bg18\\Zش u mw92.΋n;K4 x5RDmRATp޲@HS hOL#}OYN :/l3v9[jj>~{ݞUyS5Sm\nIҊ\t١湭\\UU2Q^2Yyp |27Mٌa\tWނa4p@yah\n~Fؾe`85[R:hbEE^`LvcBg~6bf~Iȃ.f݊|z2Q@hh_*\0S(+!\0;z4`gh=\t)S@W),Vm):GZd!qWT+וD/B:W\\|%f﯄x&\t|GV2ӕUKvSȒQaPpYswje*XaANAISAH[F`ɜ\tz$Xp' FVYVD+|$4k i=8}j%QbZXssƑ伸^LI:'! H,jه[%"yb CE]@bC>3h< +s$-o7]҅f,NJ찏q:oh~Y%\n~$p*)m;$l\\BE->) EMVuk( 6iq)D~*n\0r#o=QdhyVHO̙ROQ^r'\n N >q\ttf!hwβAGjhԡg_zXf]3SF-OVs-%1-c_\nZ-wF(W\n01?DAO_t%~^0"+<|A4L \nŪ:*iʌWto{*0({v*®_01\0.m]Lz(;-S)qМ7·fhyE*^;=OrO-`r뒹h>mKYBtdiG-!,ŲqdHEVb`'g{B@Xgo-Ljnz[oa&/')Ҫg?NxIBJE{P\022 6t\twO>9{rv|8RbNnE39l? [ l-2vwi^J3r0TX!b޺@Zt4\\<1wBu=.kYg]\tay0y~qhVƦf8~27'NXkED:1lBs\t&]zdȩr//W> igfk됎%pKrIjpMy0o|])|'9}QwF7,)1m~$rl[pۙar`t>ӹA%UX(+k'cat7vX[M\\@_7$HDi/{Љ`vP1f'`lD\0hCBmb3f#D;a/Oν ܺ9y\\(03٘D9rB-5@'c-=ͼ -'Vڂb6qNM\\%Cx/62/y*ˈ<\\ԗWl@ahXKNX}7X'!_z\\wTa4IFS_\t;ԠpcsZJ.ye$zZ+Z= ۻmO\n3/#0fšM{^Ot d؝bE?O?~@z+%jM7\tnIދh{_n<6Cx衦;j|lM0\0\nJ\t4v8 H_*bE$xUMAKrR0ꐠ;A!RV?y 46FvaEd_Pmjjۢc̸o3c,McnhF1<-F\\nJTNŚs9|#6I:o4++L<*kz+ZpߠOfB HtpsݦK3T|$͸ܝ*#Ir+nv|JwIbzx3VVfm9-wۺD\n\0:L=*J\0ŧL@.\tna»Pr%%8ͳ!]Lq#gne2"5$@WpyJե\\t|{Vh8}(->.&ҋOϰ}kg|5\0.1k _dҥӺe|=`,_J{U9=/|1L##ތ+BΈMu5g5&F.}6a_[!E4Z XfAˡiNQvw\n-eofnXxbSNb]RӬCWg`s^sW+̿+H1D\n%LabiR,f趼1ӺN^Ef$yXx3Fx*}\0\\J[O϶iiD R(0aFիVe< +5\\QH[GPb\0\t8%4Lc&iAiO3YsW:E$bsIIZBF,t~cu) TLF+r A\0*bW=fcWLAZ_r pCI\tr=l%h /;A71{ķȏnk?Ga 9mnBį~BJAM<7krVLE/7>6Ҽ\t&Ou ,] MUTDR6q5B:u}\\H:>`f3 I*E-77[[ "@\\X/@PœY2EQ**5X}e'G̓hSn9_\\C٠}k#q} PuB,]])HݗZy_h{>c\\b7ztgý2Crʥ;X̮3%߬mlqH$Lp1G~tm;KNN@wgbR"bQ{DV\020bq<:uj.\t Q7we:ÿ)2ңFȝ9JF?"FNPMeqל\\#*\tÑƎ7~N㟀W.QГ΂BF|KS˽.SڵzW%Z* d7(0l؂b\\jXKs-Ḟ)U' EMVG#q1zOFC5_,V }J/Q1")ќ}$\t%=]̀WfCg2JZp0֨1&@vXp\nH[\npAQ3d3VyNSn_蘢󠤗l# 8L|0q@\nSqEL\tER`\nFez@ip+԰z3&T]q HeA%llVT+sK[C9B3{=j&MF}4n: V3PH=L8@y=g|>a=d!+,fv aUڠ^R^˱FziƥԉM44}7I={Kk|drw_\\EVNju\t5J8ُjKX=?v4׷{^4 lu#13l¬!w%D|~x-Dl3pD˂,*#XXuC I)\t^n.eP4KVlq@xӓ ZϛCˀwxE\n^vrf @Z5NZn&tI_GcU[j"ڲ1<~>7%PFUhS5>;1&bϢJRu%4_ug.—#? ౸U >{];i˴t{J,h:xcޚtwIաL!)Č@iUJIx,ƢdJgd oW E}lW^E P$fvFF3 [X[svP6!k3U.'n9-"Ty`+Hiz@=Ij:D͠*% T3]~8)=YoDbPfu\0j Em1ZТo0)(-ѽH:|idl`^:H=rI Q~Α-?^ϖ~{_3ku(l .4`j"B=Y*v-rk#[W:E skn߯cee QJ&\nfg+luC^[\\k!={ٜd4+Mωk\0CpFdtTd Va\t6޻9ʠK(`3ᘪ0 ^lu-ÿG&%4>WK>"όKbΕHZahk}e!f.kta=?]PTAA^)_:l O\nVk =CvF"K90XH`rҚp`)ͨC"Phd'ډI4R <rpބQ.I* Pf*p,>ܦA*_43FTd|N+CDAq}t(kx E-^bګpBvӼ߫I\0\t5]?K6g)17OIuV/zکL ugBrYjx"VQ69ZX"1kW@NT1#mr\\ם4ΦqA"I>VZ/3JHͥ'^`Wm4}?޿llh>!`p6cD;/B)hF@~Y0`T]\\:d=(?-񂖻 JTo~%t׬~:='-nTPK9-Su0:Ƽc-FoqM$KFc(9(axr}8+%+Z?[i +5l)#DrxTB ^n삦'UDnhc8@&7tpllSl^O/NF$|%W\\fj1DGCTx'w!DJjPptM:j̅}et `y PC/#E;dp߇>.}.ЧBީZ5 nĂOagC7nKj[v\nQ29tz?}L҃d̐ å\\n\tх__& `pGa+OqAP{8EG؄2Ъ쪶|\0%+h1vE΅>t.IS#¢\nU;OzrW-\tkz䖒t](ӷ8|3\0U ?\n'3|j;} e aYQmᇤ"bXfJk0H\t\0iQcO\\qS sa0m ;:aeEm\ta6PZB]K%\0zEc H"'̟^;ذnUUM.p\\;;{HL=}mVt+g5pϡ:\0<ǧ>WWUɥ}˜WTq.8`jb\n=1U\t0hGB(򢺔uwv*Mf$rBWf߁\tq\08/ǫE|e#sT9%!\0QďF)г_6>ZG%˗\0{.Aga(0NxgsƆVT=eh$ޫ*5:+eKHךi5U+ Ԧ^ϸ),9%+-#rU@G/1,dyq4YFy<⍩WtB\\N0GhP`R*EY/NLj+IDҾgm/;t z ~G$4ˉ:R+r\t&ÅVaK xn6=$Gڶ|P(}x9Z_hEx52ސl\nZ\0}[7S($T{$g'*6=!a^9E%FW;[|ٺ(4X+)=\tn'J'Yr`~Nc\\ylEs')}2Sz\t9֚i30sNwI|%M[wLB.QK2dٕ%JEuK%\0\nh0ӕ8-eWX\\eLO!4ܒXRtw<0…= 23:ȾT)I\0RMEf'Ru$rpP!@<cߦ8?2gU9PɁ&2ﴀ;GҀB.+D>ѳVW.-u{n\n'\0\tCpB "j+Xk:TZT?6JR-\ni3sU\0O+2\\+ƬsZ={v<0݊Iu垅'qLO-1gM̤TȞ^6tp3Ѐm~ɭPYAQpV=Eq DjM"0ᕋg/|Ývȓ\tLGEZLX~A{P鉤!{]v-)[բ@Π\nd& #gq"]`rIN}vg8@#;kOM%7]Ta>rkue)|9ҼK]wɲ-dQ-%O{iRu@!NP%j˄&PfC,XYüUe}@M@/XFí;ڏ;v^zp\tߗ^ZBv_ވuR$@j,J<:+WTC`NeYO#|eG/T}AM}%(Ёeֲ>?\\dpx W.D5#\\r.𸈵II)^\\ˊxN5z4s.%U칪G#Ā/!~0M\nR:ds]Oc:bN)X Xa\nbے7EXd&/z4!]ϭѬBV zzWFtkyVoo{+xKaLp.:WyaQSoR#x 6Mk@~e`Jō)tu EsezGY`s4N nBf`0?3;2;cq,DoEf']չEE\n}4ZvL:6\0$`F؉TLyPF 0jxu&\n\0@u}5VIG6*-O(زlGaBx7Ɠ(X0Xyo*E&?/ܗwtj$7+ц p&ԤhΜ$USO؁>Ix5R.; $nmAB$#.,CZV0Tć|- ޷ AM3 J3h=Q)D6֑z[>{\t}qbWeE?SL\t̩%іY< myq[lB^`PIs䳑%W > 0D32~k=>-cH{moJaÆ)hv#Հ ¤.J&G8\\t:as #%w)lbII|n%P}0?giu1캓?JT$\0׻:}Z SpY6ғ5XgK}noP?{a/,֘ПM,h"ye1qM?v/q[%0󊤀ʈMh@[ D4~[%Ў~F'u+Sq)x=.֤9\t#]\\o7J\\,^]@Nm 듹cu!z)ĹX@c VC"^์P\tECñ^V":Pa. Ⱥ"ۛܠeϤJoIkOC8IK;+PBg~,.I녣W(e )_x0j\0ڱ~w/n'XBQWNUa8/ݒ2/oV9o|)ӈ,gΫ>2:8>Q'>!6^zRp'Y0g ,<^PG"E?REnjLŸ? ⹈?p0\tkqirXxY+WO^?8+S\\,k"2ވe$0ʧ/ya0Q}</e&YyA.7采[ߑGR{'/Sم\nTxʦǸ!p'ߠC]>9-LbjLy6MпA/ytMGmcmbƜFb\08x"jଫhOn+l/bC XO2BքpccCO\t?zmЂ t|L›l{>92j~/CK`8כolVg6G6n|&,^ASx`P(s^hdIBojP!3Z!6B/ުl0E=fW hS$f=%Ÿ32P(pQU5iﺩVʍ8X f,q+2fOPȵ:2du$h?01TUifLMg5|>uI\0#{A'.;^̸m_TھMXB"4|&1Vor2ܸb\nύzهbvm1\03uףd}a`>s @Yc#ΡRb—F7l) 5'*'8#<{n3oF8aW/ѦH|o# ($'#[\nXO.7!j!g,bӞS@cYK9=*J'{*Nʄ(Yl+ךAlܟXo~{%O($(pjj\0wD/Zn|0o9Q4V2':@Ѹ y׮hHf?>*t3{_{$V%$S>sY%v]q5#'CGv8-H\nqymV\\Z>ƒ ù?yeYk6)!RihX|!qt#tl^A%|]0^GtP_vZ%)֮N|KH\0D0WESrcMHCU/ݭ |\tL9w V;:;1Пb}4)\nSʱ#lEgxqŞbJ6+31-ͭd|}"CGikw)29Gqe8DT#O7dOO5 ioXDexJI9*/gbW+Vx_4~2Z2O΄%@ANAW>V??V5ۣecG(! !!QP\tGǂu5IprIJو#u׋7@ ,0AĜPz")?܄b5{r-4MmRȧ%'>]4xejhs*oD2©6ޣpl_z=6gbSÉZ"ÇT/Ң/Wla֓HKU2FZ]嶀mE4\\%ulidzM\\.w@L8knלo xi$Y{ݎN+9/Z\n[+FBN1Ω@#~-+*x+8!_xB~$14 ~=/ 8%c[$qIGp#S(ࠖƜ^U!\0'qr#Uܦ.i:D^}8śMYj$;a7 +ͥdt lcSl@F~敪VB졗A\0z<ޏnw*:yc ~qXP#ḏ]}u b%+CKF2sZ~uEd6ZlAOnLWezabbts pؠtA詭d{ΛhAeھ&Z%[qlST&}Z0%?Xu<^݇KǸڷk):H=xgH n?07|'FoiX9,3gKAv/l/8i{s٢' vFkQ"2Xx=R _I)aAaqpQ\nȲl>0]lUf`PV>F|$\n-qIS  Sh.{{S9".xLlW8FQ_+y+]hVKXEc&;=4]\0J/v\t> rnSZ9\0\n1`P&2G ?cI(&͚e] P\0jUk"He{.nJ.m3?%'}-Lް]"rĉ~5~ِAO+RM]zeL 6:=M1M*a褭5z;~&yO[jr}e^p2(rM HA,Ai rPB9p`t^F>$j{KxHjy1p9\t4Vė*s>2rܠ͐[\n\0\n*B7J\0l2(ƙ((kmg&k9jN'A%:0~ώEе'|ʕcyU67d&O ^f3ȿ:_I[PE3PFO3%Qtf'j6Sp<Ԁpp!Y̼1;;Fdyr_k 8#BЌ߹9V\tR]ȎzefIT(pC wuYHxN)-l_Y}刽a\nJ5&>FDV'g?CgE_>w0#p6V.9$Cjr۰8\0N$u~ɢ.6.€ R|y1&Juta=fԡʱel`J}UZ2%mF 1Cn41r{$\\Y@%3 Au`mnagCO=ז9CBu^8-DV\0 ^xdx3N4> &jy E(-"o"Z.Dc|op1n6&[Ty#['{06#LqkNOlRJj8%2憆7#~.>ALχW:\\JD;oyt,Dƙw{p?6uvx+KZᖀAWbYo6`6̠y͖xҖeřڔ>T^;\0i!4T[wC P3J>\nx;"\t`N}HiS'h;R^e2ĎY+7צ h臘߁n-MyO]n2_yBCbi蝂"'kdIOE!K733A@Y,Os$:~0g2HyCjOEg:Q|\\Wr@S;S~4̉ZJ[ԾSf@}\tbg@+GxqQ\\^d\nk3n{&yrtlfYM@,9~E hOQJ^v\n)5Z3o}x XA;0]:6Y\tsCM=c\nE =r&/z_u;ʅԀ\tiGuV1-/IR]pߢvi\09FAґ\0lc"0.Rx4yΩqt4yb&×1ev>4tpM["tL\tT>I'|4%bD \\=t3/ !?f=dGҍԲ{s\0G\t}ɇ)=J.(I=;a2_bo@4ʋߏn5Fܬh-L"\t\\r~D?I^u\\>I4ْoErTieO߮SZdœ9:vNۻS&xh_3rlby8%c@Ev z >0.yەT78B2fמSX Ęp eG6u膘656r 2 u=>2p@T@$pXEсyL[\0V41lF\n<,2;a̛{ ?#9Jpu+nI~D[D&F2Έ2?sZ,ZrIjwX;UK(՜T%'Sa|\n1RoQYO9\ti 80Ɖ^X&ˢL[L\t B(^\\W=M7*\n* N~2oj+h3tTMze@n4ɑY1X>5ͧ3@`*Ȟ9҇Ђx^reYQ7dq{F h\t4|b\\[UAGtO;\0* hF/6X~'I>b0s\0M9/uhE\nS ؜#f)dn(AhE)g{Z|C<ؙlaEx(ف \\1;YEA`VY$eMCݫݨ}\n8^qŪnO,̽*Dm{CA>.AzHPQ wO9 L2\0z"Rb\t#2!=׸]~z"Ity?׈GX&$9,_2yߒ$@qR43 #zyZ#sPKa&7]M8+ǝ@hnwt0Y5@ۼC?@gqk {K3WlvJq&uEo_o\\(t1i,bXi:j׈{x;l^ OJ Fq{=!MD{Dr+``q}ngOFƩ-OP\nܗS3B)9"žiH/C{4u#j(:>8#3a`Plyb /BeE goiQe\twBWKLi HE//\nܳkgOreHcāv)j&\tmWEU }iٱLh#qoV bmN+_~@/UnvIFXϜ'|n#QŴa\\fUS'IO1gSC#~QXe [wg@f#LwzcEj 5"VYfمMUuv6 ;_(3炼Rp|sSjmvi3`閆b;.ā߼iFϗ7t?M6;0U\t\nYspCt4n/\nl!]h?b0JC7^05n`ɧUV\\(aϠ(ISb'>ؠ;&?PU|Sua[yv򽽗ztm,82=eK7p6YLrˢ۴aFE052e|oqGb-'x{,+i?҆W1>iJtS/yXcMU'@Пz4pt1-G)Gڏ'[.u۲j-6=H_48$?"ݵǜλr`nNIJ FO)ȧD,-QUYT 4&'b|]eND}Wf:iFu'kY$s+KA4ʹxn/g}pHmWFCtyΌ@j6»$u?D![)3a=vk:Yeat` 29\njDLA\tW3-Ym:8b;KiTOۄpkVq1#\t\tGw&rLR3Rc GeDPoR\tk{RqS|'ت=kfqE5[8S\\X9\0$<xuU7\tv?֡Ѧ/Ŏ kPu,ƛ~<~o"D1O=bK輻!IKboV)Ihp.|:`&wA=Ny$^g}2׋,{! 9XתYT򯑈lQZ21+AIHABTUg}*/EiY|a |7sN%lJ^Ie)(嵖0]t2BGF2z1{|ڽ2/%e₫rOM4)FJqkPpŒL;?r]](lj\\ڶPSԆ7QN׎l㩆4/{- E/8ݨw銉]|"qZf^f_9-؃F)cMa(@v S>(oWQ⊐[v%$|d+QYaduu"vN \nP{"4/sNyQGKiŞI'\\lh˴#+f"9 3[m-T?P }U,:-ؚtRpnH}QX_8j/a-qe4;^XT3i,U3Ϸu[T@g\\ؓa@)Hɔ+PՙH2nې\nhO!kS{6WGV2h?T+,ʬ4썳l$=KPߢ|ODo+3cOOK9,}Qׁ#(P?B%a3u3BnB5n\tGwA9mvЉbxe m|a\0Y!({(s7kHQܛu2%1EQcW8WHc *$ j$0/T2(\nATW9i*PajI $bX\\u|Cw:U! R_5\tЯ)q%Cx6%Nߏ˟W7kaZT5l;gRȝǻظAJo|_o>7sC6ڂ[6Y{gO5h /;.V(e#BC4u@Nu߰w-wj*ØT0żuP6_1wA_9(V)UAST]w$`A\0Q-]wdx6ws@q DW^ϐtYn r< 0yי|WuhHYۋ h\0sGkcTHP7&ԉrf_;*w9eu܈\0b +EuF$iKS.Ќmgچf$=;MLRV0}F6^fNBK:i5֦Y-(.36e"Frv AGػq%\0SVʖ#xO.Ȯxs7čSyuuw$xm\\5tdbZ_b-]w/]J`.S?9xdiD>GМ-obaCy\0KgIPrrg DzJ@}՜hk"$@i%@w/sL1=H?V-\08%o'z B!?ف {hre3*`HںLfQDQͣX,(^YVoFgo~1Gh Leʶc~R'J9էa\t4~PK({"iv?G[lmS7khSP$!YyV2~v[ qh.,ă(4b=8C$@鲍&Xndtl.Yb0QN*U,'=AŰ`USIK-ևCӄAhyk4p\n0 }7'Hbr":RkXBs>0UMl^c}ۤE{G'<hBT`\\ja9cXB\0Rц!X_Ooؓ"]A/U[XׯA{G47mZ"VG?}' s> \\bE4\0|%?pJ|ǘe#Ї7%cLR`=L-Ml2~Β9]O?8/^S*Ij\te I`:]58"QF9j'&B=Q775e;6sa|>* tAO$RݖŠ3>z쟷 ۍ=JpuBr)FY<|h)\tůiKj q&l~:D{_ibcцSn9'ZpfB|K :6mhux=\0Ѻ]W_Ԕ)k5G2䓐M`EU;ݫmqs_z)@ˌ|T{I4mjGS_)oxt$"͛l0,qB&p)T B3p\n&Vҏ 5l\n.ReRӜ|8[#($^^\0"sK\n=bzT2og8o^8\nή$4WɔS88l4HZ,?vs-܌矺hE2ٚsu,~˼T1YˮnDŽxM RW|+<R}wv.$b8[/NtD\\qͱ['a'0*F91N09\n!mꄆ^a v^PKO2X\nFV, e')B8XCI6؂.1N$˕OƖr1ҁr&Wh$)PW2=8u% ȏx ϛM2V+\01&%22?o'K1/_o~@P7V(Mty:TYfAT%f!B$ѕ=cAi$4nH LG7.T3DL}1NZypXkh%,̕V:_uz~:۰U"-0-*4ݽ12p/|H "ȲD٫ҤE$/\\"΂y)<~{XD)6\\ \tÐvڕZ&L, 4} {D@œѼjA٘=e#]1OӬǠ~ Li nZ>~< giN^4fmaQFZC}m)#]Eҿ?2h oCv[?== XsFqKgZmBEߞ(2ks9`~gCBSGմ9:lB4ĻT@GWF26(2ߜC?L\0#1}C2+O\0?rCT0x0ӎ͐3jzlDuEAixo^{w2_\nY!hU8"(t<imz [ϓy *'TE'A|7AZ|\n5 ^XGHK=šfJ p!͞0qG>3*nΚ!0h8yrL s'X4X['\\u|?'D2 Šʨh1>i~R4vFMh!5{S'H7F+\t\0韂C5vEUL'h[kΒ\0;̗W w=\0*`u(>@!>٘Wp'{%LYSQPC--YqY g|v%]f^x6˾?[t.9Cq B[X2z&7\n}݇Se Qa JNֶY=!6;AU&jAm-XB.2hJS4Ǥbyzl/ׁO\tzӒdwfF{(\nYBo+!C%0垄,XZ\tha:7``9!7XJuK o/&$Ց"⊜`\nHF5X_aA14a⋱Uښ_LX\\bR ,_ؔzP3VQhE^pF\n杶uʱ5!| XWܸNԯ߯#d/ϛ)4L`d2X3LgU+M?SʊoRYޟUХcn!]`TDySI4"f'ؼa\0{RA8 r.B8,_"eٲ@#C˓5'ARPE<))%A͜`\0P,W99i=x͑B۽ VKfWpiaZ+Y׊*wX3 ]15*He?Cm;yPo|epӨnEqA!fd]t\\-ma/ͦ\\ZCT$nبc{݃OqoaDkl<\0DĴ!2p3T~;R4`  dt-P-e$^iՌЎI$-'Yˬzn[o\nHy/\nz2aM <7=t>v7@rr(w֔rʬQXB4c2= DmP*^gmAcwPXͭBfr;XI09Zw]XX+")x:0sts~a? |>f'boֿ#|>>χ{?{O}e>~sqn~A{|;{WzͿ[P=zK~֟ߗחzX\0s#67tw&\twީ\\kю0wyj齪Qȱ^!@SMZf"+E6zBH0cW:EƵ"n*5.Sxja/In$XGwa!dD_5qX||+O(L4Qvƍk%n?=5RfKv 1LfHkzSHWJO-N&`g|*' [ۑ!Z@xI#m'/SrdQ1?M>5g#V!. *ڀH%^VAJ\04Ĭgy\n}0]σw[/Q0uT-m9%U+aH H27o}3 <\0?(Kr;<%4P"9.Ḵ ӤtfOt|ɠAq,q%}X$\0eV&̘fjMM{\\wζC9@<\\m37K3lg2E|Jj3t;S9儏My|GVkA~;1ml 4>{.VbNN2 k_<-T=Kʤ; v?F4qYPjem:gmnc%"蟄lf7)YLfQqwC\0PB^0-T8\\\nA=j_%B{0E*`XxmdVGSF!{A. c^c'ߪ]?Xu|$llْ򒡎ӲÿB͎AQ'>ۑ-O\tzk1khAm3o 3S'ܗZP]䔾f%<\0ǑsFg?;KS%ؐfSF1,l8; |YfLu~uw:QV̼WXKK2*cvu;[aP:aBm; `Vl\tښyU#y"${8)QI #U!QUjlE\n\\ʄ6Pm[7UO٪I c[33`9^ד2}2^I9Iܚɶ]q(=5\nٕvGNM^"\0\n7!i\0klOxn;Dx6Q\t^,e#2A0LqFbզ[jR)t~C>MNbnpjuȮ˟[m=e%D!L^/\ty>cYWAi!@-W< NiϰyK*(}pC2]Uץt;"y,")g~{!Ut\\X)UČ#;5/ƒ<͵N\\.hF&Zw|͏ DONtb$pk_7T;PO&K[.-ѱKė4"l΅NlPmQ6D rr[ F-J0Nӓ5\0g+:آ \\3mC" \tj]);q۹qE-duݐyb\0)bΦvWB ;IT|MJ:e\0:>-i'53PZ͙,.]Tv!0 ċ7c},!Ph'eUAZ#]X~k):K%0B%& ?AV&!#Y̬}2by=5ߔ{e\06o\\rD(M5{}{"ס\tr|'u&n|H쉗}"e~o"g^H͘,\\o\t3H85*z> ^2*Ed-Lڑ1JJ +1tɆ;b"=<)M w=KG4T\0tkWQMpP=aD\\V8Vȱw"}te#^2LHMYr:#%+ L\t!>N98W \\CKV1WEd'~ab_=BZfzaJfa/XQJ&eGPN}\t].h{+=$t4hϓS s~9V* m59I\0Y²qreF~@C!j|AυWDOz/qbbZnΝ%^l Ԭ[f,4W;a^航-{WB>8qt 7a:uXtZon!vJRo.gvoڢmwe~e#8M{y{`G&7|sV,y^pUso}n]cK͕%yO*H@\n>z @\nl)O)"rR^\\JN3u4"mC\\_o$/eu\0]4Uz|h ): ۱<ޗ\tG1!|2CI/yE>+q"Cҫ< a[~ O,_nPk~@;M1{g!6ZɱTm.^]߬T hG&>Ӷ8\n8:]f\n [+^"&-'s,L*%Ip.NÖ->R }歅FAbҰqY]!Y@%5+qkc4mfʜVɑra0 P(2elK΁&ße]Ae@i8y>LQic>5SaֽSp'?Yd-U.~\n&7q@2RBsiSɗڽ%rܩW'~s-VJO{>=h%GM!k{%fүpmϫ' eنOp\t٢K\t ȴ`Vv@zNP~oR<)3d^fP5Φ,$o@vK9ߨ$U\0_)oޘ0xH0?!2fwS-Vy)v \0-\\e ;-gܚe`n  z\n江Of@@\t&8,U{pe+L~\tfƨYO2m%:$P IDWjH]3reKgG/|t¡,\0z?"͇9/Id@(\nxNHp:/)1I WT2"0&ɷ|fޔx~TVhBX֌9,kO-2fd{S2ˋRx--̑>j=hZCƬAF8 WA;f\0I]<(r.#E2٣zN?U-X"_uwW'`0r_0aSܱ$Ƹi Qo ؚwꤽbS7_y:)iG|V`L+$ b\twii9gR%F0R*ROpTRoХĈ\\#_=\\Uo4TyKI;87B0M˂Sr^w=:g?ֆ^A\n"\\hUҏBzF$c~EbbI'{ XBs[42wQ~cwԖkj$^꒡61*ZAn\06?:\\9RBSQ~K%VTl(f5_;!JχMiv@ dYY^o\nfp\tnKTyPWsExu, <`{JE_) 3N=/\nhJBkO$g?h6Jk|lըmC33'5u~%.2[^nlG'Y4DQµ|c ԙ2S!]E@Fp2gX}[*󡀽*\tWv3V$w6?PfPFV- K $s_Z2:wV=.|dɭx9\t] >rbW%jo6\\C=":[%Y#F4@swA~=X?{MmHO\n~=DL݄\\fSr\0}1q&#V󈋏49٥6Ab:ז5H \nKsc-I\0`~q>`a(bscpH>t:c'G;"H]}( &I:XȡhIƀpz ,^b̀1`XS)I`!kEY{hY>W3mЂs)G@)?& ,2%:':țrhԈ汒Gfy25͒ H}exLK߷^<*l>?wX,[bLdkEpքX.o\0>`< U\t(iSYWȊ2yHkħrXYD{\\޷C&u/T$pﺋ ϗ͞~侵M> {qo8\\)iU_jԻ[ўC6zu,%Gcv~WtdG2usxtqyJ<T瓈c)-X٪|2._uJ4"ǍFŗ!Fo;<[{?{H:9pjH=TyFvEY5G(l[8!0ܴNIj]ͮ-B{E-o"j2|\\GLuA@[fy}?wiN8f-$$0+F݌I81cD|Pnx‚։y7y/&/4@;7YV<(&\t_a!]ձOVI2Fc\0YhӞ<}鯵J{s>We i7o-ut`ϷR]@@(azg%{rHdzFܦhښl$F,prwZ)2+v\n.t̴<o.?bSU7]¯`:"!l<c/\nuw_ikt:) -2㈥ (_AfE=\\ݬ9)^=޳>VI.qa"">bZZIkC{YX$M\nH} 4l_yvښ]\tP)֥F O1EhhcRq! A89wQp'M*yQKlE'Fu6_GZ>Z\n=检<#A5rc2=-Un)xxMif[HK=B-'mŏW1IkQ+ze 1Wv?>s3vY,rl7W4,Rq.pbO ר2aLڂ-@;@wRs\0D ^ΈSVz\t!o<ʜXmqE̘X5cr/FB:~?,KE4Ku-S0F=}e)8`EbT`G cu"2丧o^֢)ro_7`s1zJNWHx5$,L\n=fMd51O_ppᯇx)%u|^s&w1Tw {w8PwY{jἧ&h%ZN~wUz'/glEffIum,W%5*ZgVIZ(2XGp\tnX6;NXR VZP3OBL6w-\t {5_Y8p6 \n3zy232[mn0t ,"8E`J..݂W4Teya'<6LΔQ\n[>ݨa\01ngbHxS=Acs{ A\nP0*gwAHHWf,wOGUA `s5=1t" iV_2{/÷2p`1δT^id%5\0~1l[^%iNմ9IM3$~ScbZ%Lj~XO]Ac6^p\toBvصJ;\t𮊰FMi9òuZ^F:эbWc&;ϋ&Xk*UB`vseu Zz>7DF02\0ss4+2UdxHܢŝ@7&\0DرN~AgfվM7)[>\tAq'IrnhR9v\0T/ɪx w"yhk=htrևa!U"M!&LQp&q70K%m,9cxsmga@8̗ȨnXO=Z5nC2)Y%gXalwNK4\0 Ę,41 Uʛםǜ?>Rw3mzҽb\0L͢ԷIXW7(\\EB $Qޕ/#FE"`ߕ#({d٤WIqNNgn|iTǦX{4gbP``nF=2/#GIM4ɤ+ !K^ժWSAdܝ;C\nn#Lt;nZaXD3rUg' /F fm?yv-\\Ed.vbYɆ+ثrУ+`",f]͒Ջav=|o!0.Ʊ6v8`V2LwPa3H}Sk8 509y 6pJWX_HV6zC2Jf< zGT=}t>D)\t%Hu6tfIH݃")iTJ" \\6ĶǖȅUSWm` Ldr^vL_|Ģ#pS7+26d6Wҡ/Gu7/ i|oQwl0\\wQs?O6߿}‚B֣(fxx@"[h;ۖ3} W#5'^mߦ-\n+0\n%&W)e/xgbj˂YI ǶFlۊÍ)]3Y= a: maghAy݋;5[{;z+!2*@6s0@u^6OS*s0!3,OI]\0:'WOJ^ټ,/mE c8~g$\0zj(z=[\0":F:5w=J3$$kcP?BVL`lL0N=v㝡^!vߌ>ǫa@|Ak1rklݭ$t +$ǁTb8/$W;`f>Y2՘c$?kۮgqw. |\n鄖ϰ7{K)t8K=U Ht*f|!~lWb$sh#'. . o/wAnW=~oWER|\tBlx;ӺgAitf|5*%Snykc&ŕ12@ɹD? D-@i9BЉ>'s\nֱO5 E)hxc-eߕՅǑ\0sOgy$BfC% aX?L/F)Ȱ*5L En9 LB|HNݕzt17h9iD2'øTz20#@S%f Q5ٱs"FĤP51"R Ds/^Fb@2v|oIOjB!!0[Y*6k_eժ(HB4Mx!L1Qnl,q !)=(&U"[-Qnt^^8ԵP1ԙ-ܻm+z!$AOr%y_q]sʉݺ:Hk1W1jn\nF抓IN/R\0έQz7(f+}۩"廟B1y\\ʒN1qr1 `|NZ^ޏ:G)ls/K\tFAWq컥@u`0\0;cnd}0<6k_FyI~[Iw c%1hwT3+hβ0:ZҎ"֏"]\nGO]yWpf|ϼ,L'䴳C_E*V ,T6dP*/,ރ\\FY3â'0/TX]./V8#A~CwEa7lqAxޣNB-8^.]|G5 \nD~(}ww.*fN )XGmھX$b\\?-^Vծ$\n|\t3~{ZL|nB1pox AdE0߾k;Ơ.ct:;VɅ|"e+@;vO+%QjH)0afs-VF"ky{\n#(rRtDgIV"; a斩WtM$u'CrF, n;{z7CaOJ#4_,\\W(C⒵;XV;r=׆Fѿ"\nR~\n9Mfl4G(=\t\\kɌz:s2$8|!YG͐Xd1`DZB"QȚˠ?V&gh^,z\tMɟv+|%4nrb\tne\n{P˿Mo/S|̪I+i\tCmro2m 8ՌP^oeS }[Da1e7sS_3keA㕾ZNwwǴ= AaV\nV E&VOֵoQCr)Œ;Ѳ/WGef.;zbl!gCϪj <}Z}uh*meU[#̽r\\|73Q$I f0\n'XS`<uh _Q6-DF S+<"-!J2J)|Sb:`{?;͖mB Scψ*MX? eYkk]8s4E\n(ks֗ΣUv6_&sȏUvNHi >S6\0~Fb*sxt}mQi rPCΜTq94uh+'P4Z//c~@\\%oI\0 UC<{nOذH7Qd4Z~ǩzKrL܀cȤܠuEcÇ8YJ\0,A1-PcE=Y(V/~WY?(B*9aYadtUD/6]:HX Z6,5 $yR$)YU:ݣnMI4o\0GNP>Q_RaΨdG3ɯPkZ#-1cw\t3=7 ]\t"Qʯ3;y\0/gk\\6 }κvn~zWeSB,'Sg=uO혅O!Z+L^HzϹ^O!Yx7{x^c,8PZc1g nC%y_|5F7L zA+tBdhSt"/@9bavҗh_w*r8T(NtI4AfXCBŤI}`W#%\nϟ\\W(:IhX,28ˈ1\0mp Ńt0շ@m89^-(UDAmFc)Q/ٚƨڂq]2Q"0iM^.Vϙ4?#1M̆<ȡ0\t*[?뫎Jc@Jl.HAHx,_3/7Az>\0 rE?J8,bGcXo-$ϧkRf4Mm_i=u!-+EZp',}x5Noml/Ss Q%㜀`$x ]TZ><ňUo:V3"}Pn㘏q!Vvvz5^ny*+|%%%4:111]1CӮۅ!k^vp\tAQn"}ztzXI?N|ݤCVh7_`1BTBJ6glg=dCScse [.M-hM7\02n AyyoK1\tT6ny-TIí08@Ȇ ti@" d"6Я)5ԕ@8;+mPR([_ OO4:>\tӽ/hM/GciT< "(–+ǃ,KWгh6tlYF{ ٫uG#%*  R'3?b܍VSˎ!g5W=XT.qjH=LTF \tY^$7Vf~X~tE`^6 .8ⴐX\0a$?s_xớA˥i'uJgFKia& {,|'g6!\\9̭Qxi|u<`HY]_/W\t6#(F-t}AccI-FT X\0hw@Zc(KrHL,7T$Xbzra=z ?|(q*RY=HfTBs' 2φDøZ1PTӈ*f|6;k@ɻD{n^Ez0 EWc]$ݴ[TsRl^oEݱގ?FzՊK\t G{Q&tUܴ%2.\nFָC[]&}XGSq VڦAűQq>Eg OKΖA(v_R1AGYm] v!-[EHi41d[׿aQLzY#el|.@TN YV1KMbaY!Sy Hgվ?~9 \\\nb6sV!3;"\nsӊb1,R%04K Z∗Jz>Z+ "dt~D_T_  wzaD#*8d<q}L(%q+gW_ʕcCo$hdV/A?+93*#ˌ~(p,ZXәg)kJQKK7F>Т ȅecխM>aBq:Z]ŐJkh*w1DMsWկ]ױRQMV/(˿@U\nlgRh8*:\\WZ3ЯB`t/87b%Nvnʷr޻JKXzgTgd=Y.YG S]`/iqoMOCy0FJ*/yK\n_X#"]3&ڑ{? _b%Jk;}N_"6T!2YO K +ug?\t΅3+-eZySTu#fC_(.z! (qD%Ÿ\\y^2̡X NtN^w:3R~|L tg -)PVN\0.qBmŀ̽}tƩ2MOSe iY\0όo7ӟg~`s3ɽÐt\tᢆ=@acÚblV Fcj/jϳV ?j(7\n{X]]~\t+NpA)8#&q_-OO\\|p[A:OE>Olˌ};<!/IJ?\\ GNK4d^$݂C" %/)DFu[ϑVAQ5@{OC)8GmQ QSg<\tl\nUiNീGNN6=E,6gGQchi1ɾM>Ι)VqX6VޔLsddMN5d\tǘ3>K9y5~b'^70# ̆ݭ[\nP8=X|ga_wVedhSV]@\tS8\tGy,-FfᮘtR .Nci.6εZeYL vZJܺFeL\n^>Y"+s' oMJi愙hp_x$ꅢvZܒJH'R$PARWE'D_+%z̴P$ IJU`ƚ_Su12̸#k#n}n)Z[cy*PTn\0UBS":p#g'3֢@lQwyCCr)5Z"8іP\\Q?o]XK]e53ix(WS;}4N\t\\<4֫leĮϥ[,V.a44y&:v"oG0i ʅW\t+6 8ms4G`PE)\\m5Ja[G0 L~ǥǒ(0(Gr?@o#?˄!L?[QI KOiXБeрBŞjCdž12 F=\0⦉[*8>zC;;uՔ[1!ujkWSm?ڸ*#i lG-i䴯tSAn-??UQ;3B Crrm&x5QZ?|id9; _ש+.7`I=d>~/\0X:twKSh""7%q. mSMaExyIg~bJXf*fgB4:wqʎώ:,blⓩ\nB@&\0@;C-M9]Հ0s2ןw\0Rht]YÅ2t#pg;\tC)VvG=\nŹҐ2BwuE5f?Jto"OޠN-tdoctNïHҝ2?gF\0nZݽ XI&l g(xYl-C &FD{-82=DXsmB.\0'<~0U|JnS`b:jli';:H=Nl\n,Rn%j6Cb)"sp];Xvm  8`64KO\nÃK.^ ӤՠTۓ|͊3WSVO#8KE,tausUVݩH<hMa%)8}Btuj ƀK+b.\tQ&Xݥr6(.q$d%Rkygos, <-pAF &@\0TgR\nh5K#FJ6t֔B\\b85l&O $q~;-p<>yb2]YͰm8\t|k'z+>I S|U*\tܑ=sj+* b0Д]g9B&Cya,@ɽm3/\0Osai/>%R)Qe % q r>(Hnb'})d$Q֫]y98Z\0M`+);VP,AET!^vWB\t@lBD`/։MjSO~v$z$ |A(Qj;OVVVmM+C>+f<,hkֹn n@!ߟ@E\\E6QAWi*mzWM6%aS^h9Vfח$G'\\Igk.ޤ9QDuhɇ&\\ebEP)$`]H Vroie*G1)gQx\t4bH'1$`|emCU\nȖDcS&fLh,{F@m#F\0Zj~DN>QKX|Dy#a'Bʇ</gTz^;S4hNJdPmT2z7V!ShS&/"/) X*\0,yx]hjG|ƪ2h(Pn0A5#AQ#&ZKp 4aJӹg'%fh_X;g_(G`Ff2' \0NؙPwk ӆ;:f@5G;v^@%DU*=0\n> cdEVWuXIՉ"ukwX[IL;ZauN,g4$~rw}\\:O_/~CU:ZWFEPhN*wڹkX\nȍ\0B DUŠՓRG !53_ > _;`\0||*nM0}QA(;'?Cll J,Id78 ZS2*10SO^IJ4 q| .3ΣshdIw=$"%GһO\tļZ"*9b_(OaCaԐZ-pAIFW *GōfH^xWq"ʍ`^?vR5cs`ڊmRh-X냾Hs"82}us#O1:T9J:<>V$w_u zcȧ^_(^<S*\nV>QaR l4b)$UsiBq.쥉NJ$kPH]\\cu`kqUPaL$縧>F|,U$;KORض=mT@ (ҝ8O{*P~U LfʺsͱyJxao:1"=a{u}h$˩Ei\nk83^l#dz]ûM3Y0UY n83FZ1V|5z:R9\t>88|I8&tXtQX\\8cuc)xEClpa_pJBen!%$[L N\n0!Xݘ[w/Ÿ-ؙ0ǜ^8Zۉ7zWF\t{i[L0LsΉ?3 Ƴ4DH%Ē5S>W#w1LxcD\njUro~h\t|naƦqkgL.\\gǾi۫¢uk[I-n<(TO\0ZܰeKKdl ,sJ}E ;Fi\0g8\\ʽ"JϷ(Bg+e$p{\naש=Csע=G0BE\taF=$rmO\\1i\n$!*vSx[`++ KX&PYsMsx\n<|[_S(/x| 7Na*">*YuΨa'}˙RKKy 73{u$\nrQqT*k\nT++t@W(~1~g]6ޡia\0E׳-zP~*j|p]{]\nY3}32W\n.) *1[䐄⣽PYRb#ld>\04G,7FLt\0avDW.;| `z@23zjQCڕx<)Sq&,4\nQ$ٿ*,ت0y~Ц@,=^B\0WZ\t:arT\t[Ujk+Ovī!#qᩏ`lfaY•O~%=ӓetɆ7+Xx sy) UZބ3rkRwE\\슱j7f.|^ \tdB6\tGy!ņ=[s"빒ov8^.3Vg9{=4|\n72s^^~*3sg:F7Ӥ=EqyJ\nÈ&\n\0F%e\t>oa؄+ iXt[N_Fjv2 RqW&[#?Kvȫ\tFjb5pozвG}аY'w)m yzS0J+g\0]JXm@?SCb!؁rnJ\tY\\0pnӚ"R" Rc 0sIDK74"h)WTi,'n_E= #W2QUϭ}Η? ~5TNL NG,[Cr;tK_L&}ͱ~1-\0r +͕lfULg*O%S+m6q1ЏD(aOq޺GBvk2f==z$ gMB x"3ښ:y{kݮV{ wU-'ǑFE/7?k r-қnVA"Nb5w'bL20FXryZnLHSU8[WU}2UptߓعeLxNu-ULYb7m\tX.HWeX/r,p9u3RslWðYR],F͑ml qۨq:%)HHQE+|zx3d\\C1puZrlO}#-x‘f((VP$+S9t| R',mfKMEGY9vR8=CSMA!6 \nc`wGՐb-=׷nZKy3)Y9}OTrm0pÄ8K] Bn6k=Jj@z~^/Kޱ'Lޏ=wf۽^/n*52׮ ӹ,C<眉\t^ÊDŽ JZ!/զ0A!x-CR.4r`\n@~ a_&M,,Y2Cǜ\t\0m\0dONLi8p\n- Q]Uw۲9sh+ԕ(KpH2F]~:\\\\!2yS72sl|8M42/>Z>w;wo\n-V9],!WH=ٕt\0Ҫ͝'P_`:;J㖾Zi/q&5k5r⛭pY{IǍ8^ɇ^Q|?V"{ g d boc{ڌW@`k2~%p #ve*p\nK5Dcys~E'' VY|TQOWJ\0xLnV2Tb:<9gCl`Am@3==UqG"b&-;JhָmP)_}@ {Aip+Wey^{jGbm2C& 65+=W\00f3tgCHء^JtexC q}gz'V>LP %ȴVhA{`4ɛpܺpvT]F͌\nzxxfw:y_u&ajVk ]R+4->\tB+uն ^F̎wT ts\nEV9£uEg ӇN?\t/ͯQJdюz)ƭ 3Q6rV;dV>сTC1 r~H|\\I}bYZcVzXʓh~P\\a*;$[_*h|CFE~k_=_lΈJ/Q>"ٷƵ7¡|7y?A+onoNIŠAa,ViN|U (VK-k(TKylG(1tjƘpN4lZ}a7>¶AA̡PkYqKwngu'333^\nLѢ_C<&ܙkLdiϚYEgXQ\nLA[+O$4K~'86$yܽUTk.'iuW zN;kw~;w׫W vkއOt7zW5uWQPW\0=n@6.@V\\>1۬mySW7\t}YʎT7Z2)”,5z$Xfx6$'凝L'Tn*  o4:.B.>[f֫0rBy~5a[xz24Z\te_ǒ :-8Ts1E 't=G.)q#߯McԲbkk,j^ x"pOKMI9wh\tѿX\nWD\tةL4xl(""vۡ,y>up `S+%6% "8׵%^ ;NfI2 %%m.lmV'œ_IN4=NuҹCH^[R@f14Iܰ Azu>/Wf)7;96BF uNMNJ戓f%66;f2_ ҿYM$Ȳ\0 af2nKu\nvVI7)rHwY"5mAKAPjcW[|!+#{b!f*e?Z+rq(p*rv̳Ø_9cx:BVRLcz1i!rjF [&m|a40"Nnd%eQb#X5"fJ\\3ZL~3$V#ֶyu\\4ԸUH لjGBD%ŋn{@'J`Ffv`u*9G?t̂ȕn 0GL^|tO\t1f!NnzL\t[2bIE\0/s7OjrK@/gO\n`{L9!/1lKyyAmhw_*B.:=9L 8="O7ЭZAOf-ekMb~ih4B[.6#+\nb:Wc%%e<;u'a}{\0 EA4]S^O7Wa'skzǑYqzړֱPLyrz91]s F1eA)L-2Z%գ: GS m;\\'u,0_`+\0g>UWr/2|TYh)QF\tFLj8RZx#A7^}n%if& U|[Be 8TMAwryI稐 rk<[>Վ#l)jp+R);E_EҌZ+ڭ7@{J`8"Pm+NM!vYhI1ʗ-A8\nUrr6C|,2@j/d ڷ(U巋hGW{ԓicyұoRg܎bfL#W"dI+rRV{f盱 "Rr+,x\ts[26[v:%8$$Բw‚nC+;̏zYZClJ>ޟuבDjHO^}KoQѨ._'r\\`\0KvԍU s?jTq!`{0>lKW>;" :wO\\E<=v|,2u$f?S{e5E%<Ώ\n-RT{8vԾ~Uķ @\0cm3\nkot"6$|BrG_T%R(v=.b~scZbҋ2 nkm>{IKvN8ڥۧE* зP7+O3}^ HKOohz/R1 Q^OםSUGS=SA TT