pax_global_header00006660000000000000000000000064125641676030014524gustar00rootroot0000000000000052 comment=b662fca299b02407504319709c7b1c4f452cd280 prosody-modules-0.0~hg20150813.12ac88940fe3/000077500000000000000000000000001256416760300176315ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/.hgtags000066400000000000000000000000651256416760300211100ustar00rootroot000000000000002c07bcf56a36d6e74dc0f5422e89bd61f4d31239 0.8-diverge prosody-modules-0.0~hg20150813.12ac88940fe3/CONTRIBUTING000066400000000000000000000013311256416760300214610ustar00rootroot00000000000000Contributing ============ Guidelines for developers ------------------------- * Each module should be contained in a folder of its name (e.g. `mod_ping/mod_ping.lua`) * Each module should have a wiki page with a description, usage, configuration and todo sections (feel free to copy an existing one as a template) * Commit messages should begin with the name of the plugin they are for (e.g. `mod_ping: Set correct namespace on pongs`) Instructions on cloning the repository are at http://code.google.com/p/prosody-modules/source/checkout - if you have commit access you will also see a link on that page to view your Google Code password (not the same as your Google account password) to push your changes. prosody-modules-0.0~hg20150813.12ac88940fe3/COPYING000066400000000000000000000021561256416760300206700ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2009-2015 Various Contributors (see individual files and source control) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. prosody-modules-0.0~hg20150813.12ac88940fe3/README000066400000000000000000000026501256416760300205140ustar00rootroot00000000000000prosody-modules =============== *Add-on modules for Prosody IM Server* -------------------------------------------------------------------------- Community repository for non-core, unofficial and/or experimental plugins for [Prosody][]. If you are a developer and would like to host your Prosody module in this repository, or want to contribute to existing modules, simply introduce yourself and request commit access on our [mailing list][]. Notes for users ---------------- There are lots of fun and exciting modules to be found here, we know you'll like it. However please note that each module is in a different state of development. Some are proof-of-concept, others are quite stable and ready for production use. Be sure to read the wiki page of any module before installing it on your server. We are working on methods to easily download and install modules from this repository. In the meantime most modules are either a single file and easy to install, or contain installation instructions on their wiki page. You can browse the files stored in this repository at . Prosody 0.8x compatibility -------------------------- Due to a number of backwards-incompatible API changes in Prosody 0.9, prosody-modules for 0.8 are now maintained separately at . [Prosody]: http://prosody.im/ [mailing list]: http://prosody.im/discuss prosody-modules-0.0~hg20150813.12ac88940fe3/misc/000077500000000000000000000000001256416760300205645ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/misc/munin/000077500000000000000000000000001256416760300217125ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/misc/munin/prosody_.lua000066400000000000000000000064251256416760300242620ustar00rootroot00000000000000#!/usr/bin/env lua local print = print; local pairs = pairs; local socket = require"socket"; local stats = {}; stats.c2s = { graph_title = "Prosody C2S Connections"; graph_vlabel = "users"; graph_category = "Prosody"; all_client_connections = { label = "client connections"; _key = "total_c2s"; } } stats.s2s = { graph_title = "Prosody S2S Connections"; graph_vlabel = "servers"; graph_category = "Prosody"; outgoing_connections = { label = "outgoing connections"; _key = "total_s2sout"; }; incoming_connections = { label = "incoming connections"; _key = "total_s2sin"; } } stats.mem = { graph_title = "Prosody Memory Usage"; graph_vlabel = "Bytes"; graph_args = "--base 1024 -l 0"; graph_category = "Prosody"; --memory_unused graph_order = "memory_total memory_rss memory_allocated memory_used memory_lua memory_returnable"; memory_allocated = { label = "Allocated", draw = "AREA" }; memory_lua = { label = "Lua", draw = "AREA" }; memory_rss = { label = "RSS", draw = "AREA" }; memory_total = { label = "Total", draw = "AREA" }; -- memory_unused = { label = "Unused", draw = "AREA" }; memory_used = { label = "Used", draw = "AREA" }; memory_returnable = { label = "Returnable", draw = "AREA" }; } stats.cpu = { graph_title = "Prosody CPU Usage"; graph_category = "Prosody"; graph_args = "-l 0"; graph_vlabel = "CPU time used in milliseconds"; cpu_total = { label = "CPU"; type = "DERIVE"; min = 0; }; } stats.auth = { graph_title = "Prosody Authentications"; graph_category = "Prosody"; graph_args = "--base 1000"; c2s_auth = { label = "Logins"; type = "DERIVE"; min = 0; }; c2s_authfail = { label = "Failed logins"; type = "DERIVE"; min = 0; }; } local function onerror(msg, err, exit) io.stderr:write(msg, '\n'); if err then io.stderr:write(err, '\n'); end os.exit(exit or 1); end local function connect() local conn, err = socket.connect(os.getenv"host" or "localhost", os.getenv"port" or 5782); if not conn then onerror("Could not connect to prosody", err); end conn:settimeout(1); return conn; end local function get_config(item) for k,v in pairs(item) do if type(v) == "string" then print(k .. " " .. v); elseif type(v) == "table" then for sk,v in pairs(v) do if not sk:match("^_") then print(k.."."..sk.." "..v); end end end end end local function get_stats(item) local labels = {}; for key, val in pairs(item) do if type(val) == "table" and val.label then labels[val._key or key] = key; end end local conn = connect(); local line, err = conn:receive("*l"); local stat, value, label; while line and line ~= "" and next(labels) ~= nil do stat, value = line:match('^STAT%s+"([^"]*)"%s*(%b())'); label = stat and labels[stat]; if label then print(label..".value "..tonumber(value:sub(2,-2))); labels[stat] = nil; end line, err = conn:receive("*l"); end if err then onerror(err); end end local function main(stat, mode) if mode == "suggest" then for available_stat in pairs(stats) do print(available_stat); end elseif mode == "config" then return get_config(stats[stat]); elseif stats[stat] then return get_stats(stats[stat]); end end if arg then return main(arg[0]:match("prosody_(%w*)"), ...); end return { stats = stats, get_stats = get_stats, get_config = get_config, } prosody-modules-0.0~hg20150813.12ac88940fe3/mod_addressing/000077500000000000000000000000001256416760300226135ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_addressing/mod_addressing.lua000066400000000000000000000034411256416760300263020ustar00rootroot00000000000000-- TODO Querying other servers for support, needs to keep track of remote -- server disco features local xmlns_address = 'http://jabber.org/protocol/address'; local function handle_extended_addressing(data) local stanza = data.stanza; if stanza.attr.type == "error" then return -- so we don't process bounces end local orig_to = stanza.attr.to; local addresses = stanza:get_child("addresses", xmlns_address); if addresses then module:log("debug", "Extended addressing found"); local destinations = {}; addresses:maptags(function(address) if address.attr.xmlns == xmlns_address and address.name == "address" then local type, jid, delivered = address.attr.type, address.attr.jid, address.attr.delivered; if (type == "cc" or type == "bcc" or type == "to") and jid and not delivered then destinations[#destinations+1] = jid; module:log("debug", "%s to %s", type, jid) if type == "to" or type == "cc" then address.attr.delivered = "true"; return address; elseif type == "bcc" then return nil; end end end return address; -- unsupported stuff goes right back end); for i=1,#destinations do stanza.attr.to = destinations[i]; module:log("debug", "posting stanza to %s", destinations[i]) module:send(stanza); end stanza.attr.to = orig_to; return stanza.attr.to == module.host or nil; end end module:hook("message/host", handle_extended_addressing, 10); module:hook("message/bare", handle_extended_addressing, 10); module:hook("message/full", handle_extended_addressing, 10); module:hook("presence/host", handle_extended_addressing, 10); module:hook("presence/bare", handle_extended_addressing, 10); module:hook("presence/full", handle_extended_addressing, 10); -- IQ stanzas makes no sense module:add_feature(xmlns_address); prosody-modules-0.0~hg20150813.12ac88940fe3/mod_adhoc_account_management/000077500000000000000000000000001256416760300254565ustar00rootroot00000000000000mod_adhoc_account_management.lua000066400000000000000000000075711256416760300337410ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_adhoc_account_managementlocal dataforms_new = require "util.dataforms".new; local usermanager_set_password = require "core.usermanager".set_password; local usermanager_test_password = require "core.usermanager".test_password; local jid_split = require"util.jid".split; local close_others = module:get_option_boolean("close_sessions_on_password_change", true) local require_confirm = module:get_option_boolean("require_confirm_password", true) local require_current = module:get_option_boolean("require_current_password", true) local change_password_layout = { title = "Changing Your Password"; instructions = "Fill out this form to change a your password."; { -- This is meta name = "FORM_TYPE", type = "hidden", -- Reuses form type from XEP 77 value = "jabber:iq:register:changepassword", }; { name = "password", type = "text-private", required = true, label = "New Password", }; }; if require_confirm then table.insert(change_password_layout, { name = "password-confirm", type = "text-private", required = true, label = "Confirm new password", }); end if require_current then table.insert(change_password_layout, 2, { name = "password-current", type = "text-private", required = true, label = "Current password", }); end change_password_layout = dataforms_new(change_password_layout); function change_password_command_handler(self, data, state) if not state then -- New session, send the form return { status = "executing", actions = { "complete" }, form = change_password_layout }, true; else if data.action == "cancel" then return { status = "canceled" }; end -- Who are we talking to? local username, hostname = jid_split(data.from); if not username or hostname ~= module.host then return { status = "error", error = { type = "cancel", condition = "forbidden", message = "Invalid user or hostname." } }; end -- Extract data from the form local fields = change_password_layout:data(data.form); -- Validate if require_current then if not fields["password-current"] or #fields["password-current"] == 0 then return { status = "error", error = { type = "modify", condition = "bad-request", message = "Please enter your current password" } }; elseif not usermanager_test_password(username, hostname, fields["password-current"]) then return { status = "error", error = { type = "modify", condition = "bad-request", message = "Your current password was incorrect" } }; end end if require_confirm and fields["password-confirm"] ~= fields["password"] then return { status = "error", error = { type = "modify", condition = "bad-request", message = "New password didn't match the confirmation" } }; end if not fields.password or #fields.password == 0 then return { status = "error", error = { type = "modify", condition = "bad-request", message = "Please enter a new password" } }; end -- All is good, so change password. module:log("debug", "About to usermanager.set_password(%q, password, %q)", username, hostname); local ok, err = usermanager_set_password(username, fields.password, hostname); if ok then if close_others then for _, sess in pairs(hosts[hostname].sessions[username].sessions) do if sess.full_jid ~= data.from then sess:close{ condition = "reset", text = "Password changed" } end end end return { status = "completed", info = "Password successfully changed" }; else module:log("warn", "%s@%s could not change password: %s", username, hostname, tostring(err)); return { status = "error", error = { type = "cancel", condition = "internal-server-error", message = "Could not save new password: "..tostring(err) } }; end end end -- Feature requests? What could fit under account management? local adhoc_new = module:require "adhoc".new; local adhoc_passwd = adhoc_new("Change Password", "passwd", change_password_command_handler, "user"); module:add_item ("adhoc", adhoc_passwd); prosody-modules-0.0~hg20150813.12ac88940fe3/mod_adhoc_blacklist/000077500000000000000000000000001256416760300235765ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_adhoc_blacklist/mod_adhoc_blacklist.lua000066400000000000000000000047461256416760300302610ustar00rootroot00000000000000-- mod_adhoc_blacklist -- -- http://xmpp.org/extensions/xep-0133.html#edit-blacklist -- -- Copyright (C) 2015 Kim Alvefur -- -- This file is MIT/X11 licensed. -- module:depends("adhoc"); local adhoc = module:require "adhoc"; local st = require"util.stanza"; local set = require"util.set"; local dataform = require"util.dataforms"; local adhoc_inital_data = require "util.adhoc".new_initial_data_form; local blocklist_form = dataform.new { title = "Editing the Blacklist"; instructions = "Fill out this form to edit the list of entities with whom communications are disallowed."; { type = "hidden"; name = "FORM_TYPE"; value = "http://jabber.org/protocol/admin"; }; { type = "jid-multi"; name = "blacklistjids"; label = "The blacklist"; }; } local blocklists = module:open_store("blocklist"); local blocklist_handler = adhoc_inital_data(blocklist_form, function () local blacklistjids = {}; local blacklist = blocklists:get(); if blacklist then for jid in pairs(blacklist) do table.insert(blacklistjids, jid); end end return { blacklistjids = blacklistjids }; end, function(fields, form_err) if form_err then return { status = "completed", error = { message = "Problem in submitted form" } }; end local blacklistjids = set.new(fields.blacklistjids); local ok, err = blocklists:set(nil, blacklistjids._items); if ok then return { status = "completed", info = "Blacklist updated" }; else return { status = "completed", error = { message = "Error saving blacklist: "..err } }; end end); module:add_item("adhoc", adhoc.new("Edit Blacklist", "http://jabber.org/protocol/admin#edit-blacklist", blocklist_handler, "admin")); local function is_blocked(host) local blacklistjids = blocklists:get(); return blacklistjids and blacklistjids[host]; end module:hook("route/remote", function (event) local origin, stanza = event.origin, event.stanza; if is_blocked(event.to_host) then if origin and stanza then origin.send(st.error_reply(stanza, "cancel", "not-allowed", "Communication with this domain is not allowed")); return true; end return false; end end, 1000); module:hook("s2s-stream-features", function (event) local session = event.origin; if is_blocked(session.from_host) then session:close("policy-violation"); return false; end end, 1000); module:hook("stanza/http://etherx.jabber.org/streams:features", function (event) local session = event.origin; if is_blocked(session.to_host) then session:close("policy-violation"); return true; end end, 1000); prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_blocklist/000077500000000000000000000000001256416760300236265ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_blocklist/mod_admin_blocklist.lua000066400000000000000000000026561256416760300303370ustar00rootroot00000000000000-- mod_admin_blocklist -- -- If a local admin has blocked a domain, don't allow s2s to that domain -- -- Copyright (C) 2015 Kim Alvefur -- -- This file is MIT/X11 licensed. -- module:depends("blocklist"); local st = require"util.stanza"; local jid_split = require"util.jid".split; local admins = module:get_option_inherited_set("admins", {}) / function (admin) -- Filter out non-local admins local user, host = jid_split(admin); if host == module.host then return user; end end local blocklists = module:open_store("blocklist"); local function is_blocked(host) for admin in admins do local blocklist = blocklists:get(admin); if blocklist and blocklist[host] then return true; end end end module:hook("route/remote", function (event) local origin, stanza = event.origin, event.stanza; if is_blocked(event.to_host) then if origin and stanza then origin.send(st.error_reply(stanza, "cancel", "not-allowed", "Communication with this domain is not allowed")); return true; end return false; end end, 1000); module:hook("s2s-stream-features", function (event) local session = event.origin; if is_blocked(session.from_host) then session:close("policy-violation"); return false; end end, 1000); module:hook("stanza/http://etherx.jabber.org/streams:features", function (event) local session = event.origin; if is_blocked(session.to_host) then session:close("policy-violation"); return true; end end, 1000); prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_message/000077500000000000000000000000001256416760300232645ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_message/mod_admin_message.lua000066400000000000000000000073701256416760300274310ustar00rootroot00000000000000-- Prosody IM -- -- mod_admin_message -- Console-over-XMPP implementation. -- -- This module depends on Prosody's admin_telnet module -- -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain -- Copyright (C) 2012-2013 Mikael Berthe -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- local st = require "util.stanza"; local um_is_admin = require "core.usermanager".is_admin; local admin_telnet = module:depends("admin_telnet"); local telnet_def_env = module:shared("/*/admin_telnet/env"); local telnet_commands = module:shared("/*/admin_telnet/commands"); local default_env_mt = { __index = telnet_def_env }; local host = module.host; -- Create our own session. print() will store the results in a text -- string. send(), quit(), disconnect() are no-op. local function new_session () local session = { send = function () end; quit = function () end; disconnect = function () end; }; session.print = function (...) local t = {}; for i=1,select("#", ...) do t[i] = tostring(select(i, ...)); end local text = "| "..table.concat(t, "\t"); if session.fulltext then session.fulltext = session.fulltext .. "\n" .. text; else session.fulltext = text; end end session.env = setmetatable({}, default_env_mt); -- Load up environment with helper objects for name, t in pairs(telnet_def_env) do if type(t) == "table" then session.env[name] = setmetatable({ session = session }, { __index = t }); end end return session; end local function on_message(event) -- Check the type of the incoming stanza to avoid loops: if event.stanza.attr.type == "error" then return; -- We do not want to reply to these, so leave. end local userjid = event.stanza.attr.from; local bodytag = event.stanza:get_child("body"); local body = bodytag and bodytag:get_text() or ""; if not body or body == "" then -- We do not reply to empty messages (chatstates, etc.) return true; end -- Check the requester is an admin user if not um_is_admin(userjid, module.host) then module:log("info", "Ignored request from non-admin: %s", userjid); return; end -- Create a session in order to use an admin_telnet-like environment local session = new_session(); -- Process the message using admin_telnet's onincoming function admin_telnet.console:process_line(session, body.."\n"); -- Strip trailing blank line session.fulltext = tostring(session.fulltext):gsub("\n\|%s*$", "") -- Send the reply stanza local reply_stanza = st.message({ from = host, to = userjid, type = "chat" }); reply_stanza = reply_stanza:body(session.fulltext); module:send(reply_stanza); return true; end local function on_presence(event) local send_presence = false; local userjid = event.stanza.attr.from; -- Check the requester is an admin user if not um_is_admin(userjid, module.host) then module:log("info", "Ignored presence from non-admin: %s", userjid); return; end if (event.stanza.attr.type == "subscribe") then module:log("info", "Subscription request from %s", userjid); send_presence = true; -- Send a subscription ack local presence_stanza = st.presence({ from = host, to = userjid, type = "subscribed", id = event.stanza.attr.id }); module:send(presence_stanza); elseif (event.stanza.attr.type == "probe") then send_presence = true; elseif (event.stanza.attr.type == "unsubscribe") then -- For information only... module:log("info", "Unsubscription request from %s", userjid); end if (send_presence == true) then -- Send a presence stanza module:send(st.presence({ from = host, to = userjid })); end return true; end module:hook("message/bare", on_message); module:hook("presence/bare", on_presence); prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_probe/000077500000000000000000000000001256416760300227475ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_probe/mod_admin_probe.lua000066400000000000000000000017701256416760300265750ustar00rootroot00000000000000-- Prosody IM -- Copyright (C) 2014 Florian Zeitz -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- local presence = module:depends("presence"); local send_presence_of_available_resources = presence.send_presence_of_available_resources; local hosts = prosody.hosts; local core_post_stanza = prosody.core_post_stanza; local st = require "util.stanza"; local is_admin = require "core.usermanager".is_admin; local jid_split = require "util.jid".split; module:hook("presence/bare", function(data) local origin, stanza = data.origin, data.stanza; local to, from, type = stanza.attr.to, stanza.attr.from, stanza.attr.type; local node, host = jid_split(to); if type ~= "probe" then return; end if not is_admin(from, module.host) then return; end if 0 == send_presence_of_available_resources(node, host, from, origin) then core_post_stanza(hosts[host], st.presence({from=to, to=from, type="unavailable"}), true); end return true; end, 10); prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/000077500000000000000000000000001256416760300224155ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/000077500000000000000000000000001256416760300243425ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/get_deps.sh000077500000000000000000000015531256416760300264770ustar00rootroot00000000000000#!/bin/sh JQUERY_VERSION="1.10.2" STROPHE_VERSION="1.1.2" BOOTSTRAP_VERSION="1.4.0" ADHOC_COMMITISH="87bfedccdb91e2ff7cfb165e989e5259c155b513" cd www_files/js rm -f jquery-$JQUERY_VERSION.min.js wget http://code.jquery.com/jquery-$JQUERY_VERSION.min.js || exit 1 rm -f adhoc.js wget -O adhoc.js "http://git.babelmonkeys.de/?p=adhocweb.git;a=blob_plain;f=js/adhoc.js;hb=$ADHOC_COMMITISH" || exit 1 rm -f strophe.min.js wget https://raw.github.com/strophe/strophe.im/gh-pages/strophejs/downloads/strophejs-$STROPHE_VERSION.tar.gz && tar xzf strophejs-$STROPHE_VERSION.tar.gz strophejs-$STROPHE_VERSION/strophe.min.js --strip-components=1 && rm strophejs-$STROPHE_VERSION.tar.gz || exit 1 cd ../css rm -f bootstrap-$BOOTSTRAP_VERSION.min.css wget https://raw.github.com/twbs/bootstrap/v$BOOTSTRAP_VERSION/bootstrap.min.css -O bootstrap-$BOOTSTRAP_VERSION.min.css || exit 1 prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/mod_admin_web.lua000066400000000000000000000223211256416760300276310ustar00rootroot00000000000000-- Copyright (C) 2010 Florian Zeitz -- -- This file is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- -- -- -- -- -- -- -- / -- -- -- / -- local st = require "util.stanza"; local uuid_generate = require "util.uuid".generate; local is_admin = require "core.usermanager".is_admin; local pubsub = require "util.pubsub"; local jid_bare = require "util.jid".bare; local hosts = prosody.hosts; local incoming_s2s = prosody.incoming_s2s; module:set_global(); local service = {}; local xmlns_adminsub = "http://prosody.im/adminsub"; local xmlns_c2s_session = "http://prosody.im/streams/c2s"; local xmlns_s2s_session = "http://prosody.im/streams/s2s"; local idmap = {}; local function add_client(session, host) local name = session.full_jid; local id = idmap[name]; if not id then id = uuid_generate(); idmap[name] = id; end local item = st.stanza("item", { id = id }):tag("session", {xmlns = xmlns_c2s_session, jid = name}):up(); if session.secure then local encrypted = item:tag("encrypted"); local sock = session.conn and session.conn.socket and session.conn:socket() local info = sock and sock.info and sock:info(); for k, v in pairs(info or {}) do encrypted:tag("info", { name = k }):text(tostring(v)):up(); end end if session.compressed then item:tag("compressed"):up(); end service[host]:publish(xmlns_c2s_session, host, id, item); module:log("debug", "Added client " .. name); end local function del_client(session, host) local name = session.full_jid; local id = idmap[name]; if id then local notifier = st.stanza("retract", { id = id }); service[host]:retract(xmlns_c2s_session, host, id, notifier); end end local function add_host(session, type, host) local name = (type == "out" and session.to_host) or (type == "in" and session.from_host); local id = idmap[name.."_"..type]; if not id then id = uuid_generate(); idmap[name.."_"..type] = id; end local item = st.stanza("item", { id = id }):tag("session", {xmlns = xmlns_s2s_session, jid = name}) :tag(type):up(); if session.secure then local encrypted = item:tag("encrypted"); local sock = session.conn and session.conn.socket and session.conn:socket() local info = sock and sock.info and sock:info(); for k, v in pairs(info or {}) do encrypted:tag("info", { name = k }):text(tostring(v)):up(); end if session.cert_identity_status == "valid" then encrypted:tag("valid"); else encrypted:tag("invalid"); end end if session.compressed then item:tag("compressed"):up(); end service[host]:publish(xmlns_s2s_session, host, id, item); module:log("debug", "Added host " .. name .. " s2s" .. type); end local function del_host(session, type, host) local name = (type == "out" and session.to_host) or (type == "in" and session.from_host); local id = idmap[name.."_"..type]; if id then local notifier = st.stanza("retract", { id = id }); service[host]:retract(xmlns_s2s_session, host, id, notifier); end end local function get_affiliation(jid, host) local bare_jid = jid_bare(jid); if is_admin(bare_jid, host) then return "member"; else return "none"; end end function module.add_host(module) -- Dependencies module:depends("bosh"); module:depends("admin_adhoc"); module:depends("http"); local serve_file = module:depends("http_files").serve { path = module:get_directory() .. "/www_files"; }; -- Setup HTTP server module:provides("http", { name = "admin"; route = { ["GET"] = function(event) event.response.headers.location = event.request.path .. "/"; return 301; end; ["GET /*"] = serve_file; } }); -- Setup adminsub service local function simple_broadcast(kind, node, jids, item) if item then item = st.clone(item); item.attr.xmlns = nil; -- Clear the pubsub namespace end local message = st.message({ from = module.host, type = "headline" }) :tag("event", { xmlns = xmlns_adminsub .. "#event" }) :tag(kind, { node = node }) :add_child(item); for jid in pairs(jids) do module:log("debug", "Sending notification to %s", jid); message.attr.to = jid; module:send(message); end end service[module.host] = pubsub.new({ broadcaster = simple_broadcast; normalize_jid = jid_bare; get_affiliation = function(jid) return get_affiliation(jid, module.host) end; capabilities = { member = { create = false; publish = false; retract = false; get_nodes = true; subscribe = true; unsubscribe = true; get_subscription = true; get_subscriptions = true; get_items = true; subscribe_other = false; unsubscribe_other = false; get_subscription_other = false; get_subscriptions_other = false; be_subscribed = true; be_unsubscribed = true; set_affiliation = false; }; owner = { create = true; publish = true; retract = true; get_nodes = true; subscribe = true; unsubscribe = true; get_subscription = true; get_subscriptions = true; get_items = true; subscribe_other = true; unsubscribe_other = true; get_subscription_other = true; get_subscriptions_other = true; be_subscribed = true; be_unsubscribed = true; set_affiliation = true; }; }; }); -- Create node for s2s sessions local ok, err = service[module.host]:create(xmlns_s2s_session, true); if not ok then module:log("warn", "Could not create node " .. xmlns_s2s_session .. ": " .. tostring(err)); else service[module.host]:set_affiliation(xmlns_s2s_session, true, module.host, "owner") end -- Add outgoing s2s sessions for _, session in pairs(hosts[module.host].s2sout) do if session.type ~= "s2sout_unauthed" then add_host(session, "out", module.host); end end -- Add incomming s2s sessions for session in pairs(incoming_s2s) do if session.to_host == module.host then add_host(session, "in", module.host); end end -- Create node for c2s sessions ok, err = service[module.host]:create(xmlns_c2s_session, true); if not ok then module:log("warn", "Could not create node " .. xmlns_c2s_session .. ": " .. tostring(err)); else service[module.host]:set_affiliation(xmlns_c2s_session, true, module.host, "owner") end -- Add c2s sessions for _, user in pairs(hosts[module.host].sessions or {}) do for _, session in pairs(user.sessions or {}) do add_client(session, module.host); end end -- Register adminsub handler module:hook("iq/host/http://prosody.im/adminsub:adminsub", function(event) local origin, stanza = event.origin, event.stanza; local adminsub = stanza.tags[1]; local action = adminsub.tags[1]; local reply; if action.name == "subscribe" then local ok, ret = service[module.host]:add_subscription(action.attr.node, stanza.attr.from, stanza.attr.from); if ok then reply = st.reply(stanza) :tag("adminsub", { xmlns = xmlns_adminsub }); else reply = st.error_reply(stanza, "cancel", ret); end elseif action.name == "unsubscribe" then local ok, ret = service[module.host]:remove_subscription(action.attr.node, stanza.attr.from, stanza.attr.from); if ok then reply = st.reply(stanza) :tag("adminsub", { xmlns = xmlns_adminsub }); else reply = st.error_reply(stanza, "cancel", ret); end elseif action.name == "items" then local node = action.attr.node; local ok, ret = service[module.host]:get_items(node, stanza.attr.from); if not ok then return origin.send(st.error_reply(stanza, "cancel", ret)); end local data = st.stanza("items", { node = node }); for _, entry in pairs(ret) do data:add_child(entry); end if data then reply = st.reply(stanza) :tag("adminsub", { xmlns = xmlns_adminsub }) :add_child(data); else reply = st.error_reply(stanza, "cancel", "item-not-found"); end elseif action.name == "adminfor" then local data = st.stanza("adminfor"); for host_name in pairs(hosts) do if is_admin(stanza.attr.from, host_name) then data:tag("item"):text(host_name):up(); end end reply = st.reply(stanza) :tag("adminsub", { xmlns = xmlns_adminsub }) :add_child(data); else reply = st.error_reply(stanza, "feature-not-implemented"); end return origin.send(reply); end); -- Add/remove c2s sessions module:hook("resource-bind", function(event) add_client(event.session, module.host); end); module:hook("resource-unbind", function(event) del_client(event.session, module.host); service[module.host]:remove_subscription(xmlns_c2s_session, module.host, event.session.full_jid); service[module.host]:remove_subscription(xmlns_s2s_session, module.host, event.session.full_jid); end); -- Add/remove s2s sessions module:hook("s2sout-established", function(event) add_host(event.session, "out", module.host); end); module:hook("s2sin-established", function(event) add_host(event.session, "in", module.host); end); module:hook("s2sout-destroyed", function(event) del_host(event.session, "out", module.host); end); module:hook("s2sin-destroyed", function(event) del_host(event.session, "in", module.host); end); end prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/000077500000000000000000000000001256416760300263505ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/css/000077500000000000000000000000001256416760300271405ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/css/style.css000066400000000000000000000023551256416760300310170ustar00rootroot00000000000000body { margin: 0 } a { color: #0000FF } #adhocCommands > ul { margin: 0 } .btn { margin-right: 0.3em } .btn:last-child { margin-right: 0 } #log_container { clear: both; display: none } #adhocCommands { border-right: solid 1px } #adhocCommands li { list-style: inside } #login { float: left; margin: 1em 2em 0 1em; padding-right: 1em; border: solid 1px; background: #eef0f2; color: #000000 } #main { display: none; margin: 1em } #main p { margin: 0 } #top { clear: both; width: 100%; padding: 0; } @media screen and (min-width: 757px) { #header { background: url(../images/blue_orange.png) repeat-x } } #header img { max-width: 100%; height: auto } #menu { display: none; color: #454748; font-size: 1.1em; background: #eef0f2; width: 100%; } #menu ul { display: inline; list-style-type: none; margin: 0; padding: 0.5em 0 } #menu li { display: inline; padding: 0 0.5em } #menu a { color: #454748; text-decoration: none } #menu li a:hover { color: #6197DF; text-decoration: underline } #selector { display: inline-block } #s2sList h2, #c2sList h2 { color: #4b8ade; margin: 0 } #s2sList li, #c2sList li { cursor: pointer } #host { margin: 0.25em; } prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/images/000077500000000000000000000000001256416760300276155ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/images/blue_orange.png000066400000000000000000000002361256416760300326060ustar00rootroot00000000000000PNG  IHDRZW bKGD pHYs  tIME 84 7i+IDAT(cH~?(1J ?"O[ Ll2#7R4 rmIENDB`prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/images/compressed.png000066400000000000000000000012671256416760300324750ustar00rootroot00000000000000PNG  IHDRĴl;bKGDC pHYs B(xtIME %DIDAT8kSA;1IR#>6R|TܸB+%+_ )(k1;.taQ"颭 -h+ZbwEThN ^|@Ypt'ZZ#7%F{p+ 3Xf(ٯ(rҲp ru) eJZQ.9NvCH'9?S`Fڡ*nm(;p/ `~n7`4h\1Z}*8zB06Rx3/+mGM.vY0U- Zjݮ/21gcn)Zdcʬ~d">ߠm@d{S`G"@$+KV>;mli1d!W*8t %sn+Va kX] 8@+@mo6 ׶cIENDB`prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/images/encrypted.png000066400000000000000000000022751256416760300323260ustar00rootroot00000000000000PNG  IHDRĴl;sRGBbKGD pHYs B(xtIME 4 =IDAT8˵[h\E3mc 5i6QHlMZ-O>(R(@K  Mb4ݘKUvd}sa7k|o} ?r'JmmoŲ̆CTkk{$.E[P? BNgKKνۻ)O:zu|fYࠎpLD"Q`_~áHj MME[lۂ5(E[@!O$:7`uop 4og_>b|wKm-#)m$9 |¶$O |֑iߑ !#HVO'=oZ+_nӫ,c !ŶHR|o8v!}!< 8{ {ٹ]M$x;Ю$agbIOA$E[Zm B}3$=&^pNۚC VH7D(v6t y $# G`Ql7ӄ}CVup^ gZ5Tr;_ EmtQmiJn^OئJ>ފZ"BM[Ft/Wb5 %*u*NIUA`Y*Z=I$<7ոqA|zq@aslKtFz}R-v-A<x_xZa"xY!*pzf ۖ9yvۯPU貶53H:+gA88")zv鋛DRU,CA i=b j^_:W-?uVЮE Z $yyek$g/7g,=L[AN= Ȋjsnz/_p@&8zF p3{*۔8{}wN0*j!+g plX_L]h#U$iЮ0 +Ȫŝޣ%iu%>@R>YbFP\hj.$fCEo)z4U<ϴPBrG^2cjzz56?<`<ţpBtVj+bXZ(ٖ2(spl 67>sGV Qiض@Vm$k١UUA(j")~ၝ"/zfy`aі{GHN3!KPC68`YY \H@X:y}|B߃K򮆟K8vSS +p"8VKcou{ ]ՄƶnM<= lܙ?F3]$L¶Cc*T̄MؖvH.82=+[vmɿ7&m 5XtO9XFYhVVFb\ؘzO-fr.Z}RzmF1plGtv8L6b%jevoP:QV f7c6UgT.)oR8ܦt$3mʪN-m4;:ܼ'<䭦LHRo-,CEkD<ICd5}`7,SM3+Y^nЮG<Ȝ^g*ajq{YoӬDJI69z>33+%z+5l'3ئjؠUL\@DG ~]&YP%oA(QDurF8m]ZW26j/&0zNkriL}=|2iz9x圿Q4/kij]F)0brg4?4A6K8?)Ggr4DӐx8R^)\̼ۜpı8>u&RgwůG _ _Ӫޚlo¤YN_`x1B2澘 JmHymS9Z}a:DgЮ-a߽em92sD6+'4J+#&dG mZ4 :F;,K85‰jvdUgSV`鋏-.ȊmȪegZgL]v$3[}!mҮGI^!vE8Dbn @V,GKɾrzZroMRǼ}plhkb0r/2n ےX\Wٛ(Y- VJȌzK&qfcM^Qy͵ \I콧㬱i_2h e7>sSf*,O8a?d4;Ʃ F,^$9Tsbc9 ֔tìm,,;S9z;w:^[@q;wYSaV6|}I e<a#D !!~R лlc,sX컯Ɇ I0w@UÔ!ed&nz 4JI w)jM ҢK{c/4 >d{] 7PC:'ϷU?`-Skh"yrJtlmeO޼.rKj^yDR:͊ٝxlR8 {b2-Ic-$}dWFսS$$pT*NaB!:w1"z ^OmmFH|cyw'M)Ԏu6z$WPC[yܬ{`'dmahSR²e7q&z p#XzY#c[@n0O1Y{ҏZclQ%‰ꅏ14@MVX?0?]_Kŭ+yP*Xnz{ZEG":sH4=ћ)_PfeD0RAkC2@|Za@H,$dfyŶ$Šv"Jzz{ePT-V1Ud6hՆ@.~N$Y'?dtHmL`Apz{nBd6!Iv%L-ֈx:McFZ~v(VX,#IՉ${kW(A7hUǏlxś9w'Ys剞,lg|\(&[x{\-,8{5%fsQְL d석w2eJҗՇ9x=N@.g낽ϓͯ.~V50hѪ=8ԨFO s!9l~Zdّl^rM(nuwg)fY74Ȥ'/\v^R.2RL%7fFq;=&~}pw&^ls׽ c["`ch-H9v8NϓS m%<&#r2±=󎏾dB(PiM0v}>h-M&P~}UZ%P2⤖t'q͆K>^ jcs:-^;@F]L9c^qN85IPͭ{*dV%YkDVupl9L}8HN.QX:D,#tL-@<}I.P>_lyl~=r/ՇO9}qۜ~&~Dp!lKRI(,z0g6K8{yc$pFZh ҝp8}Jy%h`jl+lKͷ|}k^bh3^;(APM-蹭/8}od7NUgQٸ'M '\d7wpovP SW9/,PK[UްAz#ѓMյ_'s26/t] 68{5r ŚdWa ;rD1[3vKZ,!Y;~jS̙lӗh쮫r4 yAgS|Ʉf6Jh`F>Tqc*۟aW\pcp+82bv-j=M,ݦr{퓥h4J.GD»ߝ<_-#Q|"ewЪ,߭ݍnP,jӮ+#ZG#޳CQm>^g(Ցݼ]p6&p D:Kij".}hsBcSG91=fY$̍6JRzx1\gHJr`;;D"+E,c >Ijؓ3v}'+ml;8Qp;x 'vGEq%PtTmVmj˜J.268VV4l+WQ}&ˡէwYR HUeSy`Bd7xK_?Bjv`H qB2Zj1yfK& -Q/tҏ.#4B"siG~8hIy)Kw^r +&ے:"HsylKQLy8F4JuDmpl=ՐF"SХb E6[A{q˗=5\2%nΤ7hQg=_Ki=ҜI;Y0'_\~]|lVQgWNߓ(S/Fh9"CfLn?l&\4.3T%XC hGLhqd‰>VEM RBoL?XݣH#qzo{Q =h-EH-Qͮ*q/К"$[{?5b" ^,wH(EkN|ZxBbL~(n\|%XЦWuFRcu׬j[y  xϨ\lbwlU ǑbC2љ,F;B:j#SٕRYy:jY5ūԋwO$8!ZÇ E B8} |0uщ̮R:Y H,_P: ww8X iBNI]pep>&xdI5m|5d|9 NfSÁ#34Jo/dţH@Xg){-1xR(:=Kl|r̫:8g/m 1Wx+Orޣ+9v'@V o8}fo}z 51נ.ېb#+=ΐ]azvJ'AZ~2EI_~ ѐ0l58~B ];Br*E59 \,7zG)\S@k- gpf-i$>|X>\zYXzy'6uy. IDAT=hW%*J`)14]A cj#+%> y%QzWW,-W`ʿ:1BO4hbh3HJ ]x jDآPuL=:YtI{D`3U1B 4;aM‰sՅ>#,z+W;қĜw!Y$ټ31;cjvЃl8!PB]Oؖr{7TWFf駓?I9x2S+dF8*9Nxzgefk+pHh=.hV⴪wSԋ N6YXuCh^잫o8}/~W/Ty}' a &ﳍOӮ6d[qfR:M㧋}De}ޣ+0mQ/^=:QiWNZN}cڧLF@fJnaJIM9tmmS rG?ϵ? ; [NcS_^=c JzA"ܳGϬ)qPa@t_31t{W7H֣49&o  a GБa`Ud˘.'{8Vr: H5d @~Ag*譄d7n [FRRrO9r1I$Y@ 5fWê`d 'QN3[!C-?O$UUMvrۄUZBV ?z1έ1cPz}gjC4L=2b9kPN Omb.g/|}Kog$b9\3K}oiћ})XzeZ $;|BhH)U鍭^9D }kºFc)'\Iay냥2(~7==.O]"W95 j]gQUs?P:gߧʊæz+ݣ|>2ka;2s@N0ꦴ[)h ²2#;INzWv7 7D9Z XҪv'?"uBZ#ֈ?];UdmIy-~ZZaۖЛ""ռJ-2vj@u\ٞzL.f38 ~{r]=UҪs -ecYpՇ;z`,4˱8^%`OW6Xpk#/>O(f1'SЪd!94 S&7>? z∣'}Vt>.nfo֛`T'1 75PYjYdb5ǁLf98j7`,_~WC]ҟ9BjEc=lN^'!w}8F$+3r3@ݬ-8}8 ~KǙ=@²|elgX& ls:{Txh +8V)c[Hrvwy5ׇIr5E;5{M iק;J=7*_#:B26AVT.?=VV(zsSd{VO'@I668pzOzI.𭣿^EjU[2SS5WmO0g_"[}p [WU,TVdUgS‰2Z=FPpX8`Ϩ6>P-(.ʽ71z+Ȫ ]r҇yL=2Q{I6ƶTO!1wEhsH^ YyCdS (vsgo5'*kIP>w6Z#6fqYoY5JWwު03-J'a{qrRd\7758FH/ѻ8s611K/){> m+:@Q {TG ?Go~͑{ %p|ee^3JaOƯfUjSv:Ŝn:DQzK3?Q:_[RX>H[3_\<.'NqODmUI,0Ջ2uy|A6Dv" k4Jl[,sB<@|a8LhuhNkgN ƤP+ʃPS R:Y'R.~oeCYcbmZ ;5ѼKuVN!x'c7M/ W;\?];4Ja%+cz}1CLcЅT2 }o W@4+ pò4g}{ ڍ/n‰*1i,-#Jt`~j` CK Z33doh=ߡD$˹`${r5w jI$UX;I^sFqȊA 5if@Yh1ob!zs;xyٕ/Ojz)Ct@rdwu+%Cw)9n˧>>e$Q]1yD`I0;FZhpMgv{}ce7pl1҉a{_`jH'i()3ɬ_\(rt>/,:߿dJz#љʃSJ')0s[Oͥ6,jI)υ_]љ۾۔j:j`ۢWf)?/^ҝg;ɥbSd|7;'&*klZpک'uQc=Vgn_׊U7+T[!῝sMHJhWyՠ!jp*N8fCKmU }{@E?!nv@N X ǹJW} O*Latb˓w\5?Xzq T#}_!5! tfBn&iEg~Qz^nqg~BV"ʟ>%Y *lz-N%6+j;ǣ3f*}eFr9YYB 4`GNHw~.ɦ' S/, IO!$mY75.q/F;LFH F\{QNgn6EH6$EdV5FtL쬍VIX|]^9+?oЬGP-Xp/:^J|7$-:r1C6jHg1o ><%lo^+R"U K;7{֓&rE@QM,C&6d^z̮T%S]o nHBU ^/a>`Ը*K85T_Gǔހ//aa f<\'#XY}P"yW_zXm@-yԽ4ñ俣b' OqW;dSG0K/DI>Lv#q \27<&N! 4V5ґCHmZIrNJ80P1 >2]%X`hj- *'hWyb駔N 0>#[_|M_ wEM@y`H0ZIPm;z:x4sGbe>נ|v8-Z߼Тѕ2i8z!2|M.qA-?9鶟 }?)|]t9QmUGF y}PCCm xgFK&7t銥ާ.߫r">>TRm,_JMF * @& :sH௽‰3$E2B뙫zqR DzkTpE0>'հ;ؙLc9ir$GISje^ 0@hX'+DS%}6 HnM9*4+ f)-\ұ\!xDx "*œE_;JP*`!?XיfWsg1=@mb kv7CAlFvw+v;N_L,$~<=ogP6Wj4_;qb/s.ۯڇ>YU vF\Vm=V XD<Ӣ^_u7Ɠd!VHl|4+~ONFkDfY.~X$;:)hUUoAxw|1# 8,B!c Qq~crgeelj$)m!"Ԫ8VINBX=8OYzm%ǰ^O,ؖϔJ;8{ӝ=$CHrˌN]fb+r|>Yz%T][~VN?jZo/#md=XQZ'u[^,6M,crJ _TM+qᦩVњ}6y}4s3gL@v`+їޝ,V?]KG,u -0tSX,śm_Zv~hNhbȊyFN8yLt';*i%Tf9> nsֈ$o*Ǯl>ܥKZ*؟SW=b^۫C^z^/P:e`,@bBo~L564[̉X&,@A6SjҗxwK%䤿v2Ogh8z![T]Y} - /[tA2r1?kҮź7jdS+C^ۇ4 *}Բuࣩn<TY5Yuśes~1yVZ~`k /}ZCA`%7t'+g $U:)G,Ҫz=gkkAڵ $C3ȪeJcouJr YUa)zKa9cSG$Zae)WZ  -yG@zB;"G:"c=yS5gJ),j;]Z}./LawWKY>00d/@/߫`Y #|\ökD Ao?`±c3{vN*ul+lP'JZ״e7J'&a7ä agiV;x>5܏,S*}Tє F;Nb5)dLu0S \Ao94Rqߜ"Uf5(&ı%:z+6 3DR9d@H<K @ފU> S5 Ici0܍]?ԓW/~{jn'huqYgQ;XIkw 6zs>k: >:v-K|9̍_o}+T2%kvص|J|  IDAT)RX,,G$[3#ֺguBqn̔" pM෿>Dti"Mw,Ӣtٝɾŕ ga1dm n}şFz֪ޖ۬S<)b0u`Ķ{xԈz!ꥠ7yY? ; ;xH(Tepfz~k1OoY@PbYkHrۚCH5\2u8'uբ u@s'NB*g[U]F~`ݧt4u&<65Vֈe`34˷ʟ(~m}vUC\C 4i=f:XbY$YQ^'uXpfe 0$/hVc`sДtfhS3,KΨK̟`!‰"[DRy崏qYUM=PU2;4+3ئBtuò6?ے9|27)GONUX'Q zn:(hǖ(M{W5$$,ݧxȌsʙqβGߙ$*-p8{o{?+4F :tI-ܣtt<܎eYz[=Y?R%0s>љRC_i}FG+/ 7 K;3ؘ}j*WQgmyF_tr3lKI>˳SzrL$i[a1YeCʏ^֏c(П?u%uf &3#})QAl"egg;{fZDJA޻o.w 32"}?V*X!Ǡt|q1n5H=u𱿩hKr' 4-4V`ghx =@9iv`/aսʃ~P{Tq1 (B2okFC0|6dBPbǐ;eDʟ;-h9/}45:N]թ%VAxjl_7 XbcϒY,}zk,_pLUd7h:PvvyI)@?Mb:h7$(Y;:t5ES^nO~Fb Um%ve1U5Udh$F'qS{V$avެju$Vhfs%6pWopmhŇ4qʝ[ZXt*Io6{Xn \5d*YlcOPxir+(x<>O3tgwhP%OJ8 ri R3!g+M ;;Dӽ*81Evb=bXVF)c S' P h`BX5UA";q˫*] ,}| @a[)Ԧ$6=sԆ!P>#c an,>O`YG0"-O|.Nbg''A(,W/I KO +p\Ծ P*25Q`chgEѭ:I} VP ]2R[{հ KR -X1+H}f^!O^=n7WIt5ݡ& t-J<ƲI,@$YA (0tn!QPaޫ៛ شEDEV?[Jŋ d b3V5[ ``5!Y޻ԉ[o(#O֡JYs=FSm U [ytqw|<%]/>B9A_]rve 譾M(fr&km/cM|lZo}qe%">GoZɳ)"Ú0ME{x|e669sӱӸ#ڝ& W P%U˙xwh{]vqq|qSk] 9wrdzWm@+a @ǭfћc@~`ai1G0oOq @zCOYu%iD!w>N'u=alB Cp& -1CN`?Sr`ST,m|F7f'. 5ʦVi^&@r4gā=>S),vߓ):Zz*#2zlC? fM4{'51ԱtݚwfI?h KmB{;O~|hj jrFJ@nG7H".P=[g(͗Lל3M2MxG"G3` YES4)JWỻ{ONvY9(a9@,CpcOP%roJ<6XɱP[4`D?m۬ofhlё\r* ow5* ;ϊTk>~ S' &JI{-ßWQ'@~V2>%2I TzO|Y"Pz gziI?ؿa@?/_=h@Dz$PL/ @1)"ʠt>@.Ý46߅ >L3L , MЃ/Yz >ngCGPLiYSObs3=="n<Д٫x9L3v3gP;G \F]t[P)XrgJ. Ĥ̆:mZg` T|yғWu(){T 'J5[K +[`˞q&rsT$V..# TA#۷] .(Ct棟I{a'ak$l>=t0܃(?qگѭ-96z}upAuvU֠kl`ah~z~E֣SnO|=DũMPJ./P]fta'}ӯo!.#SPH -2k%˙8Ytplhkwk,!D0R 2\ŦN9{mx0ijllWp3os@X[Gx@4#&v>m_XA޳:NL P @>T6 e1IC5zO ֟oxi"jhaW0ҋT&hŶ?8HO [v~ 'zP3#L@tf"N YCO- --,^)؇LY YJɱ[B8qn>ty,b6T)Ћ0te|C=oٍZc\sN^Z*% ċCP𤷓xoL'UtL@3's$6 ۷DS%PLcy5jM}YXZY'uU,m\viFʓ1tz)b Ξ?ő&ĆD^."{» (U'l(ǁ3 :,kf N8E9KPJQA0,tiWL#2BqqFOY@SxDSm=\u_; jQ?h{ݹpB(텂Hl|҇elK5L؎'EqyFKoE]GjE%R w PjvM]N4L  ͠kPb K82vL&[TN +Q#?hmFQkoA$bpZ^n}> k P$1\!@Ot~d74>j)_,=Q9㉱VD±ru} |7$ݗu~{3̯ öU ]]{ st5KO+v!@-k +B6sYe WhPJ_o?q[Op0#KυZДX,}d Rg}y UJ铡ejXNXzjo@ZYh3Aj Jߧ.B6-=aLĖsXLUޅ7w/ :WO4Nv>* ȿ]~ ա\wT" FԻ 'š5V;FpA+˭GGȽ"+M)ONpb_]?~M<=?)N6{y.|u r(f` ꗉ!{NHC KPwJ: bi /]AW@M]??AY ZXC?d=+Ȓ˽C1 R "k8tgTC=Tx)L:탛ֱnЏG @@p X;knMňtJ]zDhc4* ,wL4>_5Tea9@ I0[0lbw>؀Dr,ad <OԩЭ`Jw8at!\BH]( s6E{8Z]b?"}v; n@=!&Г> 4J[kBm[No9Wm=rPvc\A)񝰚XDlQ8@,]DO2ć$JcRDv@#h<Ɯ,(akoClVH!c>皉op0&`6ǒcss]Ht!U 4X.nmqɇT.4"vbVg5.r:A*/`xg :Kɋ0؀V11殇{=C4%$:‰@= ̩@0L +4m.аu‰w0-{,۷,|o|NauYBW8kckUQ:+`y #m( I[Pvc 2. l\i񥏥 n,".BlahI4]Le9͵w h<}$+^jgCVo-BOn%-b oq rKm#f~:Zc}c\v8^Gv»}w._b9T1?[_';Nqb{nq?וݧǞp},Wцij,7faIpg(}HU̻Y@YgW]R CgFŝ<(f$tk0Zi 72Ƚ^64\_ֽ?Oל6G1Oͭk6X}󴎳ɚ^uy@l4_ B_1iCH@ZR@cHv3lHe7d±x ]yh`a` mӃ[|?Aa;@_{b< -D&[4'BNEM^1X3 "W2-&!W/Hdz@$un`t,sDR%BL..; doЭgP>ASd۽g?BP|g7Nj2HmPXߎYP"v:e^V8rp +غf}& /7Q̎>|wo&~Ұ|+sؙoz[uɵz/޸&PI$N]d(ar,ީ!owl$eb*5<!JG|7Q { h6қAѦG5^!Veŋ4Z%tPЭ?{W=7,ox~KӍNa)`Djܬ"㒻@nԏڤ<_+;j %Ǚ'n` ?7O?zV~􃅲¶u [ip+օ1' Hn,0 ӈ*N245ZfOdp"X BW4*Am\esB?&FAn'c`z2p coѮ鿋Tqao#-]PE8Z}{ulm0N=q!3 'Ge+S$BЮ0r™ga0N`A(=-0.,=/n|g_ 5`mi̜X QD32e/FA^u1@8Yp ֓.IBXFA"l=ޞGNFVALo}Wݘguu>7K?SFuXq.p 5AvF}TwPMmh:Bџ uM&1Зޘ@?AWSPz% CH0(ѭ?]~h`a9^ )-!^@ݯ #kt(˖V]>eȝ/˩c[wll e PzaQj4?K wA]G_ЭgN6J}z=X?>]x7wO3Βk 3ve,uiE4 3.l?=GԎߩ>r+ݹD>?DxC|{'s&fv-P.OYHxEƵB\ƃ2ꗉa(3ˈ=@jw8\GбBq8iՑ :B8ėy#?3:k1sȽYB#qY_ͻm.`WUCo PD$4i0}V޼U {;?O}9Der>bɛYGq  w jA%>kԳ0 7O.L $7VT1SI!=Fۀ'&O`d76f,, "9&p bTXR-)@]~*aٟ}phޤ-7؋*1O!@(zxTs~=,.Gt 3z*ּ@cjbKz`8 b?H F;P1 ='V PzQ)H\0]YzB(v^=~?xBo|PAz[s|O[@KIE IDATU˷.P>ߪaNp /{ .3"kutj1x3!Q=sj\@~wuVQ/ RKXpMi#_vA5;桫,i0`8 cB&ߜrD2n32 7Ǜ1 p],41@C8*4ut~bN ΧiL9Ͻ]on}YE8n۟4Q: aeN-.hBSY7fAa_v36DLB@ǽG =!Xߧar LHxry*!h4YzB`؊Ϫt&0"D˕`h;`Hr;ll+'XM>„(>V BH| U:l|N{Ӏ_{8bb\iX.?u^4.@j︌_VbB:AWzo,/! 4!LSsѴUAlnЃ""LC>zPeN-=é0\j#":P3dz_hGk|b6ߚ+5.mӁ's@8O\槷T*lb!.^>* s'#.6_@Nv&ǩ B(̾<'Cx' ٟ v,7y*uh oX Sj$ONqbٽ"X@yz˗۞nR俯e,E3?P:rug} CHhhB^0E3&>P  G-ڍLXJ'ѧ@ 7 C2(1t-6ҟҭ3]Pn,={S04zl mYB4,v_O/a؀zKC< =` @bwpO'dž.+:A 1|3Ebפ^ tͼD>S[F A(704a,x\%~AȲOuXifIT wRW*N@jr7 M +|Ԗ~fKWJa7=0&=G‰|nbk UU}ׇb' U Z4V.P  ̑솔A͏kM w JJtas` }a낚>)tu$t@EO/LP{Oluw.9(#y\g*H`.L=6,Rg> M8R&+4B`XAl@2+hr JqWb >@˝UH ,-$BW!^^<6 tJ1qgԅ18x3?5<+ n}ywc)W=e@ɵE!ۨ8l fMױ)٧n?yl, HT*eڄg+`y6O$; Y jr²N2u +y7!.]N`)ڥ$e.B_/s(fݣ. yr>.KkXW =lshb&I ! ^={Vuhoh>>:[l?dL|H3/ 3D ,ڭǚD&j_WqKrhYܫKPoYk2 c-\B== n 70ɪ@~97.H_~C0jZ.7 AmYz wˏa0 ₯a˖=A02_5 DW \P 4"K%+"4E6d z ;ܞkQ(yCl:TtOZ\@ ||Qw |,O H@XB3?߸ FDȽ%}2Yz!ޅԉ PXrgGȽ²}KPTCgȽa(|xߗtiX/!;w)N&NŲ{5QDD.ܯ~3Q;O:xXL2Z*'I:3d]ۇWkUKݿ `9RÂv9g=7pBTe> 1@?{6޵uKfԻ9\w<Y~=E2[G:'0;i,wۏEa?\akS* 8S}@h[ג 鄣$lxlBSt!bkXaI4DL$W[،'.}/ JgLKnc|"s Wo,`D^ Pk] ;QRjG<{vyJvØCeASk NsHvum}`hoLsg8Ƃ2k9! +%[8@>g`s/7Эy֣7|}w~W$ $W+Cb9:bWoCjG.fiʄ5&$V`X\ƙ66svyreaMw*("@,+Vkw_|gF^,,c.:(??۞u:$:XZo0PHufX;ߜY|]r*oHO`:B^#Y[E?UϪ8}?[_VlkrK|-:W A3 'tpM[Z#oۣN|ir+Qi% c7B[N`'6zf˟7rF0\F˞*0BU5#V'[ٍu2 E_qn)7xt !CW`$EXy//,~_~ M^&<Ճ2n(Z eW=0LM YR]B'l&m\@E39tֿXzXX)ԃ?I^]dM;oCU ;Bh`UЩ,CE g8SPtܙoJv=(0]pfCV{%F @Y[\[6՞;*6־~,Q;{Y@j<ćオ۟Ŗ@PD -8thYjprq]4l?)vG w1'd<):j魹7i8 c= PL=:5\5a}xVs>6n]bOiϚLx(#6. 8}>:MbD>!DuK{0mN ;Ht#6қkBO^ ROd)"< s rkD$Po;p D{9&ZP3&9aZA(ח،X2d/Ān<<,Ф}h+c-!=-X~z"/ PŵksɵK5<b"-j8ðk=rO'Cm@dDR`y΄3O0RK*L\!~u>nϸDtkAzK&L˩0\MŗsTW'n0چ0tQԢ 6 ~E0REbSK?%z=9BtV2tcxr} Y5DM.0 .AGc4Sk\hb 𹀎Xf' ԰ '{bj:9^#0i~ ?;[~J/z·un5a3A4hc{ܛ0I7ݖ6‰u0Űүntp M/emFnWzGM\J8XA~ܛCe@$s ]inRƓ$ؠ&G:)g5!EPe6@>zsdO}ѳ\j34wq~d0>_Z,H ʐ a!C =iqb$)h͵x^BJ{ 5Et*=LMhrJ/$Е(L=2M2 a%NJK D<{ѭmp _e/ѩlNV!8dA &L22}ل2B)*|0+{E0u445`͟NJ5> t*K3ڽC^ϗ0un~:vJ;G\@'m, \uDYUl 45Vcv@߻yz61f! ,ĞGS=ta*]TNXz_ :pRF1e?UYʐcΧ%"qwP`z=}n]fq_X9v5p~͋$UwD\H >h@lH6"U'=uqu5Niܛ3 顃NQX 9`t܍R'LۑIo`K0u/bɓQGL9|) Fl ߙz| SA>vX(*ц]@WA}z꺸{;ǷЭ?A)Z~ln$ԃTdm܂F}&;'=jc)}1cn9(Cl] 3f0Djkw3\@bKKsU,*rVic*lR[dY \gXHK5Rj|}\+"uܛ{Pz󟾦q}h0X"Qo.,  ,c)WH,8#rC؂6jÆ Zl@wyNð&v>=éݧ8{/lnwv:tg8e[-Z8m>C*t%fwiwP6IR'O8{2qv ^;AW2kw7.dAĵ08{+ZѥP6*_Uqh> 4;:1 nʽWǗvTϸh$?(YyjuU S5Qgj;i,D&;FFJİuFj쿗S[K# *> ;Na?@l}e+ٙq!LRB aTFAO|'N%jS/hL}>43xi?qPohWERT`*&xeWIM !^ZǞ˜;0=i@W.\%g+2ytjkc%aXDsv<|ve}H=}^-nLHF S/IhVmM}Q;O^0&Jn-۟2\bvtuov_ ^LaX1dXkw.Rz}c-a(2;eTNVI`X A8^ ?:T9^X@zѲEI% k-Ts?`xV˙hbHw,Nڏ!_mǀbZyAG&e3wkNu>K{ ӷs}ZsSrUp}vLtP;N<%1 ,>dgNbu&Q3"+?hr@6, 59v~a: L Mᾉ-&U6bۄi@ Լ: Uz48s Q!p ]Ҳ1dc0^wCn]'&X,3FGG[{c{ٍ*%|h B7`tƗ? 3,}@hz;ioI(BvJOMѭMG d͡ ǫ3EqCBfz*h,˓>kY#JAB<:z+Qk?"&XNGРL1dDv7w ˁ>5ZtxN@;Nvl}rw@rk_~_v RbvoQ;O߷KPϯ c B1Km>tv(xf|ɵ.(6T ϭ`T`ũRW~ J k_-0Co~:+0pkw(UG> 2tOoȅ].GJ]Y̬BS{@a~ix/-ӎTc-z|!9vҢdİ-P3z,W& ZXt$'6|MYUP#C8#gP{b[~5P*.r Mѭ߃xkkCؑ*4+3)zmWf=!0%:S=͙,W ]Qvc9ؐG+ck%q$6 ۏ%ڥ949^c$לEQ9G,]A|Ojx: l=~AXk8 ]o{9tkJ;ҿ qR;l4dvJÂQL1c*|wiQHaM|~n7މOpCzWAh]4,m4Q>xkҧhb&9eڕDɯ IDAT'0pՀwV_CMTNzTŋdlTι*.}3K]4|+`A7IF!2 d} AJG1h5fABׇ2#UH fAװ׻i4 aK|zߧM:0>S_sXNJ7RpErג Pzΰ\d<ڄuBLVF0< ;uVGSohwFC|ge%da F*Pī1,/"(S@j/r nJ/eNJqȝ&=_X'ٍ^^se.ѩnG/Cf@} qlџxj25Ip[ J`yv3#Uaym"X~* ȿ=ZK7P;oˇ,m7˹'É.bX+1N-}~NwXwMPJڬT>ˣz*7Q&SŞfeb"=.7NBWbd*`eu#5t*5jCH'~0&O.mBYvpeTZQB1\%-, = 3 b"t%c2:p5ehW~'{HQpOH'{g!ˍȿ5p$KϘc>@%؀S gx-W9ʠTYMh}EK:~+2H{P3PkCԴgqwބ"bmHm^u l67DTt>jYYE/~ ˛N " @1$ H%PzϪ0;]=9AW5 ,e_&b'0 n?i'sYmv.0yԘz,_C( zΌ+#c.>9aTi%49w.$>@#9|3cN9B<|]si;4r _\ʁ FXhP$/ѭ︀j%B*:/pfIuYq |dъ *VfZr1 `eBH^.b5jp"pc^w 5RЕ83p!䇧s5dw.Q<ޅ%hrpքI#KmD-7<]yXj rvZƋMYF hS0tG8끯{ '{FdO?^5;xv> |6B1cY4VhfG~ReJxXAU҇߭>eoKk;mɤ9-0|!}Gxr82.Zz[D3/x[hMIJu MCj' K%7bcySI! h)f]mt|;lDƤoJl]ި_V|[>zWP#6~lXDN|ӈ@>y'Dr0u5hAWfn홯b:~/ɵY=E(C~+oYhyly?{hUoM} M1}>rѭM2%:66 Rƕg8>bA(xd& }^=m ]+ l>|yߝ~t6L[ ?ݕS7+6P"nx"q, А*׈v:2 2:`8JXCk.gڟ_S]f>;ŋmOWHH .Y_X_ޫw:2;u?K` z . dBN៶\Q K[UÊ|2\ r>f|33ZHxk`yζMjSJA>ČmXz_c1eBW3~d{}+7(B,7!@K`x,%Psu4,w316﨣uP>':cL*CGPJ%p;Hͯ&m)M ^}WFͮlTCȝ5P3C2 1*P+M2j,Y—$&}^㖭BwT'P 鼁 1M3ɱCyU5$@(ڀYZeZ Ӏ崡TΦ3@f4%#kC^>(CJbvyswT\-ۂPz|e cbrKMhGAuـ jԽW,zJtO9sO&/HQ)ӄ`ɔ S-_%90`Ȁ_%!ʆemҴ.os:T9:UwUWu8w03U\׷>4$jS5AS\=?p D0QlJرg6 !n%xSPWz. W϶]֤:"!c`.Ǜ_xџQΣ[ hn| Tѭ{eЬ'wI^ Wft2XeyKͱΜw8h<GIDet*O8Er{=TB6 $tu'<_2jpv0(,EȏRMm[@҄aP`Lh ulYL,,=Eе5P'g+h&uۿX_hr,N 4T`dLT (yʱp Pd}N+snI0-xД 5@lS4 8lcZR`,v !Re_Y7c,`}]Hn 4+"B9ZP9NpNb`|R7m54#ǝ)NVd7fVuݸuXsoɥɭ:V2Ϲ_N]ۯ \[UҠȑ:o]ձOE0.U E+Ѧ pr|?޶68_hirjc- 1`{t6,P?AN?O^yv|/O]OS ׅeЭs=l+:ZJfVfu_:@ smvMc0v2 #B1h ԡ%H~KM6 Q̹'ٍQ@3hD;:B3 D,\4[TRw!tm,Y_4X%𤧽8[ܓ󗡈il-AݙkkAW5ZXEv&Yh Z<}  ҳ&q x:S5wY;0gS6coTOЮXQtʶs6tڒAi_i)!FnwwUЭ,[UQ=߇?Ez>M[󍈍-OS>X]pRF6fxV/j1>& z뿅i+J{%L T_ET%9[:1ϡ)M HyzЌ)E7k񕼚/xƬ \ 7'LגK-3S/VM6z}n}YKoX|xJjt  #4_}gy]Lb9g{`<~r,P<вݰqBSMT@vP8硈Ag'L?t=d#-V+OYk0aA3AZ^06,@2'חnWSEl}'n:tF[ u@sy 3}PPo4s ]qmFCג36*t- jOoxP4N7$kq#JfB3?8RPP=n~P1-Ůb9 R36t5%2 B z}m>YYHIJЩ޷1 C#`FBУ' Z$3KV]X6P{ٷ_/D尹(`}"4] f(B`FlL@3 Zl;EP/ }!Q=A<_v ҅?C#-9}S':nl'1@x)T;5ƻadoP>ݘ+Ko&NY2 }spӛ} ~ :ZؐM2 @[ׯYe7#{u^s|4ӑ&7`E B7|G?F:3Ӊ\ .5D:~h2*^5;0` e}~7ߊ;Jg(D,[D|o%k4]%>}׵x4}󛞁Ũ`2$>`+5uQ>D(цydRχ2*Y}4ky 0kEdoq7b уR;\>M;$ t7x$vS@U |p)JʐD[m&.ƆE-;\vQiŬDcT )jkI}έpMCh3(a.. #>cP9owlL =k>Џio!7&r1LB?%i塈[cM4O򔁕vO_0!@l_w'`}urqq?r$Fc v4׵6Kf`\ М҃eߘKAS}m 5n@l'W2>@` V?E `z,=@{'S^Dmʆc`P̊37x|Op+TE39ɭڥ NdP6Ld(<*q("-뗐,rMD3XTq|_%[h.Av3zw.3w۱~yO7<Ŏ9~'Xkr[WT~bo%VT.]`|[<*$Akc,Ͽu +qEF \#i%Ue}:no;/nBJ:ɤcƭ>aLYl#Zh+ZRt>DR\fO)e%PTXBuWM?;.7A3ML[ |ZzZiaIѢKgC=x^?k8]͟BlAx]NΔM>n.xPc<(FF]NU[ٍ[U jMGWS6NE0 d^b+Go&!9~a~10<!(F 2t~=2%O`fMPd v[6tc5WB`8C\'痑-fttJ1 {~Bjom2c&\>7o~x#D# YBxczN֯M^n?( *㑥_QDN|g-n,n 6 (MqY д 3u U[TF&ɆΠk)@? h TJDRҞP;X*Ò M1=h[\b,/|3P/ Y8Ah-1rNýtD/Ѯܳ_g#{{Gs&da4^/,u2 FtΠ]VY;CMj̞w01Ib[{1P }hVHx(jW!t9!u#C=z"@r&#-rjPt.J6p;s̍3_y4;8 ;āD{՗b H]-,:d)GheZ$hb93e ,qI4#SY(@3n$-=g82MP!M'O;9[b;aw`&(&رzB=2Eu E?}e`0^  4s骣: _EA]I)6PɫV0/aaiN2|751r]@F Bz#BtJH3tk*ɿޞteAbox24%dq1@l\7l #<+@V5UD$u`ܓAЮ،!sr,!V I VIl|# cYJSYǏnT 3o^S,da9 (Z*sYlXV) /d^}9 MT}@UpA`sF Rhng1Ɓ !b+TݚX=Ρ]re)ZpJ6X .؃ CC Kh9\qV)n:H^6 ^ju|tqߟ*mk BP$ܒréVE话"tҲ 0km7z>?K IIx\P4S9N~$ ȠSֽ~AWOKMLne`n.}k_hn&xN%daC n5Y`,o^QֶtTQ<✝U\>[P& <&؎e3׉GZ2| Ά=궝[J\a -,ϾʱR/|zP$ofdKi`S*ONAy@fJT73Z]a,lcamQ-(|qcl}n= 'Zn]8u (F{s#Q BhG<:4w JF r\@B0ޝMOB^OlЫG$ lK}v0"f6\/z- _/d#erRl5W!j,}0&oN  ɴI?۲;5KB ]-v`tkKj7nP:5#GηKh&AHhP|hHlVPA/$[[$کxr%ȼ]aEzs뛯q[FEֺ)HqtS"".e]հl@Q1pT0ieq3Skmqb{hWScpo*`BH |!B9,&RqeWSW(sXp}O"'c2&; :ɺfy6J: 3rӛZ9!`$v0@ Ϡ3 Q}їi_颣g TApoX->cib3r^EJ;SPyCDG(Dt)9:zz!oNlVS}߅9\-l 'p]4Kyg4)Fic&'ھPb70tu0P"vohn-yl{%ƚ ]|zH*Nխk͟Q6N(}Fo׸Q@zp7k$@ȹ~0TC0O#>̀xNxwcP”Ĵ˩>d6Yk׈T(4KҬsԯ7s1.s:hj rc vmAgeT"sWt?n.tf3 ̖V\cf|&Őx/`aG?qoH榀*.ـzZ!y`Lߚ $- 17;.Ufr.bt]eD4!%t+e[/οB 6/CK C6V8Jw|Fs ӃC4 Llಫu w@c?V&4u}-̰\v❃[}'zcD]_,>&k<2hEtpEvŦ{PwaxViF⪳KG(ynûj}V^n4e{?ĸ tkTamBW!<( AL ߗ0l"é2 Ъu҂ZzMɉA&cR '):=0CG,[BYԳ~ D|^;_m}ioEƂZm(qA%?3Ǯ?, OwbEƭ+7Xce(!vcr [{p]A"uD3m[oxRi<(볬7E,ZmN'9LHln|5giHJhBsRC &SyHVV K9]Z ݩ hS**#Bi~ È%6.E7OP=9Yce B.rV, ƏyXBCMPG?~<0bzC_۴۔ØJZ/sO))Zx@-P;Q39֠cj5ŧ޽f{;Va N>Fe~^sK$#9#94ygS/ѩܶM\!e{g@Y!:, J\fEJ6 y[X.9valj2 _\j`H B{6qw53XpGK;x|3> dR;]1GTj fz=%ݶVvu("k TϽ1Nl⬓@77 )ճLFBmF1ڰ6Jt{_t\?q ʞd )6>saf1Jx6nWP>MY6Yz֧5 g};V P~G?v6Z ;R[(l֏>.9˼#NFlhI/?2uQZ^hck^E9Xm:֨o_v\HA&ggw RtuM/PBRTU`ѣ~6KOko199,6ÝBҠTyvHDhʬw֗8OSHC{V4ۄ?lhc.! ;cP;9)t 7&Ɯ _ BL5}+S}H|sbW5 >Y]v0UP*z{Z%b ~^}۶Ev)z_UWkM/[waPLP?O߉g*mkEhF/6 1Ly}tv(h|+66nFIJ%4c|\?C ֙ۛ~yNƺ[ᱵH:ù uX~  K{JGbc9?+deyokntn5 Ƚؘ b69'`<.l"˲f"%@T}T@U bw 4ڴ&}n y:M2,4fZӈ}-!5N7<d_7`lg0t0,'a`is3lteQVt- A7,`M4,CLd0(WݺPM(&hMmGz7TeNPݙm,KQkr0o"|f9@h >qoSb-(ve(bԆ|fâ 5ЩBS}e`:}W u*NrD"l0QH{~.B>p{MH<![sg4Pg(р z_ P0Yv@(S YXғmA |:WS޿B;g=@$ m+PViyb^i4  [RIwЭ= nݺn?X.@̍**gI,t"c *BhL[C}Fe:p= ."Sv9 F^d=5q1̠ZYNu o|^ȧotQ> C*[Y%dKؿ×!9j2 y-B@QL 4@H􄺀Yj5?Xs?%z4&s]ݘ.Cue94S%L/JE =bCJu{/w AM<a>{32XJ BSS` u A3<qVifZzG#)L3I\Ge 4w@$}V*Xb7w`n7iS! Cc01( 9SzCT.Ũ 4 ۶lq,A*Ul@|WJGp q)5Ox_)[wqܣN604Ԯևu_PD0Ex/ebYQ=Q_@6Q9Y"rB 6}3T! 4.&qءRNdtO{,[e'nz<A4,oH߂a@"Xzoo)P tzgm(0'/Svj5QG0H<V^ ДԻ,K2^k}x.H١ꋩM@ђ4_W?ckZN] ]cѩNpʝi9G_ƿǿ?k+ R# D׏! Q "sPVj-%Dj۩,>dCgL&ddt튻6?uVqkbZ%Ӕ.nߟ'=aai(@(@]],h(iFP:<@] ͣWC= . BF,OA"0E#׌,pA \PB> J;$ǚ f!@vopC流f'9菈0 b)*϶Щo:xvW8g[4r&E0:AQ?[F<і* _Hc&@5$c>PBD :T=y[ߔ-kE<ǎ~Fu uau ,E2Mx٩a'efN2nb{B` @^C4Hj994cVtGO90 oLÞCSӠ2~*j >&o/я^cV 1+. {1pU(|}:_.!:=s. 񙅒c"SBiHlSY%ܛ)N,}`eߺwRS_܋$I[H%F>}w)>70c)ZAx򵥓I.CGׯЮl[X@afe /4 hVvb HdK|AUJ[&eAO22e ^F8@X iֶLn(5.vfcI(ԟ'x҇ԏ IDATdo]xg))> BbYLטu ʶ2 % `~v7Fv qN 岬É cSǯd>KTDRWp{zo:ij]J![P˧k <\`LVLtQ hQ h~ЄR8|5,=@#! ; I~28QqD,[`W$cމYIv`7`w@70;{Ҁa UZAt5c]8L`0@?9@?;/8SL9j&#ѠNtBR~1/|OЩ9׾1JxKT!x.@@tBԦ0`nmG,sUt%O,=4:m2+`tb5mE#[Sfb?h;ghv-E.'-}$]FsSSGr ++X~}B;`ڿO!#(xաk45wJc4SKoP6JeUD-49`EPLUPX2&>w]+^=iP=͋\(8ϫr8l/G=t>>(4ee7nP>,W,3L&S = )ZG$-U TSkDe?`zD5"ES?_KQ4jNW@\AdZNcdmim闯h}n3ݐK*=!5Pk߄:?}%gaQ({Aׁݖlh4ExiRd 'tG>"D3c4h2lqΡʻ`A9:~\5$.c?7O# ^:.ѫ1t5f[GfsqJMB43`JW6@Wqz3NF;,62tEˮ)ǿKМ੕©#tI9_`\`}ݥd sGV)D<|3V:h!yG\^dRVs.d!.h%jgw=:t44'A1Q㏑=q5pd>d x'B;/4Z#é#-  Tw>Y6{qߠWO l}A;_$ }N=_+f8b'SFR-t1Q9DZLeU /Cš~po/Wb&>e Iz~B6!v ?"bsn~W0tB^séS_N(ZG|E]27?߄*`8͕h}[ "ƣ[ hV:8_lWs K6cv\cMǘelߋ4T )j5qy6H Ƽ |,`f:^~?ϒ"*{"ڐ/ BA *vҢA6"COA쐕i]9LN4# ]6B8  qXCgp_"Ln&Ǜ_7nӿgo{XH=:pEn nF@^[Gr}7/r_)Yh~UʀDHE5}݊P|Į|d3t;0<(Z"9<%ϨMvcn"y4{l'h@܏9`]z@8y ɱLS 3AWkqYˡSݲj} Kfrh҇.3ԯ@\0Sc>چЉ:>T ݚcKԯtk9 wﳷO 8E C="Kl(FYEgUNЭGA#: "l}`DE ChϗD"6T}`\y4O?hsm-"jtZNOl`6?O]Yz}I0md0.Zx_PA0&:uu`mE?Fͫ:rϓ,@DMf"̾i=5O*3tY[NqGWBMc`2+4Sjn]i/ hM:$ wp??/{m]l<+xMS Uye7н$/&hEڶg n!!B_ A]tb#C74%JBKMЭ߄"=K4 +XR-۴cA,{Eon ~}gOZM͊Jp Rș3Ҧ{t=Vb>dądiFA Fnm`^#1de!Vv/qB&Z텝r1p']mY.yWnD%h3(4BS2uJ pL%km+mșA6g?,_'n֯QKon~G?.yYIu.G7+Nrضhs]] !e7~"un0KC)CK1GƋWKOqWӠJWM D a9P$ 6p:N?]C2.Vo-4&Sl}! Rg m,xR,@Kd 1#۹lD?_*|>o&E`!5'kC=[0(&ms[0~ q4^cHw탄.BC]s'lj.-3(ZGh?phKHƌϔkk!zF#3܈[M$+Hk 9!:Zś`8%<jg>1ּob7>QЩzg bL[?DGjefpJ®?ke. Wpxc3z8 gܵ*ag||">5O%M=ja' kr-Tjf]@$E%$tmf­ǜ4e\f~W@WWEdJV1R1ա)<,N\_m)f VE||ouq]B,)PLB6"S!XE_@zr(t-K?O(pfu3G_}>w?| r#MHw=w?o^<nb= {(`D%A= u}΍Whڂ7N][& m2$.j<1Etkٱq23У+ aqŬ2C`O*-n .]^5yww~w˔иZ`.;トѸznq1r$Bػ+Ή\P!:k-4ɾDgyIѩ 3*ArOQ=O#?l?B( G`7Uڸ]B]ol+ڮ V Zȱh>-dzf"l0.BXXfh Km`A¤=Sp37(1]솶qt 'bѿ8{M*NnfD>L~,V jBgPoL_@?R-vھr2P_vQk _>aПASo`祳 JEw>gFaz$|ag-"j"S7>P.@syқSvgU{ÿw?G _W"fl.h'~ݎ;ï?wݿ} X1W26ׅ*,;1\iLxb;=B4o`Z%r`8̏+KO BMHʬW5e!1VЎ{7rh7̶Y0a8ʀ(cA@j3XUN6noEѫ'Rc "爆s_^s=Me&UCb]2ׯP>7N!Ah:̡x S܎ 4uhVM^B(B G?qoT>B Ƚ~PCd6; ]2,=5-ogw)$; r~ EH,愕iio|uG@p䅝R!vv;%JqlC@C|CD,4(q }~hn Xx1 7osh1.QXyfJմg Wʬps!uJ<) о?r9ιrc(GS00kgwqϫ`ض} ! 6 BT(4OR?aw; hjH韞zg#ϡ\VX' f6sVT |&Zś @tRO t u+_/ zX?)` f>H a#.ʬNehsJ۹~"5(ظ}B nMZ~F~Պyz$9VnH Mn*ǰ*8 XAh_ oWPPzmE \PhD;>:hWj6.ظaq>BB @B@B'@pc6ƀb﮽hz~ܙє{gH#~W;<=y2 )E+BejNgۋBqDTeRKۓA>ik8kmnŌEӿgwk,,o{ as8W["SK ݷ# L^c@-abha!n.=+αM, uwH@>>cQ rs6H u8qv?]H[߼sJ%AU'YQAE$T@\ ׾k K" nΛ3"J`u$d7_($wm w%B*li_6;ǑOh,}(h߼ 7n$kn HmVl*pnk&Z^j HS!`5{W_ 64Ys"D>٫yRe֞xbƘPLW~aSzw#Nۤs5lƘ(s7BjZjՙWksgP̸Ǝ<8 $0HbDC {&* oKm|u?:WZ0ɂ)_Qq{`,,{Vt)A$k{/[x4 G5$]y A`,"P m,o`SMXd 4yPk[,zX2')-UBIvwXp$"hլVֲ 8 _OvPo#CJ; vbY;N<jKq(f8BţJ' A YhғFXz r-+L=؀KHڂ$@S$w3"SvW ]mP$a~Z1 $aIǯQ8ֹIy΀z0HX$<@ʐXUڒ$4BU )Aۋe8r65w.]'`Ip9m#YilkG{/l#?{7>wa6mӤ9ƒjIP4lt{[sZE:#RN5Hi,|),lMc)$ZM$ƖEk+FIZPWm1ҲM"&,sΪvI=Sԓm''BoG̣o)nZzW(-YUZEpYTwW )gݻ%A1U@1hYYE jֺh%0MzC-b`IK\9Iпs GnBqx(-&Xzy],}Yip 70|2N=ij$RrmUムtڠ(溓-9PW;4ם}ŖOlٵ9W(K峉pxDOk9wP@>ʰhdfpivdi ہگB'Xy"K+^9~(HAA5AUB`X#l `lԏ>u<"@;x.>8 I=+NMR;LJ%eR7H:TUf%,*]"d J2l)!PLnJ.? S3'/1Q;/u0Z0ooOgc̠{<^a\wpsXѧE!KR׿+SW8 MG_.ETPvM40ݝ\]SX?  Y{$?=ЧHu&B޴jɝ!cޒL\X2d}51VAp,=Et=yT|^KҒeЮvs$78<)뽿F&+@QԖ^5w: zpup%,B[D&I4ݼBQT|o>{ȥvPLl]-\Fz&Cu"ުwMbTooh;|jO,ޞPU(YP 6p8HBs%#4mueqd=ӱXdŊG&iNx‹H-U}ӹ2\PXj3.@(5 KVh$};aRko F=t?+As? zB|-U7gȰ6B *@WNX] IDAT'\v/8|9R2%u#'!xI#PfEid.ApsF+dfd7BiFUZH, $/Zַ:9v5`$k;(=?E+T 6 iUSσyx9L쉪[ʔrq"*YoI,uCYzXrj:sv]oP' >s/y$Ew!MPyղf@_=YJ \'ɼ. C1iH|d$5%nO\ʚcy]4.TUmPh;"/4n}| +E6R`@ђa 1} D:n! V4Rc i#4j9߆PRڲ4bw;b[)y)JmM9P%G.#Sy ffn8DNm+ofJ7pqpz߮,E&!Ձ`27TWr>;4p+YX@#X:9 \fDBy"o1s*W0toF&Kow 9*` BJpH!AGba\klm;0$3Z fe6l:kMWex (V&ص=&%sW(Ȁ7ovj6[]Ph^s".c} v\ 4ޞ$NdZOWkk!{O@>Ŷ5n\UB@S:^xXz,=lfݠTwNXab0S- AAFP y}fcI , 3?վYe,{{;T).E_)f^>e?dD,qB~ĎYXjS@8MiŤ!Ӏ|MLg\m_8^Y(*%YK6 ʲZ#S#(׵Vhjk莂 ́ZőjKrK6WbC Li@?k,d,X`uf\@E(2n&q+%W+C6'Aj dJIzKbx{\1m0/2;'ptsSVbd\PڄsSƼ B7$U + (fkI|{LmmL8b nҤ7$`on+be8$=s=Z*kmgJ67.VXԲ3)XWج-jm6׬@* h͛^!@ڽ: *ڤ.@lY~?bXzR)Lݸu}Yo ƱE(bljQ-1v/"oHz.KOPF /1]@}pW J1piҷ؄4U5x~]MA;6Ɂb~C{ݴ% I!@yΓ[Ǽ9{f^?ĭoكx$~,!+րlNdO=C8OkgŻ;>| KN@IOvDb<-@*L(jz6)Zhɖk(fC5@!@f>-BG1ذ1C<$:]j@IcUݼŞPpT{+-ғTנU9A*%ؠ_ey-,``QL{[ ۔< '[gX] X:13He(UtiXcwC1>ڼdOո.cj9Y+:%S&!r Is+%Țby"8VLX]:< .׊W;%{am~?Rп=C!lh/6=]"rqN@C I,h׼yth Y / s ;8$ΠlM&,=A,}UpF.?qd)XK"oA$( ,=A*/-ɧfLY[Rki-Cuautd dP \y:'Y2? Bjah1J'k]G13Y=[XTɼ c߁e|޿q+3.66 l[xǿ}q/~),.xүabwM(Dbv>Wݦ*Y;͠IIH-uoG!nH(M?- $s`#.whٕXsY:8nݵ* MN&,<^UG>k//*:// , F)Sᄊs#>׃tĜg|}U`9 5^;! YgYauvռۓ BQg킡fkdp@ iF/#&Id3C҉όŜ6үϗu8Ut-Z@כCtSaujbgYg]Hwl̶<;|aric/bBs؂bT Y=vYw1,AgZ5ȣ'(g"(h6JP(fd2V:@ͭ<|W^n}&A;b ,mI/׵$o!AM 'o؊3vw'A=Nn,&RxٹxFa\ra?z{;` U2Y+sJ'Գ(*ۡNtnB|Mp.! CnL T3D,G$G4VD,Y\[h df 1űt"X]5}J, 8l x«s&(4$ RUf ]s6d}.rfN7z(C\](y^r9^9G~}X4Amb $nP4ő* nؽpwM" !iP$)n"VgL5N_Z",[rȬ oR HЬyfT;Y= H.?SyP?r7F*(?p Lpz&dEk I*f]#s8'θltOb->8 lėƢiiV RH.ݕB&;|"R`,"DI<$@󶬽1F/ G| Tmcj_7F_K{F51ZeFKU리Vm%yp9q)lPuDr,QM$',p#< ]L g<2}^'봗hޚ(rZ#Y̬Ѓ pa#/LAU] @ִ$!C"& i;(H\ta]D<73~v Up{_0#Dӈsmm7b5BV49%icEs:hz6'}dxPtE;87(r%;* ,+oނ^?;B%]Z雚 BaS }.r߼LW"`l)pnؘbCV߾ L Ċ=x K{@jifxX [Ωl&Oaގ ƚ9UL.YrZKo+@(Z4_zIh 4n(f擌VqvOXW'&j,,+W~v`VsAtm>moyy,u/8^ں@hh': W?S$:oOsF*+q๷@u7QLie׋3z3{vpJ04divРos;8W?Iؖe XwF13sdWj>ڻm K*#bdPRIe"hBڎLKo" I1ߗF>ie7v/E&P4үMaskZiV"Pdpe{pr,w0rW%qwR-!)N?.ǀ/ HEm34 E"52 -}Y=MD&)MN\BϢX>C4u&^4M{\bma-ATU T5@Bk7,5/C>o;g܆O|rmL۠ђ%v7߰jw&$,'}V|W!.B@4F _5m]sokI+Lص=Q㊲CkŖ.8_=+.mAv;9Pd@J:QlkK W߆|/] @[Ѐ?MxC%JxQneKsQ$vT]Pt!;l%669V$7{iKll5c[Wf6eo#>WmLͻd]YzӘ=:ȶ8cn>fkԛՂW$@yS*w0$O@۝G:beX|}y$`Z,Y  KK9-n[.a\3x< iVOU鐖]fBuf+ZmhR P[M7]+y3"@4$}'"\N|a.8/{|[7/]xǷ܍ɗށ >mǽo;+}G>jS\mc~7{t4Eiw_R0"~W^bsN@5_5P[k 8O$ 0D9@~XX엓w ^ӑ~m))F$j^$TaRŞwV(뛋]'6U r  ̡1NWk[s^Et٨9foY1}`kQ PJT4AJ%YowmoED&jCBb-RTasq5[S#LcMvd77@Kwp)sep  U^3KO2kӞW xYr@0w(dޣY:mx Y" 7M[D1Bj{EnKcrocm/׬v`kY~^ 4(UyyW``q(_:I(#QTE"PZXXfsTC/ZUxCx U8 {}ںR9v=Ftb7""&EX»ٍ_6zmg-E(hi ٬4>Ëp=p_m(; NmNaZJ_ ?Eɵ[[M}ǐZVsچ=|PI=ȴ`z`9-*~ڕ1$Q~r<` &03AIغŃ |"pyn+^(UM˫;< \f׶xZi"ç:g͝D1[۽xq IDATXzZ -AţhAJ{=ՠ+\8XqR5UekXĭY "#5"ţ6u \֎Ȅ9''1&'joiQ,4rٲ#n?\-si {*QN#*E*Ko ysAηZzW;ݚ}oGvcs I,=KP6B4,X<7<ͣŐgrCNAX Th`;JjSKwG&j5Sɚyv;KOZeȄ.@O2:k,5"j_3+"^D P[E"f"T*Ԩ&P/yE(d>zM$}tY%*$I @QW0 A|o)k;(Uщ FK{G6| 娀ڎ ${qh=gylxbWEQ!JzUUM{ѵ'%oj]KۣڬnT9$%@:v"dтbF7ni\ ,E xĆ,voTpCMOJ$UPQR˽UA~^FtzڊO<:~GLk4oˀo/6Na8D5yDN kJG|1`|ȻCidc֎ 4 =])dVW`e*`2b'|iL69'W` igK?wYzBZ3Vl.-a+ )6w~ﷺDp9} Es(fXlK|>|Ѡ_KrRȀ#ƑL: R |\|ըC#H:l,ME|On?wկ=)WA$U~l/[NEMh'fVޡdII?}Xm~Qu}σǚ>(x%#񡏾=qTr2z722qPHwWKK~=Eb >t`p5C=| w{52; .]W[Ĉ!pWO4ZzCNC([V5{hV@1㮚SUU R*M^sz h%${%x3W+ك[M}o$O הZ}X#gk{+IJAy A*}Urr] `Z9%lK& Ű2 E6@!>knusƜ&2&_ԑfd7VO6*4#ծՌY6c JEH$"6!7ໂ,C߀YU WDMUYnMw$(HJCr 8|":>.&Uƣ5_{?NaF"QܐG,{ݿG~3*E@z&🟽77.5^^ƒ??e}t0-x];p}PU4cp ~,s%r_I~1y[Ŵ 5ݏ[`qL4] w:&(n0A9\H5?]Z Pk_3ux=rE*xM[LMQU2<xӈ''sىޭf5W:q=p.C@I7W^܏'k9Ox(|u^Ԍ5g`qn}3Exdݛ2 (OdždqPa͕ZjWB;;Z[<߉kOB2`'pwEJA\T&fcK-{s ӃzJNaVl9kX>oo(dx=O L{2fpd8hɬ#U}`k Y9Moς ȱpw\gΰwbuC!Whz@Z?U9]DOUqG~b;|}I-i9AVX/1rެ,|!꫑pM\+T+ļ !9}lX8~)C/{3Vjl$xE!)Tx␐^~@IN !dkC wP%n J_?C X͍ ڊЮ@* %VU@ч  Xý?ϔy yIO&p~W|gώ(J'3,}_]3ҒE ֻ7?o|P-oOˎ 8/ˍAi,.دw/>qh*7<:B H0z,.;x Sݿs原bn@k>b) Eؾ5iٗ ㎷s/,4$U%*,lc\md?\z^ɉ~j%_6wfm#@lr/^p\q.<Ǵ#:CbJSU%8[0 Egh :(]Ћp BpgX ؽXI$힨Iݽ--#ޖnOE{De}ڳ+mqd]/϶'STjܶ9!r&uvȧU߷B}hV@$oc K)IQ7 } +S&(Oa6Ue?R*cJgȖ$Kd|~Cy,,͞#[$2V](yڴF^ 2Z4"=瓑s1ŞvD1ZDBSNIT PDbTU?'VLjSfUqp v]k\> .KՀsѪĮzh@"~lEQ A@tT者iPF\#K"p$'OwTxg)Fk>Sy "3i tG~/$1*ܡgP<¿E\qxY}РKiE:'??s)tq;ůcS3w7nWiW?=nbCb#m-95WD^Ua*959Z{ l.H%@VZ'.,nmp@_A>ZYt3 3toz MZFk kc*_5u*&tpZIN "zzs`qѿc3l5O+_ƒBhZ* 7k*@~/ۍV -yӛc""D<6cָFA̽Z{H 1yӘ;d;"&%6gZݘX."oކ?B²N)5(2$q^Xw[hjݍ DNy*AzñC7hvJYjSӬ)~Cg2,v ƫbq͠^` '~ Ǹۯv)|W7K/ki)+*~I|R˻Jwm}>Zr얖 )]D.16g\V iٕ!8sH &ÚhőR1u4\%dcCPX9G#Hoz@bcEDE1ͮb\ O2Vg\ Sb)ZňA0-A̳'AfNvPkPJ"M0P5nBI)hE,5X?ֳF7U% YEv/#6@` aSmuLO٠hf0mn`Lm2oHR+\5́.5[]YdVled;c4֏d>E)Za,kpW ekřf}jBC.VN9y$6>6/&$Qemܒjm0+h%Pːs@ BU #Pp݀' հ*x_\/~Z󬬢br*'y!bt :׎!\tA)v>_O>S\zCW~-ZX!_h@K KB8kwT73<|iű19¿~xCNb Xh|Cڸv'I ?O! %ǟ̂~.Ns6 ex{N!ґɰ翚kOCV_ƢƯDnzDZJo(Fy$zr$( Lz{"Ȭ@| ;oaY]cS 6${4-tș/E 9哛PH?)̊_](ʪdxuL#w)wܡ42QsswY 6ʁVPz3ku!"22%)WmbS F9yo&= k`u -U-}yy{y% X:7@x䓖,v{K/+t#Xf!cj^K蜖~d@@;.be$eqŸ9}Э{ڌ=٘l>U dPoC@3/ABUxl?>۲$Hӝ`)=/@sPs<ӔBUO}_>m$ vݟϽXZίK, [Kl4$>?=>+>[MWGo4*B6|) fJW?\sk"% Wj7eYK#)BUKI e:AϪ=m+L?k+TvR]YAz'1d+BՕC!61Iko(0Mg1\f#Prx3A ГUru,/|Ҝchhi}i]D1mo,6+:FX|>> ;M?i[(O!u1- Z1P b LU!zڥLvlceC˲_u -VH# J/ן#Nw)%?Aԭr1ӽ-?k`s i4?z͎RE<PȈ"{U@W}NشYZY<8EtpPdfWzV e;0wg|"b.bZ O8 >ςYtp+SՕalnip^[Շ%!jx P|1U5ATO+`1u gG.n)Sa{^Jg!IP @W",ϊb8mT%j] %/1>|'s'{=?.ǁ~1G܌G܄_=v7&OҾ{'qkTUHǞ`K[}2 Вze?y8DQ[! C*j/NAWfqyk};Y e}x[v7OΝ`q|${ ?UUq% ;YYVgf kOW|BQ8_N5o#OqTR\;Ǔ=椫,$H!8{xgx<=gl&Zd09Bҕ}:ʵթy!v~k{wr,+UմzRyo{kԳ0Zat(.cI4`jB|l3; 6ךl N5N6֜5:f|,RfHқN(ehr`p&^ʹà 6C9'cU9,H D:v s =|iOB~ee-M摘, \Q8t,NĚTz'9QV0~ kO @ɺg'yg'12brh{Xxz7lB,`_a{)?wkןK(gLLx&QBsYVW0A=kMg:RTQΈCw >! ǝf{f!T*kUu <=b|l{Bp 4X4 1wx3j6L'-wV7kx{O>J͵ IDATy Cp],K/]!k"5s 0]F]}_#yCX Gah><~X>{B nSb@e$uj# Tr;|gv>5toJ-u2IHr5ڵKoH j=f ;B;uV߿C[All 7t B(V"ˈOl!sm!`Xz>BH*F6F5W#Y}L& OyëX84徖,}M7l`R Jzr&YwFd#sHÙPĈ QZ?4J(e"0$ 2"z[HZPj>ˇNR1rQ9/[',=ҖOPm$a[ Xxf,=H'/KOh;ĮeoO;wi[WG(xS[^wy\^a*f1 Y;Y?|rϻU}'/\%q <ҩ ЫmO/סJ v WC5[N*2{sBpc[z9ڟ < Ǡ,{j]m[o@y5{}lV* 2/ SGJZC!גJ DGPٚl]j;_l/Z1A N1F'P  KBY5$vt$V P>:zbM5䖦=>X1{y^ M.t :t4il|#jJt# f%ё2Yo9*J/?KP92ŴC@P RSнdNbT`loe70m M74ٯ9ɩn_']rgsPj,;#dl, S*9Ƶ. F`.t0RnY? қCOJ D/Bn$W` PBW5Y4)=:Up1LߟujuTEO⠏}QG:ṋ9Oz+P |sW%[2h߱'xNP).fq c=c'(V/مYHH_o=q)YN0wk{7YY$ˮO2_;Ɖmz3zpBhk:6d# 9o}eBSm؅g:ߝїݻH܀٩~_"1YBq}-:T XWo@9@$%1|W ipzG1!6&a}NכdōR5V; X%=hY+bYքѸVxc.Py;YP=6jz4}3K{[v=@ye6 ko߿ J)/ǫ^k{}oaG~?GIϞ|t 1A)յ *u5)30~nű#iA(0 *x!j?KĘ/|LPy/b ܥ,t-4)sTz%|'2~I+>P!%`t re7Mо;xt0e( MKv#PȮ/b kMTw(Ӊ5W8]購ꨏO,1ic-ٌCIP͵j+5! C 3]Ӯ0&]C0Mc{NHX1vߝPAn;h2צ{G9%v;DeTQOְ$) usCJ8n7GsAA9] j&VϏ&؁:8uKoN~$&/b%Fm=K0v×Zo.XG0+s(<Z e<Ժ/w׽f#zSbq'd^˟]lnZH*Zò崾3)珌d_staضqY^@ aD' mu{@EC砻$vVlV1un:P2#X>`.ǚF~f(Q[*YZ ɩ< k{ԑ^q3zZovlؐg Fx'6W8:nzB UN̰* Jv B(CV/ЂO^ +0u&"7>{P/4n]d] vUec)!&BQ Uqujrj F:uke+)$#K.̹ .cA\f a;{ `rsO[X1u?gtG\k͋C E^P>w:X#W -js䪀^iR :Abz gK®~ɱQ|RˑL3 &sSUO[DvKcL%y%'<}#_ǻYmR-4b]}"Hz,u-$E%gwR 8iQ<^՟ݏO_;I15z.@F(~bl&<a8\vG)G]㩪%CX ك0tثKah|$ ^i6}#xk*ꆉ|zE[ T]lWj=+?BnPLu:J>d+L*T)ؓ)N;YXH0@BP거 F+п 3yuut Wwby]ʹP^''bAg؀yϼA9Cq#ٓ4k]hy[ -ؼ6f9W,VT#B* @ ʙ(%oŷdKcu_\m`9 +5ޯ"*=Sg &T$΄p{OP xGG$AE3 Ww>})WƉFKv]~WO Xp*\EٓE,Kϰ՜WB&7-=6Pb#9֯q$JGO&(66w~w߯bj$Ǡ+~dR(O+Q@̀ˤZGQj4 Cv m ne<~eWތwCCKP S H;cps< D!K2Acp>+ZDOUlv^+@*Iݱ}Iڀ&!}wk B˹~y2;:A,,'/g3/aA:}K.ʻݻHjTRҲl*u]2i[H!:ZBfdOCI` gO`9||2._lrZxcJO_nn` ,qoa8o'_klR WP/.* 3`smViďWZd;+Y'L]֡6d|,5Lj @aux$W 4ZCDr!:&;zz- ![ٮ]/?(^?l]#T7} {3xO= k`boIo=x| /_:-4GhJ6Isf =՚ 0tR~QH}&[>(%: CZlþo߅ׂx^)Sx?!cjbM5S%!*蚈^T&:~g+aD|sWl! NT!W"C%e;$gb>0@؝ͦ+(z~v+a'Ù$]I6 6.^P ( M=yVݯɐAm&g Dek;yh4q bD԰qe׻#kr-kX:=k!jYހn$aM'ȯJ6Xz!yAtfȋCkl kBZO"lzܒ~I(m@R&Ccle| >g4,,m1y  ] M{Nz?.0Kۘ BM-Ve"L}g&BC,~w)U`(oG_Qj= 뛵g{V o@{,VvȲÒcQmh*LGjioo7++H&ǾcaM:ylsnBP]p2zaHdB߄* Wb}@aXuAB=}ܴYPz-%/*@;,>Q/lrKX!g n$Emdqc , C9t视+MG`NTQ/DlAX'>6{Y4F-7X<˓6nA螛W|֙:@Xҙ_@ثl ЙctV<{;k{nҳZm vsa)iNɨ:RQX w`rPmٍXhߟ6|׻'ΞXu6>^Aiؾ<2׶'aXt:78K]+#= iEXn9#]?cjO 7Qvv8ŴHQ{C']A(wxƄ{Nrnxk!@8A*qm)z%Al;"8Jo`w-M1Jc ?+<l)vMU02tn4OX, =SPkE"|]ʢ$Y9| S6dǃy3XjiJO&D|sS=[$ SzS |4"tpc=O"tG L`9{ŕ% Ewa5'b֠z=/JS\;l2U> A|F zo&pt&=w50a , KfY7YKU9nq&-6:O9 KOÃh Cb۩/~b}0#0 OQ5a|fE8kL: lZvRX*Ag_pK>?z8&4h}f{%EY|/̤HZS#P3o&/@rÓ4A'VQ!lsd920 z o|{r>)2 +lHr%@(095`e󨗆[#BF]+6]oXN bSK(nL&v88ozLh_BF{= %ʨ]::/o9T>$Qe+%*qgoŧeCv hl8y0-g"J ߷MK]EV7+'];ى[ظ22 ;Hϖx=K!56¾Ya :2N*c*:hHNֱq%n]`4 ̵gywP5n*bBlyJݧ C*IBhߴs; @d{n A& 8i72XY ,7~l\dku݀ǏlbXBrYhk+vq%&EV*}-l﹊WQok>_{7sX`v&M3m+A]>*'˞0 Sȯݲ-y*`XVwcdiImU%ɰ^\ʼhIvBs@-CWqR&$ 14 M1N[' tUpY^8ŲMQ˧ƖNPmBH*:mt WBS%KQM\l(mPH Wk}"kdōTǻˣVxjHrR`h+&Kϸ辧cD߀aL`)Awn@oz1mn#F=Yz1Xt’ PQ-\ )D/!s=%9 IDATJd;,o`L3P\rYz+}]>dN:cUO :D*aM8A*s^9՗v&iɱ uH}nvi L9[ Dah}P p ԌЎ5q?&)ʾs`k#Yθ*Lc{ X}hQJQ*+Cס ,4o5g3x[_qֿki˹mIsL>Mc4W~$o4)fFoAu|rB os4|zu\>c_ܽUޕaMJq}37@)?PQX=lPj]Zh[ƆjPFғk(gz?H@[O/3NP+ؙ ]k cU]8Y6F&$`I0q`ן8rgH,;P4Hr?a=Ș 'dIpWOO C 8c/=xX !WE"*sTC12_BK/z#ځ0\FPQͪ1jurЭׂaZaӸlf =yתIPt_ bX6K}:&8,h:och,C:@w ! S!e05mQ@i ߲X^VFE LA2n5ӌ:,W,[mݙ^oqZh}kZNnGGE,3 A6[9zu^\ 4cO}W| <=z]hl8[62ݾ'}0œ>C`{^*}%Ǿ{dHdXyC>HM_&Q+x;@eUI;R*YkEyԋF囮7]`w9Ai`G~@ꢄ1 9T #,~<4)1\w-46e(RJa .9;L/UXJ}_Hj %=UV7XB2ގ7-Vgzk &eyu%ZRqɧ7}l7Av:ڃd8QlObK y \u `FU"FZapځȜw d0|@$5LhrhZE%':!>k--yP31t]w)Wr,=%;fg@iԌ3?]]Bp3fv1NCWn=@Oz]V39o_tNܔjOb M>9D̳`X SgdF||:ǭ/'P4_ _̲ ,_E[}еc> tdαqHl9 PFUs}_Vrl/J >W @Zz1R'Ȩc:*pSD*}-,a H*o|L|o.tZV2!71A8QjONo6h+˙8Q-t ;ʛa+5X`)C+:RF%XuHuG [7bXR ?R3yW?!W2.+ɾþ;F~eXvN |@+YE 2W/!bd8gv0  FˢKeɩ kZ %va k361,zԱ /G}3% r:EcЎw"Bn1>6"Pe2 v&9o Y"AWm "( E>IJ'K0w6lRFuIU@s-?{1Be?FTV| o/Ï}D\W:MN;dvk3S1R|[;pB(>0(~U MU\lJ\i(mxWDPjq+x6$hr-v Ɗƺp Mt}.>c/*}n2> CsIU{V[)2"8Air>eu,< ˋ*&`~h 䂱-`o!B@T\ ޳i0HLQ\@z^Ԡw1~M[;=·J{-kX!G>=[A~%舌zQl27b>ע^!#=[ڥ%wThԋ w~VBT΋O&IiZ8pru 5;KԴtP%+4E"@->5FOfπ @D~`0Q~3;:O'Zyd2??r`Hn8N>-VKMa:W0JB<-{jTcl7 4c7P/;K֎N() =0 Jx=; ʖ;<} P:.Yݠ [MZ.5ɎGqnV6u4I_=ypW&|]ے 0;K? k CϿU?51:I rEat#5Khylz$`,}CNŰn+eTr %!I@[GB ,)=깶 S ﱳKF&lO s-< bLBg8 hzԓ1iPHHpgP 9B}TpP;9@4ʽuow)4Rc:lw{Ԛk뺉?rM{PB4=I,QI̓H5 ǟX!&(eE`E~>C{?IqPcѥ?p8y9_T>2)K+֤xI0:]CbLEq};-%ԣ6I`s1?J+= O>Xȉ-dfGAzv{XZX!2 i;-,YS+ؼ2]qƪ;3F ۻO&f3;Ǝ][@M' mYHzC_& KY3!FeUm+O|r܁h8zU\ᜯPBTMﺾydvpl18K@4]l* "dɩ!0meb҆?Ű87m bQ>\گ_~A}\ DtD*rKCb E C=JhHޮ(=!U0UPk\mS]iLP⮀z_qooڥ2ދ:WB@t(MP3Ї%XL=|ؗ|e N=Ŭ\R=2a;odyZWzwGF:V{vA2'v!w7˲/x4R@W_gTw.!y~O@$| c^u/! Ϝj(g]^$NnUOMUԢMb-ʡs(VDmUvYֱlR ߵ ]MQɥ]bR%4)!&7 %l\.[(m5[/^"s}SG3(mUZz+41Q@CvJ ݍX D >^ +UYʼ ҇u.K5okNydRD-39l^`;c:,ð&APX8~ͫ 5(>d<`L(&[u;!^N4+}ͪ!Q!D2z C1':(M:@ߥލưAH9eSxktPgX*L}>Bm?B  HF+ O { Z0à◯auM]0bg!$ZLELMGAsTěaO$x)(EOvac3kt'|w~WB w/}d/|m5IAdd՜}Χf.xnTz, ]foYTN ɩ7 Mְp!XL1d[]E3͍&6C9nM>Z5pkVItEӥO>~PuKc{!W(g6@_%P$=/%jÖrS7ֱqyaJ]?`j^gtY̫Xak1-PP4%7\.a΀޶E Y@Ttx"xhPO4fKK @ Kԝ$IդS[]_KZ,woNX*LF{gԲ,qzσAFiFi-?֝O( >Pm`N7`dmw:kp2 ._+ꍢ=뉑 uıC':2[AaWzprbjnpaP>-@* C"]v$Eek%uov::u6L*Jzo%%擮Am>(^yCSGbVP$eY1cX{︈l^q>N[CTю~ϣ? !!j]'荽woQ_8aL'kpcŰCc]+޴P\4s/ g"{me:c鍥aa&c9ƀ G~{!ֳ**9klWhdOΰ;`8P!yDҖWXzt&[YׁEȤڂq[C','^{Mp٤Ӡ͞%d <yWa=? 4f` wW0`U0L}/Lc jfnE:z-4/O_,+_>?ӗ&uHzrW90)~99ȕA*B7/ycSZs`Y~Ģb}+ W$^tjAY`ͯ=DVw_ X/:5?Z -mJn&Ek!BCEPJ\-,@2PcAQp*Z~R A A{JZ 8ʣO9"Z&s @*AD0t&IYEn:m*+ 2@*nu#s눎q㔻ej& BXiz2vӔ7D-@/+o MtIMM_-T.,үc;K~O\)TsaϪxɞ1ʲ&K3HGv. XzBa~Qm%2lmkʭ@5O~57SKkp;Ngz/b޾ʠ^BW\]x^~{3M|G/*2 p/rGo% RMcx+z:Q <>`Yo>wm@n;o߾e`ţG*ژ+(g _|X^Eqm+#KJ hG3F?+^/6rflcRDR9樥F+|j: B*E[L*>8:r Y :pýw8Jipԡ}Y]`MQź[B@Zżw2 N`@;1 Kω:lN-EY^{14S\Q+쌝W@v!~ wHXPo?ذ !`V[*q ²;h'T1vBԷ}uCz_?/zW^iݘHN->,d#vӀyCtvӏ:G d6L寃a00QpEڱ]ھ,e |o7"ދPlm0E$,97(7_i_s{1!],iXY:/@Sş~ ,.Ko[3X9v1fo^ҳ|d)i G~$,[Q L @c~y5=l-yc2q/Mp``zƲŷ`0fGk(;a8GǨRlo\En\IzB*4ܰtp7 k=t }p,CO~ވ?^];wd <81s,?yC87t8{> g|>+ ceJMf͞:Hw䉸v]j|u_reg&#=#x[n\ 棟}n}änVzWz5;×BL\cFWP0}n-ϣ^L5.}˫0u/ǛEFm웏vVZ}y;zv%`Yo|0~p9LHXh)5mtɱzvj;8e>}aRyԼ ཎʙ=<Ns^}6f HO0Z@F(5 kx"ЮIoAd$ۨSBǘjJNDlTޅr!| ^0Q.@m==DzV twr"4I ب(]9!iPG@}ml#9(8ᇭI/NxX.#ݞ;z)l+ū}sC~׾|^m2^9#xq- |k}N(bK x||/y|~n|}"8v!\?X`2$>Xz! |}/ h" Koy^Yg6mߟå߹"FBx3xC9ۃ ]7@M+Ȼ2G?% opRޅ\뱪L^5Y6 z X,YzBw `tdPY[||Ɏ"EVl;/uAGKKPj!DGlZ~%3c,P`3VP/ENB=6;NаtƽܭWznשiHl̑]ϢP^9 $Szul\Ԙt]N,bSn,=!T3u݋(P\Xg{9l^H#s-rur+Q‰Ad7Xv|_  ~J L ґyobHZ琜5K F4(5[{4X8Qw Dq^=P0;29UuIHHHBKAA qete\gtEg>?eEE ; !d:tݗ:ιnw soթs=wޅA15rzB ^k>ɱ B`UV@ JiR8 } KBLʇ\Gʸ䲛0qq 2!Vwno |`>,g7qܜs=eLCfyT ࣟތj͌@).}ov1u!+𙏿$Pmϕ?TxUZ?*ň܋zÌg(M fDq )581ߚT+0i}НԪV}s`P ޙdV'Dd匉Xz%{VɎ̣PRQ jQ%2CET P#KCy.תaQ>nJ0Ű1JT`]“Жk9"L]m! 6'(iʎQ:dNJ(NaP^Nlox,“gp|hŰ@!!K?bƫYɪ[^.b8w􊭞{f|2-Q-&[TEp JjV]I8 b `њ"6D2Ѩ7XN0 MkW4rթ凗ۮŋΌ^ d{/x103kݎb>}M7l3**nc ~j``t)g;P-.hVqN2G"UBܠF4=n˹̇rZ1VIQ/N rh)LC3dQc%U]UfTL%a ͢tbRVN`2$*Ac8Σ4;ƹ,?%3؆ϝtݵ rʳ-}m axSKdm9viF3IVI窨mNīDjͯU$sx<ʾ1O-D q׺8} 8OF0wznnaL_dp-.KQc*sIm`xC2ּt:[`0 (u6u[w*cĊw;&TYVD,=;^\a/@}=!}Ft-|/EVr,3OiAO^-fқK&سq)AAko?b34M`_܍sS@ Ctrg2Q};P߀_fnsOdOh/]}#_'v{x_nZ"Ni1@nS0=S5{6Y%{|JwRod2_߽R ̡^r0݃cHK,}F 2jm?̹EOPޚG?K@ u:86ol@'tZa Da` k>a/FQ ΀Q0Z}vOavbaj`|Axꔶ]@*Wm֡R ģo@ zԸ"JӃGfiuYNw"=XE5Y<& u/݇,CWwN5iqZ]fC(X%&ӏг YrW؍>f-e}755T$BoOcr{[pd(&<-ȝc将L3' =KXz+`l 󸈥̆KOP (̅0 P4+N^%FkZci3r(^C)òLӊU]8y8X}[͂T ~~,x/ٯlvPE-AъhTǑ 1 >g|l^fp WaŒ#7 N(cq|t%V:^ `)[o2rEww}S8.vH +}CǠ%+(c ǂ;ZY%)1МEV>ndԊq,Ufc5U4i Ob~r3vfN˶>CƑb:V nRT L<hPis{ueKXzA}|C Zq?f'2?ҋꕔ -Σ0<ɐd 0ښDeJX6=l8%Mc+g1s0T@K8xS"/ kGqXu4l 35T;=2^Dh60b]=eAjժO 6P+") A: f ̻X^M0u B9 2'ea.$'~_MXz_r,A+eZmH0oH<S>-AMbc."pp6 5 l?`~­ 8n`<>+Ǟ<ف'Ш,:FCBV۔gB8d#L UdI1tWuGzA *,p+EbǗm3\E2;N qԢώP/w.;C!IJ4KL0`N )BaՊA-::̮9ʑ0-,0rt4 FWQkץh Aݳ#43q%up(E2Xz%C箣?5_񴎃Մ4]XC>dO#x}QwOam#"+DC5 G%cr$v0P16ɚjh(ؽɗ`dߘy6ĕ@30gm'ȩXrdX:dWT8 PK< 9IَߠT'3\W#UȮJzq%P%pA93c7JGPSߌڱ-J!nhXar]QXv0W(7B5 &~~%D3lôʰ(_ƚc`@9p#[:[s#pț<9c{3@)CcX=cu]G VL$ǜ R,O0k)pLo9@ִ*EYF))J9 aG:LjjF1Pf 8d6-ӠB9as `cАfۺK7Rͱ)C{ J8Ƶ:b@b A|1$ CC}}>&&4ӄ,QppX^{`PQ0{msBuX8 \֐7HNE5OfDsNs@S4nyjK0֞X2"XgBî$1s p-:! /sg K ۛ&6?;oBDU1}*b+57S}7p}޺05Ўm2D!kIa%a[+K*@@(PHa9Y~ tL(0a 4yr@έ`GsX]n 1_:)K(\t$^+@KA3dǡdìL,O,OU`Bm`C!y.up%""(ŠEHe̎CI/I ^k0И~ق-+GoX A8j G(蟐=C7},7{PJT fsnr^CCrrˡ M/o,M,Fc8ppLfXs|54kebpk, *sBׄ0D); Yk ]w{'H`Z"Xwx5w[6NNSg;Xz1ZcN֫7@Aj+>sXm >6(ž1NثR {/'. j,\G>67nHQ]9_C 7u;3 ecXk0}4v[! Oge-[c:ĊԊ7gl[ J Rġ ax40sM*2YKZ 600Rx8W@cS鄄B/3~Ǯ3B櫍0fj•&MOKsR#(ow \jQx(o0b}ylf4ھPw zf%ץ0&r<Cl0/7U/Lྪygwp SM<Xd ** vnWYe6zr~(u%Ar͘i_*! ܲ]F1 Z!f Wȟ^.v:oa R㍣-'O*m;yۇtȼqy5: U90sf˸eg (Ez}Ɓ!6`6͎X#bi VJ>N9)⿑pD.B5 qE2w0c/{?r&H3K-$1j :uYjݯ*62 y1f~})X~g{wȖFGoX̀s`7BIb &SVp)# ~vop ׅnd1fg7VϙIj㘍q Lg3Ŝh$v\}cuY W]A`lAKޗ k^$t$®| {*=4\}dߦLM%5o!̯cߜXu3)e- =$NT< -03%AI&@{ݝɂwp) $\kݚxZ3aw0tc6jz;]ڊa;.tVJ~zZǺ2nmov9A,YHy-߸6"ЧPMưtmc7(<9Fѱ%%SFb6} q T\cC~bMé']~XW8&zԪ{b#s<696nHU EKܒAⳗ00 $ 5'A5u 0]uඓ#QNF.nNU#LN8:ehd=NTq7y hv9Hj 4zjX IDAT ۏY:޵[U90L|"Qr@Ͷ7enwޫ)Cv40 ⯁$r(o`lYR[9sϡ:JO~$CrPAK/ 21q0> m6W޽Aܯ.F7q$b뺘g?=lDr"5x+o& 6.ЯhCLZ !h,g,G!Pk #<ʬdD.Kˋp0`Pm7I|u-g ˰YzDid#&,CV#X<\dbE:0yXm[53)$GK o2mqw}(n "`0B>[gZSaa' w'XgVW I.v5`w{ 4f%?/Mxyf/E'K6e}s?Z p ^R4²!hYY^ߑq,w-'ۯoc+%  *FXcwA#- cAѴ4(l*Ö1@ Vk%,U^ٳbIATw ZYy%!N;36g٫Ãğ5 ɹŌՄ0|<6eU3I*/v?yuj(0mdݟ yjkieP3_.0w.|A3x+i;L/Oq,W\^ݞkqbpj00u3{U0}MAK'Њ/v!=XNWn u˺ xDzJ, jbZWof4|ǽ k.S؋nUΐ:#V@5P5mɅ`<嗀'H< F'Nh^ C<0D j't;Arԧa!ЙM1Q2ZNӑZQ\eH XT=0 ,G **(4W!@b>^:"$׾ nUHab6HGQ}4Dr[AO17-#2SޘCbՕH32xuImBbeh Xqd}+^ m0fJv5ׂfhK.Xa/@%B9 'Ih^P 5.: 50_r.cf 4lcTa|ou\㔊5<;+My/2]VXK/BGO6X`i9D +΄}U71&_* r%0Htfn"C3ɭj#j ߑ㓧?2')֟m#MSJiH0>ml p1t.6gMy/{EEkm|U9#}[S,Ca pfù2W" K7G۽ VyWP5ЏM[*H%( ρ6 h%/ +!Q ]@Xa?rt3Jy-ѳ:c cqQP}ڪ+,82 :DI`AGCRZ˭9 ԦOf2h<*y]5@]|!E}O5Wce'X~Bh>Ʈ@Է_JjP˚k8x8gH%pڳҒȾQM~Hv q<.C*0tC$7SHgGQz #K/Tb5?!V:`8N2yxN a^yD3{lS ُ]Vؒ[b.ruOQQ& NTm?U *\ ` ܛM>%W_QHXSĸÇ<6vB,tUI<:>dx&K/tJpF +QdM>aέ}bGU7$Q5=bi ya p'ٳkm 7u4B{ e\nGͧa'Q[zڅ.N888_أNeW&u_/b+aܲCv]?RcVvpBbwotk2} E#s0Z٭H$5; Q(}5?? YL֎pǥi(q)򷜃WcPO g7`''Cڲaȑ[m|??<6_wA;߈vged/]Ty!kQbwl`U0rX/ηO\cs9G9u9o}O/R*$ü;6[cI(9 tgHLKE|_"앑J&F-42e=$rkcfqUlY9˨>/\ƪǝW=Be{NU A+Y^Bte2oUqMw>qJaZ_wb\wUXNAp;Vi6֩rJţUE ~pp":MR'V5!`c==Us%HH2{9bU4t HCb?{t‹?,4t) $]c.<@ڷX sn7h5Z:$1>y?OQ4LНi!xx H"b1sުkaL ܚ)^&O-;h`)J0<ʼGw|^Bc/,Aʭv(aج|G?gkbw̿Q(? %?V1 0%ʂ3eWÜs9;ƷሺJ7% =>#CK~ZF8Mq L`_f2J[Y[[vY(iK+]vS*Ak1ޡA"ۼrߌ[G9Kgʗ*2+_!2W' hɤCo xm`;㷆<8Sa #}vR`ק ';ԑNK:w9[_8EX^ey̯Z.1@uЀ[GhE}>[8-mrc'ʃ! rsfboҹp((çZ!7w70x41PvekAR ga+z dsmc"Jp/['eDyаTGؘy \F ̹mM#UX\*og:!s='m7EbttŮ)}BL}?FF(H uovd7C/:.wٟN9-(Xeq{4ygmeJW:&3 #8uRRNm!7tDeEsAKV<\A3~&q7ncE 3nލEOGsJA٨R%~`zҏB`+̿|\ͯL6l:N\ 5i4!Of2 eL(g8$hf)W9ߋB2tJ ̸F ^]n]?ڷhYh'8bX ͭॿYPҙ'}j6E+Qp[uUq%׎C?x;\kC]&l34 "&”9hհ7d VLE '`C u\8Xp-Xڛ?ï6}Wh2p|dvNZ |Vb(vcSDVIQ;4And3~y:m)Xd_ &֗P7"[+n>Ql߀h!M 7~w)K6dFb1G}65.IӯI}† }#+޼G/:&$> #G\. X߅ҽoG2)xֹs-5&&@W],VZɝ4~ :8R뮃vҥ j6*"M0?uӧ:u`ux c?+.kHRͿZklP V\7A?ѶKVVv{f)ɗNFރm.K7h)P5+oCw20 &#=t޽όjoNӯxw yQ'yI!nhd͢p6U-jP!DiK/՗+[jsTқ(O4t̋Bql#i'Z QcaK:wOk…:vyH߫<\3 ݡA΁ړXLHﱌ=`Ɠ?V]ȩMO `Z0<ѳ@T'clڲF(/l}f~;Xu ,)Zdӝ7#>30 {p\,reB95y1AmJ#g Gcm8󖳴`Y+!}l 86w@]b6E?|/Xysex=2HXrN.>O{jvaX3%XWK֭_藡pbC|T\,= ʈp>̉LQx @7ՁA6B biou0N]uLȞm0%Z4Qg/8ntz˹F7;[15=Cfe9X]ӾX_? Lde=Sl'`K:D]}M.8, -[f$ {܍Q4*GT}"$V_87c!w=f}Zu o[} wڼ nE/ s7.y)T[ qX k2 ];2Xr/{^C[j( @C"R> 6nBb5HmgzYЖ]Av۷sww +qd3f'"HqpƁ_[+> V9j1ڂ(eJ"N+Qn6h2͢LVQ1۟sqC-0l h`Pw1/cjTvP<}O]T$A[̜W=l&AUZU.J Q,.ZCZ"o,ҁRR>(L8TfsJ iİĭZRsisz}wQl*sfz]ƒ얜ޣ Y*rb_NJ$\a ͮ@BxyM sP{m`^2ƑqTEmۿW#j-#oG@[z"kKQ0?mE0 ޫ| ƱGd[ f]E%<֦#IsЏlA?<˹0lo{GmC--ÿGl20E(S*ȣЏlyYkcgNuыX}5Xu?lwsPa}ֺZi֛"\OP~M/A}P;tgy3gn;hG> @;u &G|܁_VqcЏVٴ>y<ٻil8>[% ݉kވlnfWytה$gls'G:4&_2.3EO W<}1X{b{ҋXzlbzI 0E=ީv5+9V{#eR_;nWWE_e. -"L| e(^Qa8רb9 uz%"ϫ+ #΃H5sbE*QPpmq{(B 㲶jf.F9+bV%V܄=oB} )hI"h1-wx'~J2F晷s/kkSv}_XU' )޼&)~`7 ?UPy3}fSnW^v{4Lyz%uPў5@-bV.9^m8G:AK5k߀10}F*, Pu%;չ^UEu! tEgz39~8s0{[`^Q"ͳ1Oy2GwYGWHy\i|%u^[-QCEeD(WA^sY{ٖsK\}Gq NX@BŨ,=@cID!ޡ ˣbXu`r8i⮿݆0dQx%) *mcPU=28%.e 5ѬRݡ1/XȣL<Uh <}z.N+>XzQ Lw e zxƁe50>WGj8VeKmV1Ý! ̻%˜,m9 ،;}q|y[fP6g $q\V ϭ:-UP0:4Y)jOdFlᳳ7UApoiMrCl@~I1}e$9P#IbQ(Dٗ&Q] K/9w:rnkl)`p&^ ;"!Nt^>:π1rآ̅X5w n[Y,"PM5}$)!{6lNJt]5&҃B`$+"IĭpNebmIDATJƽĬX{r~yC[15~57&D.Ў(+ 'KI QD1^VzhP"&ثt1'+D}ʇO jZقd}:sd`:cy.IIlW]Z @aifaO' = [`gwL֧"YL'3O%K–Xm4g}^ QÞdk}HC :>'*6& exTp91#]UbTjpAD\˪ FfoeG1N*K\:j/H1ħe,'K6"ʡ(KMͦo,LIENDB`prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/images/secure.png000066400000000000000000000027661256416760300316240ustar00rootroot00000000000000PNG  IHDR\sRGBbKGD pHYs B(xtIME (8C`vIDAT8˝{lS9>>vl'CC "PKUMQM[zRS)KE)zY׎IvLZF X4\20rsq8s|I|hJ_>}n pJx,mK9uBR[]Gv7kDp<}+T/aQ8s,|Xtkr#FKkxys26_~奷˳ hjGF hMag1F1|̿Wi~QbŦUasw՗Hjg[Z mhT*͢Xp:iZ2\}7֖h3lT[>F/.ƑٽrFN>c&N8Z_qI-| 43qlEk}Lr'3Z8|/nyzU?T 1p8:hH-͝ Ov4tswĐe$E HjUd2(ĔI dbۘB #֙j%' O.k\~Bp:]\ݹQOJ6C:;/x/x*tyydg5+U+g܎|(@Cjα䧓Z0]^ˮl[UJ̒^>Z=< Bsg^F#qEYCmxgg&I.*Zsh\pƞ'BTm(ۖO3]Bl*F` LŦ?tȲ-}e.զ IF'Mc f 7SQ0MYI$R #<0¶mebQeEQT,-@utCG@݅xō׻k:!KUfbX0 `iM‘}R,/ijV}J*b.A}>Bhԏ{S Z{7`t»CdIB]]ܝJk+W*ZBCK$%pqf?}>9CwŞL``(@ۍ-a\}f]two0wfLF#SI.(PF8 Ci)*á+wʤ'-_g-VՆ(/a(>b=ȓa# HW&WF;u,ӟ{dc{DfWZ|nO~9 Prosody Webadmin

Incoming S2S connections:

    Outgoing S2S connections:

      Client connections:

        prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/js/000077500000000000000000000000001256416760300267645ustar00rootroot00000000000000prosody-modules-0.0~hg20150813.12ac88940fe3/mod_admin_web/admin_web/www_files/js/main.js000066400000000000000000000244201256416760300302500ustar00rootroot00000000000000var BOSH_SERVICE = '/http-bind/'; var show_log = false; Strophe.addNamespace('C2SSTREAM', 'http://prosody.im/streams/c2s'); Strophe.addNamespace('S2SSTREAM', 'http://prosody.im/streams/s2s'); Strophe.addNamespace('ADMINSUB', 'http://prosody.im/adminsub'); Strophe.addNamespace('CAPS', 'http://jabber.org/protocol/caps'); var localJID = null; var connection = null; var adminsubHost = null; var adhocControl = new Adhoc('#adhocDisplay', function() {}); function log(msg) { var entry = $('
        ').append(document.createTextNode(msg)); $('#log').append(entry); } function rawInput(data) { log('RECV: ' + data); } function rawOutput(data) { log('SENT: ' + data); } function _cbNewS2S(e) { var items, item, entry, tmp, retract, id, jid, infos, info, metadata; items = e.getElementsByTagName('item'); for (i = 0; i < items.length; i++) { item = items[i]; id = item.attributes.getNamedItem('id').value; jid = item.getElementsByTagName('session')[0].attributes.getNamedItem('jid').value; infos = item.getElementsByTagName('info'); entry = $('
      • ' + jid + '
      • '); if (tmp = item.getElementsByTagName('encrypted')[0]) { if (tmp.getElementsByTagName('valid')[0]) { entry.append(' (secure) (encrypted)'); } else { entry.append(' (encrypted)'); } } if (item.getElementsByTagName('compressed')[0]) { entry.append(' (compressed)'); } metadata = $('